Version Description
- 20 August 2019 =
- Added setting for mobile specific margin.
- Prevent Welcome Page Redirect During Bulk Install and TGMPA
- Added support for password settings field.
- Layout Block: Add filter to control whether Add Layout Block button is shown or not.
- Fixed issue with widget duplication after moving a widget.
- Fixed Read More Custom Text issue.
Download this release
Release Info
Developer | gpriday |
Plugin | Page Builder by SiteOrigin |
Version | 2.10.7 |
Comparing to | |
See all releases |
Code changes from version 2.10.6 to 2.10.7
- compat/js/siteorigin-panels-layout-block.js +351 -351
- compat/js/siteorigin-panels-layout-block.min.js +1 -1
- compat/layout-block.php +114 -114
- compat/pb-icon.svg +0 -1
- compat/pb-icon_white.svg +0 -1
- css/front.css +0 -47
- css/front.min.css +0 -1
- css/icons/readme.txt +0 -5
- css/images/pb-icon_white.svg +1 -1
- css/mixins.less +0 -173
- inc/admin-dashboard.php +117 -117
- inc/admin-layouts.php +494 -494
- inc/admin-tutorials.php +0 -50
- inc/admin-widget-dialog.php +193 -193
- inc/admin.php +1485 -1485
- inc/cache-renderer.php +37 -37
- inc/css-builder.php +256 -256
- inc/functions.php +105 -105
- inc/live-editor.php +84 -84
- inc/renderer-legacy.php +168 -168
- inc/renderer.php +872 -864
- inc/revisions.php +107 -107
- inc/settings.php +668 -662
- inc/sidebars-emulator.php +224 -224
- inc/styles-admin.php +517 -513
- inc/styles.php +750 -713
- inc/widget-shortcode.php +122 -122
- inc/widgets/layout.php +134 -134
- inc/widgets/post-loop-helper.php +100 -100
- inc/widgets/post-loop.php +422 -422
- js/siteorigin-panels-2106.min.js +0 -1
- js/{siteorigin-panels-2106.js → siteorigin-panels-2107.js} +6621 -6619
- js/siteorigin-panels-2107.min.js +1 -0
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 |
-
jQuery(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(jQuery.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 |
-
jQuery(document).off('mouseup', rowOrWidgetMouseUp);
|
123 |
-
|
124 |
-
if (isFunction(_this2.props.onRowOrWidgetMouseUp)) {
|
125 |
-
_this2.props.onRowOrWidgetMouseUp();
|
126 |
-
}
|
127 |
-
};
|
128 |
-
|
129 |
-
jQuery(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 |
-
jQuery(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 = jQuery.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 |
-
jQuery.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 (jQuery) {
|
313 |
-
if (soPanelsBlockEditorAdmin.showAddButton) {
|
314 |
-
jQuery(function () {
|
315 |
-
setTimeout(function () {
|
316 |
-
var editorDispatch = wp.data.dispatch('core/editor');
|
317 |
-
var editorSelect = wp.data.select('core/editor');
|
318 |
-
var tmpl = jQuery('#siteorigin-panels-add-layout-block-button').html();
|
319 |
-
var $addButton = jQuery(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 |
+
jQuery(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(jQuery.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 |
+
jQuery(document).off('mouseup', rowOrWidgetMouseUp);
|
123 |
+
|
124 |
+
if (isFunction(_this2.props.onRowOrWidgetMouseUp)) {
|
125 |
+
_this2.props.onRowOrWidgetMouseUp();
|
126 |
+
}
|
127 |
+
};
|
128 |
+
|
129 |
+
jQuery(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 |
+
jQuery(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 = jQuery.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 |
+
jQuery.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 (jQuery) {
|
313 |
+
if (soPanelsBlockEditorAdmin.showAddButton) {
|
314 |
+
jQuery(function () {
|
315 |
+
setTimeout(function () {
|
316 |
+
var editorDispatch = wp.data.dispatch('core/editor');
|
317 |
+
var editorSelect = wp.data.select('core/editor');
|
318 |
+
var tmpl = jQuery('#siteorigin-panels-add-layout-block-button').html();
|
319 |
+
var $addButton = jQuery(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);
|
compat/js/siteorigin-panels-layout-block.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
"use strict";function _typeof(e){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}function _createClass(e,t,n){return t&&_defineProperties(e.prototype,t),n&&_defineProperties(e,n),e}function _possibleConstructorReturn(e,t){return!t||"object"!==_typeof(t)&&"function"!=typeof t?_assertThisInitialized(e):t}function _assertThisInitialized(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function _getPrototypeOf(e){return(_getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&_setPrototypeOf(e,t)}function _setPrototypeOf(e,t){return(_setPrototypeOf=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}var _lodash=lodash,isEqual=_lodash.isEqual,debounce=_lodash.debounce,isEmpty=_lodash.isEmpty,isFunction=_lodash.isFunction,registerBlockType=wp.blocks.registerBlockType,_wp$element=wp.element,Component=_wp$element.Component,Fragment=_wp$element.Fragment,RawHTML=_wp$element.RawHTML,createRef=_wp$element.createRef,BlockControls=wp.editor.BlockControls,_wp$components=wp.components,Toolbar=_wp$components.Toolbar,IconButton=_wp$components.IconButton,Spinner=_wp$components.Spinner,__=wp.i18n.__,_window=window,soPanelsBlockEditorAdmin=_window.soPanelsBlockEditorAdmin,SiteOriginPanelsLayoutBlock=function(
|
1 |
+
"use strict";function _typeof(e){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}function _createClass(e,t,n){return t&&_defineProperties(e.prototype,t),n&&_defineProperties(e,n),e}function _possibleConstructorReturn(e,t){return!t||"object"!==_typeof(t)&&"function"!=typeof t?_assertThisInitialized(e):t}function _assertThisInitialized(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function _getPrototypeOf(e){return(_getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&_setPrototypeOf(e,t)}function _setPrototypeOf(e,t){return(_setPrototypeOf=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}var _lodash=lodash,isEqual=_lodash.isEqual,debounce=_lodash.debounce,isEmpty=_lodash.isEmpty,isFunction=_lodash.isFunction,registerBlockType=wp.blocks.registerBlockType,_wp$element=wp.element,Component=_wp$element.Component,Fragment=_wp$element.Fragment,RawHTML=_wp$element.RawHTML,createRef=_wp$element.createRef,BlockControls=wp.editor.BlockControls,_wp$components=wp.components,Toolbar=_wp$components.Toolbar,IconButton=_wp$components.IconButton,Spinner=_wp$components.Spinner,__=wp.i18n.__,_window=window,soPanelsBlockEditorAdmin=_window.soPanelsBlockEditorAdmin,SiteOriginPanelsLayoutBlock=function(){function i(e){var t;_classCallCheck(this,i),t=_possibleConstructorReturn(this,_getPrototypeOf(i).call(this,e));var n="edit"===soPanelsBlockEditorAdmin.defaultMode||isEmpty(e.panelsData);return t.state={editing:n,loadingPreview:!n,previewHtml:""},t.panelsContainer=createRef(),t.previewContainer=createRef(),t.panelsInitialized=!1,t.previewInitialized=!1,t}return _inherits(i,Component),_createClass(i,[{key:"componentDidMount",value:function(){this.isStillMounted=!0,this.state.editing?this.setupPanels():this.state.editing||this.previewInitialized||(this.fetchPreview(this.props),this.fetchPreview=debounce(this.fetchPreview,500))}},{key:"componentWillUnmount",value:function(){this.isStillMounted=!1,this.builderView&&this.builderView.off("content_change")}},{key:"componentDidUpdate",value:function(e){this.state.editing&&!this.panelsInitialized?this.setupPanels():this.state.loadingPreview?this.fetchPreview(this.props):!this.previewInitialized&&this.previewContainer.current&&(jQuery(document).trigger("panels_setup_preview"),this.previewInitialized=!0)}},{key:"setupPanels",value:function(){var t=this,e=jQuery(this.panelsContainer.current),n=new panels.model.builder;this.builderView=new panels.view.builder({model:n,config:{editorType:"standalone"}});function i(){isFunction(t.props.onRowOrWidgetMouseDown)&&t.props.onRowOrWidgetMouseDown(),jQuery(document).on("mouseup",function e(){jQuery(document).off("mouseup",e),isFunction(t.props.onRowOrWidgetMouseUp)&&t.props.onRowOrWidgetMouseUp()})}var o=JSON.parse(JSON.stringify(jQuery.extend({},this.props.panelsData)));this.builderView.on("row_added",function(){t.builderView.$(".so-row-move").off("mousedown",i),t.builderView.$(".so-row-move").on("mousedown",i),t.builderView.$(".so-widget").off("mousedown",i),t.builderView.$(".so-widget").on("mousedown",i)}),this.builderView.on("widget_added",function(){t.builderView.$(".so-widget").off("mousedown",i),t.builderView.$(".so-widget").on("mousedown",i)}),this.builderView.render().attach({container:e}).setData(o),this.builderView.trigger("builder_resize"),this.builderView.on("content_change",function(){var e=t.builderView.getData();t.panelsDataChanged=!isEqual(o,e),t.panelsDataChanged&&(t.props.onContentChange&&isFunction(t.props.onContentChange)&&t.props.onContentChange(e),t.setState({loadingPreview:!0,previewHtml:""}))}),jQuery(document).trigger("panels_setup",this.builderView),this.panelsInitialized=!0}},{key:"fetchPreview",value:function(e){var t=this;if(this.isStillMounted){this.previewInitialized=!1;var n=this.currentFetchRequest=jQuery.post({url:soPanelsBlockEditorAdmin.previewUrl,data:{action:"so_panels_layout_block_preview",panelsData:JSON.stringify(e.panelsData)}}).then(function(e){t.isStillMounted&&n===t.currentFetchRequest&&e&&t.setState({previewHtml:e,loadingPreview:!1})});return n}}},{key:"render",value:function(){var e=this,t=this.props.panelsData;if(this.state.editing)return React.createElement(Fragment,null,React.createElement(BlockControls,null,React.createElement(Toolbar,null,React.createElement(IconButton,{icon:"visibility",className:"components-icon-button components-toolbar__control",label:__("Preview layout.","siteorigin-panels"),onClick:function(){t&&e.setState({editing:!1})}}))),React.createElement("div",{key:"layout-block",className:"siteorigin-panels-layout-block-container",ref:this.panelsContainer}));var n=this.state.loadingPreview;return React.createElement(Fragment,null,React.createElement(BlockControls,null,React.createElement(Toolbar,null,React.createElement(IconButton,{icon:"edit",className:"components-icon-button components-toolbar__control",label:__("Edit layout.","siteorigin-panels"),onClick:function(){e.panelsInitialized=!1,e.setState({editing:!0})}}))),React.createElement("div",{key:"preview",className:"so-panels-block-layout-preview-container"},n?React.createElement("div",{className:"so-panels-spinner-container"},React.createElement("span",null,React.createElement(Spinner,null))):React.createElement("div",{className:"so-panels-raw-html-container",ref:this.previewContainer},React.createElement(RawHTML,null,this.state.previewHtml))))}}]),i}();registerBlockType("siteorigin-panels/layout-block",{title:__("SiteOrigin Layout","siteorigin-panels"),description:__("Build a layout using SiteOrigin's Page Builder.","siteorigin-panels"),icon:function(){return React.createElement("span",{className:"siteorigin-panels-block-icon"})},category:"layout",keywords:["page builder","column,grid","panel"],supports:{html:!1},attributes:{panelsData:{type:"object"}},edit:function(e){var t=e.attributes,n=e.setAttributes,i=e.toggleSelection;return React.createElement(SiteOriginPanelsLayoutBlock,{panelsData:t.panelsData,onContentChange:function(e){_.isEmpty(e.widgets)||jQuery.post(soPanelsBlockEditorAdmin.sanitizeUrl,{action:"so_panels_layout_block_sanitize",panelsData:JSON.stringify(e)},function(e){""!==e&&n({panelsData:e})})},onRowOrWidgetMouseDown:function(){i(!1)},onRowOrWidgetMouseUp:function(){i(!0)}})},save:function(){return null}}),function(r){soPanelsBlockEditorAdmin.showAddButton&&r(function(){setTimeout(function(){var n=wp.data.dispatch("core/editor"),i=wp.data.select("core/editor"),e=r("#siteorigin-panels-add-layout-block-button").html(),t=r(e).insertAfter(".editor-writing-flow > div:first");t.on("click",function(){var e=wp.blocks.createBlock("siteorigin-panels/layout-block",{});if(i.isEditedPostEmpty()){var t=i.getBlocks();t.length?n.replaceBlock(t[0].clientId,e):n.insertBlock(e)}else n.insertBlock(e)});function o(){wp.data.select("core/editor").isEditedPostEmpty()?t.show():t.hide()}wp.data.subscribe(o),o()},100)})}(jQuery);
|
compat/layout-block.php
CHANGED
@@ -1,114 +1,114 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class SiteOrigin_Panels_Compat_Layout_Block {
|
4 |
-
|
5 |
-
const BLOCK_NAME = 'siteorigin-panels/layout-block';
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Get the singleton instance
|
9 |
-
*
|
10 |
-
* @return SiteOrigin_Panels_Compat_Layout_Block
|
11 |
-
*/
|
12 |
-
public static function single() {
|
13 |
-
static $single;
|
14 |
-
|
15 |
-
return empty( $single ) ? $single = new self() : $single;
|
16 |
-
}
|
17 |
-
|
18 |
-
public function __construct() {
|
19 |
-
add_action( 'init', array( $this, 'register_layout_block' ) );
|
20 |
-
// This action is slightly later than `enqueue_block_editor_assets`,
|
21 |
-
// which we need to use to ensure our templates are loaded at the right time.
|
22 |
-
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_layout_block_editor_assets' ) );
|
23 |
-
}
|
24 |
-
|
25 |
-
public function register_layout_block() {
|
26 |
-
register_block_type( self::BLOCK_NAME, array(
|
27 |
-
'render_callback' => array( $this, 'render_layout_block' ),
|
28 |
-
) );
|
29 |
-
}
|
30 |
-
|
31 |
-
public function enqueue_layout_block_editor_assets() {
|
32 |
-
if ( SiteOrigin_Panels_Admin::is_block_editor() ) {
|
33 |
-
$panels_admin = SiteOrigin_Panels_Admin::single();
|
34 |
-
$panels_admin->enqueue_admin_scripts();
|
35 |
-
$panels_admin->enqueue_admin_styles();
|
36 |
-
$panels_admin->js_templates();
|
37 |
-
|
38 |
-
wp_enqueue_script(
|
39 |
-
'siteorigin-panels-layout-block',
|
40 |
-
plugins_url( 'js/siteorigin-panels-layout-block' . SITEORIGIN_PANELS_JS_SUFFIX . '.js', __FILE__ ),
|
41 |
-
array(
|
42 |
-
'wp-editor',
|
43 |
-
'wp-blocks',
|
44 |
-
'wp-i18n',
|
45 |
-
'wp-element',
|
46 |
-
'wp-components',
|
47 |
-
'wp-compose',
|
48 |
-
'so-panels-admin'
|
49 |
-
),
|
50 |
-
SITEORIGIN_PANELS_VERSION
|
51 |
-
);
|
52 |
-
|
53 |
-
$current_screen = get_current_screen();
|
54 |
-
$is_panels_post_type = in_array( $current_screen->id, siteorigin_panels_setting( 'post-types' ) );
|
55 |
-
wp_localize_script(
|
56 |
-
'siteorigin-panels-layout-block',
|
57 |
-
'soPanelsBlockEditorAdmin',
|
58 |
-
array(
|
59 |
-
'sanitizeUrl' => wp_nonce_url( admin_url( 'admin-ajax.php' ), 'layout-block-sanitize', '_panelsnonce' ),
|
60 |
-
'previewUrl' => wp_nonce_url( admin_url( 'admin-ajax.php' ), 'layout-block-preview', '_panelsnonce' ),
|
61 |
-
'defaultMode' => siteorigin_panels_setting( 'layout-block-default-mode' ),
|
62 |
-
'showAddButton' => $is_panels_post_type,
|
63 |
-
)
|
64 |
-
);
|
65 |
-
// This is only available in WP5.
|
66 |
-
if ( function_exists( 'wp_set_script_translations' ) ) {
|
67 |
-
wp_set_script_translations( 'siteorigin-panels-layout-block', 'siteorigin-panels' );
|
68 |
-
}
|
69 |
-
SiteOrigin_Panels_Styles::register_scripts();
|
70 |
-
wp_enqueue_script( 'siteorigin-panels-front-styles' );
|
71 |
-
|
72 |
-
// Enqueue front end scripts for our widgets bundle.
|
73 |
-
if ( class_exists( 'SiteOrigin_Widgets_Bundle' ) ) {
|
74 |
-
$sowb = SiteOrigin_Widgets_Bundle::single();
|
75 |
-
$sowb->register_general_scripts();
|
76 |
-
if ( method_exists( $sowb, 'enqueue_registered_widgets_scripts' ) ) {
|
77 |
-
$sowb->enqueue_registered_widgets_scripts( true, false );
|
78 |
-
}
|
79 |
-
}
|
80 |
-
}
|
81 |
-
}
|
82 |
-
|
83 |
-
public function render_layout_block( $attributes ) {
|
84 |
-
|
85 |
-
if ( empty( $attributes['panelsData'] ) ) {
|
86 |
-
return '<div>'.
|
87 |
-
__( "You need to add a widget, row, or prebuilt layout before you'll see anything here. :)", 'siteorigin-panels' ) .
|
88 |
-
'</div>';
|
89 |
-
}
|
90 |
-
$panels_data = $attributes['panelsData'];
|
91 |
-
$panels_data = $this->sanitize_panels_data( $panels_data );
|
92 |
-
$builder_id = isset( $attributes['builder_id'] ) ? $attributes['builder_id'] : uniqid( 'gb' . get_the_ID() . '-' );
|
93 |
-
|
94 |
-
// Support for custom CSS classes
|
95 |
-
$add_custom_class_name = function( $class_names ) use ($attributes) {
|
96 |
-
if ( ! empty( $attributes['className'] ) ) {
|
97 |
-
$class_names[] = $attributes['className'];
|
98 |
-
}
|
99 |
-
return $class_names;
|
100 |
-
};
|
101 |
-
add_filter( 'siteorigin_panels_layout_classes', $add_custom_class_name );
|
102 |
-
$rendered_layout = SiteOrigin_Panels::renderer()->render( $builder_id, true, $panels_data );
|
103 |
-
remove_filter( 'siteorigin_panels_layout_classes', $add_custom_class_name );
|
104 |
-
return $rendered_layout;
|
105 |
-
}
|
106 |
-
|
107 |
-
private function sanitize_panels_data( $panels_data ) {
|
108 |
-
// We force calling widgets' update functions here, but a better solution is to ensure these are called when
|
109 |
-
// the block is saved, but there is currently no simple method to do so.
|
110 |
-
$panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'], false, true );
|
111 |
-
$panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
|
112 |
-
return $panels_data;
|
113 |
-
}
|
114 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class SiteOrigin_Panels_Compat_Layout_Block {
|
4 |
+
|
5 |
+
const BLOCK_NAME = 'siteorigin-panels/layout-block';
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Get the singleton instance
|
9 |
+
*
|
10 |
+
* @return SiteOrigin_Panels_Compat_Layout_Block
|
11 |
+
*/
|
12 |
+
public static function single() {
|
13 |
+
static $single;
|
14 |
+
|
15 |
+
return empty( $single ) ? $single = new self() : $single;
|
16 |
+
}
|
17 |
+
|
18 |
+
public function __construct() {
|
19 |
+
add_action( 'init', array( $this, 'register_layout_block' ) );
|
20 |
+
// This action is slightly later than `enqueue_block_editor_assets`,
|
21 |
+
// which we need to use to ensure our templates are loaded at the right time.
|
22 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_layout_block_editor_assets' ) );
|
23 |
+
}
|
24 |
+
|
25 |
+
public function register_layout_block() {
|
26 |
+
register_block_type( self::BLOCK_NAME, array(
|
27 |
+
'render_callback' => array( $this, 'render_layout_block' ),
|
28 |
+
) );
|
29 |
+
}
|
30 |
+
|
31 |
+
public function enqueue_layout_block_editor_assets() {
|
32 |
+
if ( SiteOrigin_Panels_Admin::is_block_editor() ) {
|
33 |
+
$panels_admin = SiteOrigin_Panels_Admin::single();
|
34 |
+
$panels_admin->enqueue_admin_scripts();
|
35 |
+
$panels_admin->enqueue_admin_styles();
|
36 |
+
$panels_admin->js_templates();
|
37 |
+
|
38 |
+
wp_enqueue_script(
|
39 |
+
'siteorigin-panels-layout-block',
|
40 |
+
plugins_url( 'js/siteorigin-panels-layout-block' . SITEORIGIN_PANELS_JS_SUFFIX . '.js', __FILE__ ),
|
41 |
+
array(
|
42 |
+
'wp-editor',
|
43 |
+
'wp-blocks',
|
44 |
+
'wp-i18n',
|
45 |
+
'wp-element',
|
46 |
+
'wp-components',
|
47 |
+
'wp-compose',
|
48 |
+
'so-panels-admin'
|
49 |
+
),
|
50 |
+
SITEORIGIN_PANELS_VERSION
|
51 |
+
);
|
52 |
+
|
53 |
+
$current_screen = get_current_screen();
|
54 |
+
$is_panels_post_type = in_array( $current_screen->id, siteorigin_panels_setting( 'post-types' ) );
|
55 |
+
wp_localize_script(
|
56 |
+
'siteorigin-panels-layout-block',
|
57 |
+
'soPanelsBlockEditorAdmin',
|
58 |
+
array(
|
59 |
+
'sanitizeUrl' => wp_nonce_url( admin_url( 'admin-ajax.php' ), 'layout-block-sanitize', '_panelsnonce' ),
|
60 |
+
'previewUrl' => wp_nonce_url( admin_url( 'admin-ajax.php' ), 'layout-block-preview', '_panelsnonce' ),
|
61 |
+
'defaultMode' => siteorigin_panels_setting( 'layout-block-default-mode' ),
|
62 |
+
'showAddButton' => apply_filters( 'siteorigin_layout_block_show_add_button', $is_panels_post_type ),
|
63 |
+
)
|
64 |
+
);
|
65 |
+
// This is only available in WP5.
|
66 |
+
if ( function_exists( 'wp_set_script_translations' ) ) {
|
67 |
+
wp_set_script_translations( 'siteorigin-panels-layout-block', 'siteorigin-panels' );
|
68 |
+
}
|
69 |
+
SiteOrigin_Panels_Styles::register_scripts();
|
70 |
+
wp_enqueue_script( 'siteorigin-panels-front-styles' );
|
71 |
+
|
72 |
+
// Enqueue front end scripts for our widgets bundle.
|
73 |
+
if ( class_exists( 'SiteOrigin_Widgets_Bundle' ) ) {
|
74 |
+
$sowb = SiteOrigin_Widgets_Bundle::single();
|
75 |
+
$sowb->register_general_scripts();
|
76 |
+
if ( method_exists( $sowb, 'enqueue_registered_widgets_scripts' ) ) {
|
77 |
+
$sowb->enqueue_registered_widgets_scripts( true, false );
|
78 |
+
}
|
79 |
+
}
|
80 |
+
}
|
81 |
+
}
|
82 |
+
|
83 |
+
public function render_layout_block( $attributes ) {
|
84 |
+
|
85 |
+
if ( empty( $attributes['panelsData'] ) ) {
|
86 |
+
return '<div>'.
|
87 |
+
__( "You need to add a widget, row, or prebuilt layout before you'll see anything here. :)", 'siteorigin-panels' ) .
|
88 |
+
'</div>';
|
89 |
+
}
|
90 |
+
$panels_data = $attributes['panelsData'];
|
91 |
+
$panels_data = $this->sanitize_panels_data( $panels_data );
|
92 |
+
$builder_id = isset( $attributes['builder_id'] ) ? $attributes['builder_id'] : uniqid( 'gb' . get_the_ID() . '-' );
|
93 |
+
|
94 |
+
// Support for custom CSS classes
|
95 |
+
$add_custom_class_name = function( $class_names ) use ($attributes) {
|
96 |
+
if ( ! empty( $attributes['className'] ) ) {
|
97 |
+
$class_names[] = $attributes['className'];
|
98 |
+
}
|
99 |
+
return $class_names;
|
100 |
+
};
|
101 |
+
add_filter( 'siteorigin_panels_layout_classes', $add_custom_class_name );
|
102 |
+
$rendered_layout = SiteOrigin_Panels::renderer()->render( $builder_id, true, $panels_data );
|
103 |
+
remove_filter( 'siteorigin_panels_layout_classes', $add_custom_class_name );
|
104 |
+
return $rendered_layout;
|
105 |
+
}
|
106 |
+
|
107 |
+
private function sanitize_panels_data( $panels_data ) {
|
108 |
+
// We force calling widgets' update functions here, but a better solution is to ensure these are called when
|
109 |
+
// the block is saved, but there is currently no simple method to do so.
|
110 |
+
$panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'], false, true );
|
111 |
+
$panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
|
112 |
+
return $panels_data;
|
113 |
+
}
|
114 |
+
}
|
compat/pb-icon.svg
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 703.29 745.09"><defs><style>.cls-1{opacity:0.5;}.cls-2{opacity:0.2;}</style></defs><title>pb-icon</title><path d="M731.52,232.52,397,430.73a17.11,17.11,0,0,1-17.45,0L45,232.52a17.12,17.12,0,0,1,0-29.46L379.54,4.85a17.11,17.11,0,0,1,17.45,0L731.52,203.06A17.12,17.12,0,0,1,731.52,232.52Z" transform="translate(-36.62 -2.46)"/><path class="cls-1" d="M731.52,399.94,397,598.15a17.11,17.11,0,0,1-17.45,0L45,399.94a17.12,17.12,0,0,1,0-29.46L379.54,172.27a17.11,17.11,0,0,1,17.45,0L731.52,370.48A17.12,17.12,0,0,1,731.52,399.94Z" transform="translate(-36.62 -2.46)"/><path class="cls-2" d="M731.52,546.94,397,745.15a17.11,17.11,0,0,1-17.45,0L45,546.94a17.12,17.12,0,0,1,0-29.46L379.54,319.27a17.11,17.11,0,0,1,17.45,0L731.52,517.48A17.12,17.12,0,0,1,731.52,546.94Z" transform="translate(-36.62 -2.46)"/></svg>
|
Â
|
compat/pb-icon_white.svg
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 703.29 745.09"><defs><style>.cls-1{opacity:0.5;}.cls-2{opacity:0.2;}</style></defs><title>pb-icon</title><path fill="white" d="M731.52,232.52,397,430.73a17.11,17.11,0,0,1-17.45,0L45,232.52a17.12,17.12,0,0,1,0-29.46L379.54,4.85a17.11,17.11,0,0,1,17.45,0L731.52,203.06A17.12,17.12,0,0,1,731.52,232.52Z" transform="translate(-36.62 -2.46)"/><path class="cls-1" fill="white" d="M731.52,399.94,397,598.15a17.11,17.11,0,0,1-17.45,0L45,399.94a17.12,17.12,0,0,1,0-29.46L379.54,172.27a17.11,17.11,0,0,1,17.45,0L731.52,370.48A17.12,17.12,0,0,1,731.52,399.94Z" transform="translate(-36.62 -2.46)"/><path fill="white" class="cls-2" d="M731.52,546.94,397,745.15a17.11,17.11,0,0,1-17.45,0L45,546.94a17.12,17.12,0,0,1,0-29.46L379.54,319.27a17.11,17.11,0,0,1,17.45,0L731.52,517.48A17.12,17.12,0,0,1,731.52,546.94Z" transform="translate(-36.62 -2.46)"/></svg>
|
Â
|
css/front.css
DELETED
@@ -1,47 +0,0 @@
|
|
1 |
-
.panel-grid.panel-no-style,
|
2 |
-
.panel-grid.panel-has-style > .panel-row-style {
|
3 |
-
display: -webkit-flex;
|
4 |
-
display: flex;
|
5 |
-
-ms-flex-wrap: wrap;
|
6 |
-
-webkit-flex-wrap: wrap;
|
7 |
-
flex-wrap: nowrap;
|
8 |
-
-ms-justify-content: space-between;
|
9 |
-
-webkit-justify-content: space-between;
|
10 |
-
justify-content: space-between;
|
11 |
-
}
|
12 |
-
.panel-grid-cell {
|
13 |
-
-ms-box-sizing: border-box;
|
14 |
-
-moz-box-sizing: border-box;
|
15 |
-
-webkit-box-sizing: border-box;
|
16 |
-
box-sizing: border-box;
|
17 |
-
}
|
18 |
-
.panel-grid-cell .panel-cell-style {
|
19 |
-
height: 100%;
|
20 |
-
}
|
21 |
-
.panel-grid-cell .so-panel {
|
22 |
-
zoom: 1;
|
23 |
-
}
|
24 |
-
.panel-grid-cell .so-panel:before {
|
25 |
-
content: '';
|
26 |
-
display: block;
|
27 |
-
}
|
28 |
-
.panel-grid-cell .so-panel:after {
|
29 |
-
content: '';
|
30 |
-
display: table;
|
31 |
-
clear: both;
|
32 |
-
}
|
33 |
-
.panel-grid-cell .panel-last-child {
|
34 |
-
margin-bottom: 0;
|
35 |
-
}
|
36 |
-
.panel-grid-cell .widget-title {
|
37 |
-
margin-top: 0;
|
38 |
-
}
|
39 |
-
body.siteorigin-panels-before-js {
|
40 |
-
overflow-x: hidden;
|
41 |
-
}
|
42 |
-
body.siteorigin-panels-before-js .siteorigin-panels-stretch {
|
43 |
-
margin-right: -1000px !important;
|
44 |
-
margin-left: -1000px !important;
|
45 |
-
padding-right: 1000px !important;
|
46 |
-
padding-left: 1000px !important;
|
47 |
-
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
css/front.min.css
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
.panel-grid.panel-has-style>.panel-row-style,.panel-grid.panel-no-style{display:flex;-ms-flex-wrap:wrap;flex-wrap:nowrap;-ms-justify-content:space-between;justify-content:space-between}.panel-grid-cell{-ms-box-sizing:border-box;box-sizing:border-box}.panel-grid-cell .panel-cell-style{height:100%}.panel-grid-cell .so-panel{zoom:1}.panel-grid-cell .so-panel:before{content:"";display:block}.panel-grid-cell .so-panel:after{content:"";display:table;clear:both}.panel-grid-cell .panel-last-child{margin-bottom:0}.panel-grid-cell .widget-title{margin-top:0}body.siteorigin-panels-before-js{overflow-x:hidden}body.siteorigin-panels-before-js .siteorigin-panels-stretch{margin-right:-1000px!important;margin-left:-1000px!important;padding-right:1000px!important;padding-left:1000px!important}
|
Â
|
css/icons/readme.txt
DELETED
@@ -1,5 +0,0 @@
|
|
1 |
-
Icons are a subset of FontAwesome
|
2 |
-
Font Awesome by Dave Gandy - http://fontawesome.io
|
3 |
-
|
4 |
-
License: SIL OFL 1.1
|
5 |
-
URL: http://scripts.sil.org/OFL
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
css/images/pb-icon_white.svg
CHANGED
@@ -1 +1 @@
|
|
1 |
-
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 703.29 745.09"><defs><style>.cls-1{opacity:0.5;}.cls-2{opacity:0.2;}</style></defs><title>pb-icon</title><path fill="white" d="M731.52,232.52,397,430.73a17.11,17.11,0,0,1-17.45,0L45,232.52a17.12,17.12,0,0,1,0-29.46L379.54,4.85a17.11,17.11,0,0,1,17.45,0L731.52,203.06A17.12,17.12,0,0,1,731.52,232.52Z" transform="translate(-36.62 -2.46)"/><path class="cls-1" fill="white" d="M731.52,399.94,397,598.15a17.11,17.11,0,0,1-17.45,0L45,399.94a17.12,17.12,0,0,1,0-29.46L379.54,172.27a17.11,17.11,0,0,1,17.45,0L731.52,370.48A17.12,17.12,0,0,1,731.52,399.94Z" transform="translate(-36.62 -2.46)"/><path fill="white" class="cls-2" d="M731.52,546.94,397,745.15a17.11,17.11,0,0,1-17.45,0L45,546.94a17.12,17.12,0,0,1,0-29.46L379.54,319.27a17.11,17.11,0,0,1,17.45,0L731.52,517.48A17.12,17.12,0,0,1,731.52,546.94Z" transform="translate(-36.62 -2.46)"/></svg>
|
1 |
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 703.29 745.09"><defs><style>.cls-1{opacity:0.5;}.cls-2{opacity:0.2;}</style></defs><title>pb-icon</title><path fill="white" d="M731.52,232.52,397,430.73a17.11,17.11,0,0,1-17.45,0L45,232.52a17.12,17.12,0,0,1,0-29.46L379.54,4.85a17.11,17.11,0,0,1,17.45,0L731.52,203.06A17.12,17.12,0,0,1,731.52,232.52Z" transform="translate(-36.62 -2.46)"/><path class="cls-1" fill="white" d="M731.52,399.94,397,598.15a17.11,17.11,0,0,1-17.45,0L45,399.94a17.12,17.12,0,0,1,0-29.46L379.54,172.27a17.11,17.11,0,0,1,17.45,0L731.52,370.48A17.12,17.12,0,0,1,731.52,399.94Z" transform="translate(-36.62 -2.46)"/><path fill="white" class="cls-2" d="M731.52,546.94,397,745.15a17.11,17.11,0,0,1-17.45,0L45,546.94a17.12,17.12,0,0,1,0-29.46L379.54,319.27a17.11,17.11,0,0,1,17.45,0L731.52,517.48A17.12,17.12,0,0,1,731.52,546.94Z" transform="translate(-36.62 -2.46)"/></svg>
|
css/mixins.less
DELETED
@@ -1,173 +0,0 @@
|
|
1 |
-
.gradient(@color: #F5F5F5, @start: #EEE, @stop: #FFF) {
|
2 |
-
background: @color;
|
3 |
-
background: -webkit-gradient(linear, left bottom, left top, color-stop(0, @start), color-stop(1, @stop));
|
4 |
-
background: -ms-linear-gradient(bottom,@start,@stop);
|
5 |
-
background: -moz-linear-gradient(center bottom,@start 0%,@stop 100%);
|
6 |
-
background: -o-linear-gradient(@stop,@start);
|
7 |
-
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)", @stop, @start));
|
8 |
-
}
|
9 |
-
|
10 |
-
.bw-gradient(@color: #F5F5F5, @start: 0, @stop: 255) {
|
11 |
-
background: @color;
|
12 |
-
background: -webkit-gradient(linear, left bottom, left top, color-stop(0, rgb(@start,@start,@start)), color-stop(1, rgb(@stop,@stop,@stop)));
|
13 |
-
background: -ms-linear-gradient(bottom, rgb(@start,@start,@start) 0%, rgb(@stop,@stop,@stop) 100%);
|
14 |
-
background: -moz-linear-gradient(center bottom, rgb(@start,@start,@start) 0%, rgb(@stop,@stop,@stop) 100%);
|
15 |
-
background: -o-linear-gradient(rgb(@stop,@stop,@stop), rgb(@start,@start,@start));
|
16 |
-
background: linear-gradient(rgb(@stop,@stop,@stop), rgb(@start,@start,@start));
|
17 |
-
|
18 |
-
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",rgb(@stop,@stop,@stop), rgb(@start,@start,@start)));
|
19 |
-
}
|
20 |
-
|
21 |
-
.linear-gradient(@color, @gradient) {
|
22 |
-
background: @color;
|
23 |
-
background: -moz-linear-gradient(@gradient);
|
24 |
-
background: -webkit-linear-gradient(@gradient);
|
25 |
-
background: -o-linear-gradient(@gradient);
|
26 |
-
background: -ms-linear-gradient(@gradient);
|
27 |
-
background: linear-gradient(@gradient);
|
28 |
-
}
|
29 |
-
|
30 |
-
.bordered(@top-color: #EEE, @right-color: #EEE, @bottom-color: #EEE, @left-color: #EEE) {
|
31 |
-
border-top: solid 1px @top-color;
|
32 |
-
border-left: solid 1px @left-color;
|
33 |
-
border-right: solid 1px @right-color;
|
34 |
-
border-bottom: solid 1px @bottom-color;
|
35 |
-
}
|
36 |
-
|
37 |
-
.drop-shadow(@x-axis: 0, @y-axis: 1px, @blur: 2px, @alpha: 0.1) {
|
38 |
-
-webkit-box-shadow: @x-axis @y-axis @blur rgba(0, 0, 0, @alpha);
|
39 |
-
-moz-box-shadow: @x-axis @y-axis @blur rgba(0, 0, 0, @alpha);
|
40 |
-
box-shadow: @x-axis @y-axis @blur rgba(0, 0, 0, @alpha);
|
41 |
-
}
|
42 |
-
|
43 |
-
.box-shadow(@shadow) {
|
44 |
-
-webkit-box-shadow: @shadow;
|
45 |
-
-moz-box-shadow: @shadow;
|
46 |
-
box-shadow: @shadow;
|
47 |
-
}
|
48 |
-
|
49 |
-
.rounded(@radius: 2px) {
|
50 |
-
-webkit-border-radius: @radius;
|
51 |
-
-moz-border-radius: @radius;
|
52 |
-
border-radius: @radius;
|
53 |
-
}
|
54 |
-
|
55 |
-
.border-radius(@topright: 0, @bottomright: 0, @bottomleft: 0, @topleft: 0) {
|
56 |
-
-webkit-border-top-right-radius: @topright;
|
57 |
-
-webkit-border-bottom-right-radius: @bottomright;
|
58 |
-
-webkit-border-bottom-left-radius: @bottomleft;
|
59 |
-
-webkit-border-top-left-radius: @topleft;
|
60 |
-
-moz-border-radius-topright: @topright;
|
61 |
-
-moz-border-radius-bottomright: @bottomright;
|
62 |
-
-moz-border-radius-bottomleft: @bottomleft;
|
63 |
-
-moz-border-radius-topleft: @topleft;
|
64 |
-
border-top-right-radius: @topright;
|
65 |
-
border-bottom-right-radius: @bottomright;
|
66 |
-
border-bottom-left-radius: @bottomleft;
|
67 |
-
border-top-left-radius: @topleft;
|
68 |
-
.background-clip(padding-box);
|
69 |
-
}
|
70 |
-
|
71 |
-
.opacity(@opacity: 0.5) {
|
72 |
-
-moz-opacity: @opacity;
|
73 |
-
-khtml-opacity: @opacity;
|
74 |
-
-webkit-opacity: @opacity;
|
75 |
-
opacity: @opacity;
|
76 |
-
@opperc: @opacity * 100;
|
77 |
-
-ms-filter: ~"progid:DXImageTransform.Microsoft.Alpha(opacity=@{opperc})";
|
78 |
-
filter: ~"alpha(opacity=@{opperc})";
|
79 |
-
}
|
80 |
-
|
81 |
-
.transition-duration(@duration: 0.2s) {
|
82 |
-
-moz-transition-duration: @duration;
|
83 |
-
-webkit-transition-duration: @duration;
|
84 |
-
-o-transition-duration: @duration;
|
85 |
-
transition-duration: @duration;
|
86 |
-
}
|
87 |
-
|
88 |
-
.transform(...) {
|
89 |
-
-webkit-transform: @arguments;
|
90 |
-
-moz-transform: @arguments;
|
91 |
-
-o-transform: @arguments;
|
92 |
-
-ms-transform: @arguments;
|
93 |
-
transform: @arguments;
|
94 |
-
}
|
95 |
-
|
96 |
-
.rotation(@deg:5deg) {
|
97 |
-
.transform(rotate(@deg));
|
98 |
-
}
|
99 |
-
|
100 |
-
.scale(@ratio:1.5) {
|
101 |
-
.transform(scale(@ratio));
|
102 |
-
}
|
103 |
-
|
104 |
-
.transition(@duration:0.2s, @on: all, @ease:ease) {
|
105 |
-
-webkit-transition: @on @duration @ease;
|
106 |
-
-moz-transition: @on @duration @ease;
|
107 |
-
-o-transition: @on @duration @ease;
|
108 |
-
transition: @on @duration @ease;
|
109 |
-
}
|
110 |
-
|
111 |
-
.inner-shadow(@horizontal:0, @vertical:1px, @blur:2px, @alpha: 0.4) {
|
112 |
-
-webkit-box-shadow: inset @horizontal @vertical @blur rgba(0, 0, 0, @alpha);
|
113 |
-
-moz-box-shadow: inset @horizontal @vertical @blur rgba(0, 0, 0, @alpha);
|
114 |
-
box-shadow: inset @horizontal @vertical @blur rgba(0, 0, 0, @alpha);
|
115 |
-
}
|
116 |
-
|
117 |
-
.box-sizing(@sizing: border-box) {
|
118 |
-
-ms-box-sizing: @sizing;
|
119 |
-
-moz-box-sizing: @sizing;
|
120 |
-
-webkit-box-sizing: @sizing;
|
121 |
-
box-sizing: @sizing;
|
122 |
-
}
|
123 |
-
|
124 |
-
.user-select(@argument: none) {
|
125 |
-
-webkit-user-select: @argument;
|
126 |
-
-moz-user-select: @argument;
|
127 |
-
-ms-user-select: @argument;
|
128 |
-
user-select: @argument;
|
129 |
-
}
|
130 |
-
|
131 |
-
.columns(@colwidth: 250px, @colcount: 0, @colgap: 50px, @columnRuleColor: #EEE, @columnRuleStyle: solid, @columnRuleWidth: 1px) {
|
132 |
-
-moz-column-width: @colwidth;
|
133 |
-
-moz-column-count: @colcount;
|
134 |
-
-moz-column-gap: @colgap;
|
135 |
-
-moz-column-rule-color: @columnRuleColor;
|
136 |
-
-moz-column-rule-style: @columnRuleStyle;
|
137 |
-
-moz-column-rule-width: @columnRuleWidth;
|
138 |
-
-webkit-column-width: @colwidth;
|
139 |
-
-webkit-column-count: @colcount;
|
140 |
-
-webkit-column-gap: @colgap;
|
141 |
-
-webkit-column-rule-color: @columnRuleColor;
|
142 |
-
-webkit-column-rule-style: @columnRuleStyle;
|
143 |
-
-webkit-column-rule-width: @columnRuleWidth;
|
144 |
-
column-width: @colwidth;
|
145 |
-
column-count: @colcount;
|
146 |
-
column-gap: @colgap;
|
147 |
-
column-rule-color: @columnRuleColor;
|
148 |
-
column-rule-style: @columnRuleStyle;
|
149 |
-
column-rule-width: @columnRuleWidth;
|
150 |
-
}
|
151 |
-
|
152 |
-
.translate(@x:0, @y:0) {
|
153 |
-
.transform(translate(@x, @y));
|
154 |
-
}
|
155 |
-
|
156 |
-
.background-clip(@argument: padding-box) {
|
157 |
-
-moz-background-clip: @argument;
|
158 |
-
-webkit-background-clip: @argument;
|
159 |
-
background-clip: @argument;
|
160 |
-
}
|
161 |
-
|
162 |
-
.clearfix() {
|
163 |
-
zoom: 1;
|
164 |
-
&:before {
|
165 |
-
content: '';
|
166 |
-
display: block;
|
167 |
-
}
|
168 |
-
&:after {
|
169 |
-
content: '';
|
170 |
-
display: table;
|
171 |
-
clear: both;
|
172 |
-
}
|
173 |
-
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
inc/admin-dashboard.php
CHANGED
@@ -1,117 +1,117 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class SiteOrigin_Panels_Admin_Dashboard {
|
4 |
-
|
5 |
-
function __construct() {
|
6 |
-
add_action( 'wp_dashboard_setup', array( $this, 'register_dashboard_widgets' ), 15 );
|
7 |
-
add_action( 'admin_print_styles', array( $this, 'enqueue_admin_styles' ) );
|
8 |
-
}
|
9 |
-
|
10 |
-
/**
|
11 |
-
* @return SiteOrigin_Panels_Admin_Dashboard
|
12 |
-
*/
|
13 |
-
public static function single() {
|
14 |
-
static $single;
|
15 |
-
return empty( $single ) ? $single = new self() : $single;
|
16 |
-
}
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Register the dashboard widget
|
20 |
-
*/
|
21 |
-
public function register_dashboard_widgets(){
|
22 |
-
if( function_exists( 'wp_dashboard_primary_output' ) ) {
|
23 |
-
wp_add_dashboard_widget( 'so-dashboard-news', __( 'SiteOrigin Page Builder News', 'siteorigin-panels' ), array(
|
24 |
-
$this,
|
25 |
-
'dashboard_overview_widget'
|
26 |
-
) );
|
27 |
-
|
28 |
-
// Move Page Builder widget to the top
|
29 |
-
global $wp_meta_boxes;
|
30 |
-
|
31 |
-
$dashboard = $wp_meta_boxes['dashboard']['normal']['core'];
|
32 |
-
$ours = array( 'so-dashboard-news' => $dashboard['so-dashboard-news'] );
|
33 |
-
|
34 |
-
$wp_meta_boxes['dashboard']['normal']['core'] = array_merge( $ours, $dashboard ); // WPCS: override ok.
|
35 |
-
}
|
36 |
-
}
|
37 |
-
|
38 |
-
/**
|
39 |
-
* Enqueue the dashboard styles
|
40 |
-
*/
|
41 |
-
public function enqueue_admin_styles( $page ){
|
42 |
-
$screen = get_current_screen();
|
43 |
-
if( ! empty( $screen ) && $screen->id == 'dashboard' ) {
|
44 |
-
wp_enqueue_style(
|
45 |
-
'so-panels-dashboard',
|
46 |
-
siteorigin_panels_url( 'css/dashboard.css' ),
|
47 |
-
array( 'wp-color-picker' ),
|
48 |
-
SITEORIGIN_PANELS_VERSION
|
49 |
-
);
|
50 |
-
}
|
51 |
-
}
|
52 |
-
|
53 |
-
/**
|
54 |
-
* Display the actual widget
|
55 |
-
*/
|
56 |
-
public function dashboard_overview_widget(){
|
57 |
-
$feeds = array(
|
58 |
-
array(
|
59 |
-
'url' => 'https://siteorigin.com/feed/',
|
60 |
-
'items' => 4,
|
61 |
-
'show_summary' => 0,
|
62 |
-
'show_author' => 0,
|
63 |
-
'show_date' => 1,
|
64 |
-
),
|
65 |
-
);
|
66 |
-
|
67 |
-
wp_dashboard_primary_output( 'so_dashboard_widget_news', $feeds );
|
68 |
-
|
69 |
-
if( function_exists( 'wp_print_community_events_markup' ) ) {
|
70 |
-
?>
|
71 |
-
<p class="community-events-footer">
|
72 |
-
<?php
|
73 |
-
printf(
|
74 |
-
'<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
|
75 |
-
esc_url( 'https://siteorigin.com/blog/' ),
|
76 |
-
__( 'Blog', 'siteorigin-panels' ),
|
77 |
-
/* translators: accessibility text */
|
78 |
-
__( '(opens in a new window)', 'siteorigin-panels' )
|
79 |
-
);
|
80 |
-
echo ' | ';
|
81 |
-
|
82 |
-
if( class_exists( 'SiteOrigin_Premium' ) ) {
|
83 |
-
printf(
|
84 |
-
'<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-email-alt"></span></a>',
|
85 |
-
esc_url( 'mailto:support@siteorigin.com' ),
|
86 |
-
__( 'Email Support', 'siteorigin-panels' ),
|
87 |
-
/* translators: accessibility text */
|
88 |
-
__( '(email SiteOrigin support)', 'siteorigin-panels' )
|
89 |
-
);
|
90 |
-
}
|
91 |
-
else {
|
92 |
-
printf(
|
93 |
-
'<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
|
94 |
-
esc_url( 'https://siteorigin.com/thread/' ),
|
95 |
-
__( 'Support Forum', 'siteorigin-panels' ),
|
96 |
-
/* translators: accessibility text */
|
97 |
-
__( '(opens in a new window)', 'siteorigin-panels' )
|
98 |
-
);
|
99 |
-
}
|
100 |
-
|
101 |
-
if ( SiteOrigin_Panels::display_premium_teaser() ) {
|
102 |
-
echo ' | ';
|
103 |
-
printf(
|
104 |
-
'<a href="%1$s" target="_blank" rel="noopener noreferrer" style="color: #2ebd59">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
|
105 |
-
/* translators: If a Rosetta site exists (e.g. https://es.wordpress.org/news/), then use that. Otherwise, leave untranslated. */
|
106 |
-
esc_url( 'https://siteorigin.com/downloads/premium/' ),
|
107 |
-
__( 'Get Premium', 'siteorigin-panels' ),
|
108 |
-
/* translators: accessibility text */
|
109 |
-
__( '(opens in a new window)', 'siteorigin-panels' )
|
110 |
-
);
|
111 |
-
}
|
112 |
-
?>
|
113 |
-
</p>
|
114 |
-
<?php
|
115 |
-
}
|
116 |
-
}
|
117 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class SiteOrigin_Panels_Admin_Dashboard {
|
4 |
+
|
5 |
+
function __construct() {
|
6 |
+
add_action( 'wp_dashboard_setup', array( $this, 'register_dashboard_widgets' ), 15 );
|
7 |
+
add_action( 'admin_print_styles', array( $this, 'enqueue_admin_styles' ) );
|
8 |
+
}
|
9 |
+
|
10 |
+
/**
|
11 |
+
* @return SiteOrigin_Panels_Admin_Dashboard
|
12 |
+
*/
|
13 |
+
public static function single() {
|
14 |
+
static $single;
|
15 |
+
return empty( $single ) ? $single = new self() : $single;
|
16 |
+
}
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Register the dashboard widget
|
20 |
+
*/
|
21 |
+
public function register_dashboard_widgets(){
|
22 |
+
if( function_exists( 'wp_dashboard_primary_output' ) ) {
|
23 |
+
wp_add_dashboard_widget( 'so-dashboard-news', __( 'SiteOrigin Page Builder News', 'siteorigin-panels' ), array(
|
24 |
+
$this,
|
25 |
+
'dashboard_overview_widget'
|
26 |
+
) );
|
27 |
+
|
28 |
+
// Move Page Builder widget to the top
|
29 |
+
global $wp_meta_boxes;
|
30 |
+
|
31 |
+
$dashboard = $wp_meta_boxes['dashboard']['normal']['core'];
|
32 |
+
$ours = array( 'so-dashboard-news' => $dashboard['so-dashboard-news'] );
|
33 |
+
|
34 |
+
$wp_meta_boxes['dashboard']['normal']['core'] = array_merge( $ours, $dashboard ); // WPCS: override ok.
|
35 |
+
}
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Enqueue the dashboard styles
|
40 |
+
*/
|
41 |
+
public function enqueue_admin_styles( $page ){
|
42 |
+
$screen = get_current_screen();
|
43 |
+
if( ! empty( $screen ) && $screen->id == 'dashboard' ) {
|
44 |
+
wp_enqueue_style(
|
45 |
+
'so-panels-dashboard',
|
46 |
+
siteorigin_panels_url( 'css/dashboard.css' ),
|
47 |
+
array( 'wp-color-picker' ),
|
48 |
+
SITEORIGIN_PANELS_VERSION
|
49 |
+
);
|
50 |
+
}
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Display the actual widget
|
55 |
+
*/
|
56 |
+
public function dashboard_overview_widget(){
|
57 |
+
$feeds = array(
|
58 |
+
array(
|
59 |
+
'url' => 'https://siteorigin.com/feed/',
|
60 |
+
'items' => 4,
|
61 |
+
'show_summary' => 0,
|
62 |
+
'show_author' => 0,
|
63 |
+
'show_date' => 1,
|
64 |
+
),
|
65 |
+
);
|
66 |
+
|
67 |
+
wp_dashboard_primary_output( 'so_dashboard_widget_news', $feeds );
|
68 |
+
|
69 |
+
if( function_exists( 'wp_print_community_events_markup' ) ) {
|
70 |
+
?>
|
71 |
+
<p class="community-events-footer">
|
72 |
+
<?php
|
73 |
+
printf(
|
74 |
+
'<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
|
75 |
+
esc_url( 'https://siteorigin.com/blog/' ),
|
76 |
+
__( 'Blog', 'siteorigin-panels' ),
|
77 |
+
/* translators: accessibility text */
|
78 |
+
__( '(opens in a new window)', 'siteorigin-panels' )
|
79 |
+
);
|
80 |
+
echo ' | ';
|
81 |
+
|
82 |
+
if( class_exists( 'SiteOrigin_Premium' ) ) {
|
83 |
+
printf(
|
84 |
+
'<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-email-alt"></span></a>',
|
85 |
+
esc_url( 'mailto:support@siteorigin.com' ),
|
86 |
+
__( 'Email Support', 'siteorigin-panels' ),
|
87 |
+
/* translators: accessibility text */
|
88 |
+
__( '(email SiteOrigin support)', 'siteorigin-panels' )
|
89 |
+
);
|
90 |
+
}
|
91 |
+
else {
|
92 |
+
printf(
|
93 |
+
'<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
|
94 |
+
esc_url( 'https://siteorigin.com/thread/' ),
|
95 |
+
__( 'Support Forum', 'siteorigin-panels' ),
|
96 |
+
/* translators: accessibility text */
|
97 |
+
__( '(opens in a new window)', 'siteorigin-panels' )
|
98 |
+
);
|
99 |
+
}
|
100 |
+
|
101 |
+
if ( SiteOrigin_Panels::display_premium_teaser() ) {
|
102 |
+
echo ' | ';
|
103 |
+
printf(
|
104 |
+
'<a href="%1$s" target="_blank" rel="noopener noreferrer" style="color: #2ebd59">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
|
105 |
+
/* translators: If a Rosetta site exists (e.g. https://es.wordpress.org/news/), then use that. Otherwise, leave untranslated. */
|
106 |
+
esc_url( 'https://siteorigin.com/downloads/premium/' ),
|
107 |
+
__( 'Get Premium', 'siteorigin-panels' ),
|
108 |
+
/* translators: accessibility text */
|
109 |
+
__( '(opens in a new window)', 'siteorigin-panels' )
|
110 |
+
);
|
111 |
+
}
|
112 |
+
?>
|
113 |
+
</p>
|
114 |
+
<?php
|
115 |
+
}
|
116 |
+
}
|
117 |
+
}
|
inc/admin-layouts.php
CHANGED
@@ -1,494 +1,494 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Class SiteOrigin_Panels_Admin
|
5 |
-
*
|
6 |
-
* Handles all the admin and database interactions.
|
7 |
-
*/
|
8 |
-
class SiteOrigin_Panels_Admin_Layouts {
|
9 |
-
|
10 |
-
const LAYOUT_URL = 'https://layouts.siteorigin.com/';
|
11 |
-
|
12 |
-
function __construct() {
|
13 |
-
// Filter all the available external layout directories.
|
14 |
-
add_filter( 'siteorigin_panels_external_layout_directories', array( $this, 'filter_directories' ), 8 );
|
15 |
-
// Filter all the available local layout folders.
|
16 |
-
add_filter( 'siteorigin_panels_prebuilt_layouts', array( $this, 'get_local_layouts' ), 8 );
|
17 |
-
|
18 |
-
add_action( 'wp_ajax_so_panels_layouts_query', array( $this, 'action_get_prebuilt_layouts' ) );
|
19 |
-
add_action( 'wp_ajax_so_panels_get_layout', array( $this, 'action_get_prebuilt_layout' ) );
|
20 |
-
add_action( 'wp_ajax_so_panels_import_layout', array( $this, 'action_import_layout' ) );
|
21 |
-
add_action( 'wp_ajax_so_panels_export_layout', array( $this, 'action_export_layout' ) );
|
22 |
-
add_action( 'wp_ajax_so_panels_directory_enable', array( $this, 'action_directory_enable' ) );
|
23 |
-
}
|
24 |
-
|
25 |
-
/**
|
26 |
-
* @return SiteOrigin_Panels_Admin_Layouts
|
27 |
-
*/
|
28 |
-
public static function single() {
|
29 |
-
static $single;
|
30 |
-
return empty( $single ) ? $single = new self() : $single;
|
31 |
-
}
|
32 |
-
|
33 |
-
/**
|
34 |
-
* Add the main SiteOrigin layout directory
|
35 |
-
*/
|
36 |
-
public function filter_directories( $directories ){
|
37 |
-
if ( apply_filters( 'siteorigin_panels_layouts_directory_enabled', true ) ) {
|
38 |
-
$directories['siteorigin'] = array(
|
39 |
-
// The title of the layouts directory in the sidebar.
|
40 |
-
'title' => __( 'Layouts Directory', 'siteorigin-panels' ),
|
41 |
-
// The URL of the directory.
|
42 |
-
'url' => self::LAYOUT_URL,
|
43 |
-
// Any additional arguments to pass to the layouts server
|
44 |
-
'args' => array()
|
45 |
-
);
|
46 |
-
}
|
47 |
-
|
48 |
-
return $directories;
|
49 |
-
}
|
50 |
-
|
51 |
-
/**
|
52 |
-
* Get all the layout directories.
|
53 |
-
*
|
54 |
-
* @return array
|
55 |
-
*/
|
56 |
-
public function get_directories(){
|
57 |
-
$directories = apply_filters( 'siteorigin_panels_external_layout_directories', array() );
|
58 |
-
if( empty( $directories ) || ! is_array( $directories ) ) {
|
59 |
-
$directories = array();
|
60 |
-
}
|
61 |
-
|
62 |
-
return $directories;
|
63 |
-
}
|
64 |
-
|
65 |
-
|
66 |
-
/**
|
67 |
-
* Looks through local folders in the active theme and any others filtered in by theme and plugins, to find JSON
|
68 |
-
* prebuilt layouts.
|
69 |
-
*
|
70 |
-
*/
|
71 |
-
public function get_local_layouts() {
|
72 |
-
|
73 |
-
// By default we'll look for layouts in a directory in the active theme
|
74 |
-
$layout_folders = array( get_template_directory() . '/siteorigin-page-builder-layouts' );
|
75 |
-
|
76 |
-
// And the child theme if there is one.
|
77 |
-
if ( is_child_theme() ) {
|
78 |
-
$layout_folders[] = get_stylesheet_directory() . '/siteorigin-page-builder-layouts';
|
79 |
-
}
|
80 |
-
|
81 |
-
// This allows themes and plugins to customize where we look for layouts.
|
82 |
-
$layout_folders = apply_filters( 'siteorigin_panels_local_layouts_directories', $layout_folders );
|
83 |
-
|
84 |
-
$layouts = array();
|
85 |
-
foreach ( $layout_folders as $folder ) {
|
86 |
-
$folder = realpath($folder);
|
87 |
-
if ( file_exists( $folder ) && is_dir( $folder ) ) {
|
88 |
-
$files = list_files( $folder, 1 );
|
89 |
-
if ( empty( $files ) ) {
|
90 |
-
continue;
|
91 |
-
}
|
92 |
-
|
93 |
-
foreach ( $files as $file ) {
|
94 |
-
|
95 |
-
if ( function_exists( 'mime_content_type' ) ) {
|
96 |
-
// get file mime type
|
97 |
-
$mime_type = mime_content_type( $file );
|
98 |
-
|
99 |
-
// Valid if text files.
|
100 |
-
$valid_file_type = strpos( $mime_type, 'text/' ) === 0;
|
101 |
-
} else {
|
102 |
-
// If `mime_content_type` isn't available, just check file extension.
|
103 |
-
$ext = pathinfo( $file, PATHINFO_EXTENSION );
|
104 |
-
|
105 |
-
// skip files which don't have a `.json` extension.
|
106 |
-
$valid_file_type = ! empty( $ext ) && $ext === 'json';
|
107 |
-
}
|
108 |
-
|
109 |
-
if ( ! $valid_file_type ) {
|
110 |
-
continue;
|
111 |
-
}
|
112 |
-
|
113 |
-
// get file contents
|
114 |
-
$file_contents = file_get_contents( $file );
|
115 |
-
|
116 |
-
// skip if file_get_contents fails
|
117 |
-
if ( $file_contents === false ) {
|
118 |
-
continue;
|
119 |
-
}
|
120 |
-
|
121 |
-
// json decode
|
122 |
-
$panels_data = json_decode( $file_contents, true );
|
123 |
-
|
124 |
-
if ( ! empty( $panels_data ) ) {
|
125 |
-
// get file name by stripping out folder path and .json extension
|
126 |
-
$file_name = str_replace( array( $folder . '/', '.json' ), '', $file );
|
127 |
-
|
128 |
-
// get name: check for id or name else use filename
|
129 |
-
$panels_data['id'] = sanitize_title_with_dashes( $this->get_layout_id( $panels_data, $file_name ) );
|
130 |
-
|
131 |
-
if ( empty( $panels_data['name'] ) ) {
|
132 |
-
$panels_data['name'] = $file_name;
|
133 |
-
}
|
134 |
-
|
135 |
-
$panels_data['name'] = sanitize_text_field( $panels_data['name'] );
|
136 |
-
|
137 |
-
// get screenshot: check for screenshot prop else try use image file with same filename.
|
138 |
-
$panels_data['screenshot'] = $this->get_layout_file_screenshot( $panels_data, $folder, $file_name );
|
139 |
-
|
140 |
-
// set item on layouts array
|
141 |
-
$layouts[ $panels_data['id'] ] = $panels_data;
|
142 |
-
}
|
143 |
-
}
|
144 |
-
}
|
145 |
-
}
|
146 |
-
|
147 |
-
return $layouts;
|
148 |
-
}
|
149 |
-
|
150 |
-
private function get_layout_id( $layout_data, $fallback ) {
|
151 |
-
if ( ! empty( $layout_data['id'] ) ) {
|
152 |
-
return $layout_data['id'];
|
153 |
-
} else if ( ! empty( $layout_data['name'] ) ) {
|
154 |
-
return $layout_data['name'];
|
155 |
-
} else {
|
156 |
-
return $fallback;
|
157 |
-
}
|
158 |
-
}
|
159 |
-
|
160 |
-
private function get_layout_file_screenshot( $panels_data, $folder_path, $file_name ) {
|
161 |
-
if ( ! empty( $panels_data['screenshot'] ) ) {
|
162 |
-
return $panels_data['screenshot'];
|
163 |
-
} else {
|
164 |
-
$paths = glob( $folder_path . "/$file_name.{jpg,jpeg,gif,png}", GLOB_BRACE );
|
165 |
-
// Highlander Condition. There can be only one.
|
166 |
-
$screenshot_path = empty( $paths ) ? '' : wp_normalize_path( $paths[0] );
|
167 |
-
$wp_content_dir = wp_normalize_path( WP_CONTENT_DIR );
|
168 |
-
$screenshot_url = '';
|
169 |
-
if ( file_exists( $screenshot_path ) &&
|
170 |
-
strrpos( $screenshot_path, $wp_content_dir ) === 0 ) {
|
171 |
-
|
172 |
-
$screenshot_url = str_replace( $wp_content_dir, content_url(), $screenshot_path );
|
173 |
-
}
|
174 |
-
|
175 |
-
return $screenshot_url;
|
176 |
-
}
|
177 |
-
}
|
178 |
-
|
179 |
-
/**
|
180 |
-
* Gets all the prebuilt layouts.
|
181 |
-
*/
|
182 |
-
function action_get_prebuilt_layouts() {
|
183 |
-
if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
|
184 |
-
wp_die( __( 'Invalid request.', 'siteorigin-panels' ), 403 );
|
185 |
-
}
|
186 |
-
|
187 |
-
// Get any layouts that the current user could edit.
|
188 |
-
header( 'content-type: application/json' );
|
189 |
-
|
190 |
-
$type = ! empty( $_REQUEST['type'] ) ? $_REQUEST['type'] : 'directory-siteorigin';
|
191 |
-
$search = ! empty( $_REQUEST['search'] ) ? trim( strtolower( $_REQUEST['search'] ) ) : '';
|
192 |
-
$page_num = ! empty( $_REQUEST['page'] ) ? intval( $_REQUEST['page'] ) : 1;
|
193 |
-
|
194 |
-
$return = array(
|
195 |
-
'title' => '',
|
196 |
-
'items' => array()
|
197 |
-
);
|
198 |
-
if ( $type == 'prebuilt' ) {
|
199 |
-
$return['title'] = __( 'Theme Defined Layouts', 'siteorigin-panels' );
|
200 |
-
|
201 |
-
// This is for theme bundled prebuilt directories
|
202 |
-
$layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
|
203 |
-
|
204 |
-
foreach ( $layouts as $id => $vals ) {
|
205 |
-
if ( ! empty( $search ) && strpos( strtolower( $vals['name'] ), $search ) === false ) {
|
206 |
-
continue;
|
207 |
-
}
|
208 |
-
|
209 |
-
$return['items'][] = array(
|
210 |
-
'title' => $vals['name'],
|
211 |
-
'id' => $id,
|
212 |
-
'type' => 'prebuilt',
|
213 |
-
'description' => isset( $vals['description'] ) ? $vals['description'] : '',
|
214 |
-
'screenshot' => ! empty( $vals['screenshot'] ) ? $vals['screenshot'] : ''
|
215 |
-
);
|
216 |
-
}
|
217 |
-
|
218 |
-
$return['max_num_pages'] = 1;
|
219 |
-
} elseif ( substr( $type, 0, 10 ) == 'directory-' ) {
|
220 |
-
$return['title'] = __( 'Layouts Directory', 'siteorigin-panels' );
|
221 |
-
|
222 |
-
// This is a query of the prebuilt layout directory
|
223 |
-
$query = array();
|
224 |
-
if ( ! empty( $search ) ) {
|
225 |
-
$query['search'] = $search;
|
226 |
-
}
|
227 |
-
$query['page'] = $page_num;
|
228 |
-
|
229 |
-
$directory_id = str_replace( 'directory-', '', $type );
|
230 |
-
$directories = $this->get_directories();
|
231 |
-
$directory = ! empty( $directories[ $directory_id ] ) ? $directories[ $directory_id ] : false;
|
232 |
-
|
233 |
-
if( empty( $directory ) ) {
|
234 |
-
return false;
|
235 |
-
}
|
236 |
-
|
237 |
-
$url = add_query_arg( $query, $directory[ 'url' ] . 'wp-admin/admin-ajax.php?action=query_layouts' );
|
238 |
-
if( ! empty( $directory[ 'args' ] ) && is_array( $directory[ 'args' ] ) ) {
|
239 |
-
$url = add_query_arg( $directory[ 'args' ], $url );
|
240 |
-
}
|
241 |
-
|
242 |
-
$url = apply_filters( 'siteorigin_panels_layouts_directory_url', $url );
|
243 |
-
$response = wp_remote_get( $url );
|
244 |
-
|
245 |
-
if ( is_array( $response ) && $response['response']['code'] == 200 ) {
|
246 |
-
$results = json_decode( $response['body'], true );
|
247 |
-
if ( ! empty( $results ) && ! empty( $results['items'] ) ) {
|
248 |
-
foreach ( $results['items'] as $item ) {
|
249 |
-
$item['id'] = $item['slug'];
|
250 |
-
$item['type'] = $type;
|
251 |
-
|
252 |
-
if( empty( $item['screenshot'] ) && ! empty( $item['preview'] ) ) {
|
253 |
-
$preview_url = add_query_arg( 'screenshot', 'true', $item[ 'preview' ] );
|
254 |
-
$item['screenshot'] = 'https://s.wordpress.com/mshots/v1/' . urlencode( $preview_url ) . '?w=700';
|
255 |
-
}
|
256 |
-
|
257 |
-
$return['items'][] = $item;
|
258 |
-
}
|
259 |
-
}
|
260 |
-
|
261 |
-
$return['max_num_pages'] = $results['max_num_pages'];
|
262 |
-
}
|
263 |
-
} elseif ( strpos( $type, 'clone_' ) !== false ) {
|
264 |
-
// Check that the user can view the given page types
|
265 |
-
$post_type = get_post_type_object( str_replace( 'clone_', '', $type ) );
|
266 |
-
if( empty( $post_type ) ) {
|
267 |
-
return;
|
268 |
-
}
|
269 |
-
|
270 |
-
$return['title'] = sprintf( __( 'Clone %s', 'siteorigin-panels' ), esc_html( $post_type->labels->singular_name ) );
|
271 |
-
|
272 |
-
global $wpdb;
|
273 |
-
$user_can_read_private = ( $post_type->name == 'post' && current_user_can( 'read_private_posts' ) || ( $post_type->name == 'page' && current_user_can( 'read_private_pages' ) ) );
|
274 |
-
$include_private = $user_can_read_private ? "OR posts.post_status = 'private' " : "";
|
275 |
-
|
276 |
-
// Select only the posts with the given post type that also have panels_data
|
277 |
-
$results = $wpdb->get_results( "
|
278 |
-
SELECT SQL_CALC_FOUND_ROWS DISTINCT ID, post_title, meta.meta_value
|
279 |
-
FROM {$wpdb->posts} AS posts
|
280 |
-
JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
|
281 |
-
WHERE
|
282 |
-
posts.post_type = '" . esc_sql( $post_type->name ) . "'
|
283 |
-
AND meta.meta_key = 'panels_data'
|
284 |
-
" . ( ! empty( $search ) ? 'AND posts.post_title LIKE "%' . esc_sql( $search ) . '%"' : '' ) . "
|
285 |
-
AND ( posts.post_status = 'publish' OR posts.post_status = 'draft' " . $include_private . ")
|
286 |
-
ORDER BY post_date DESC
|
287 |
-
LIMIT 16 OFFSET " . intval( ( $page_num - 1 ) * 16 ) );
|
288 |
-
$total_posts = $wpdb->get_var( "SELECT FOUND_ROWS();" );
|
289 |
-
|
290 |
-
foreach ( $results as $result ) {
|
291 |
-
$thumbnail = get_the_post_thumbnail_url( $result->ID, array( 400, 300 ) );
|
292 |
-
$return['items'][] = array(
|
293 |
-
'id' => $result->ID,
|
294 |
-
'title' => $result->post_title,
|
295 |
-
'type' => $type,
|
296 |
-
'screenshot' => ! empty( $thumbnail ) ? $thumbnail : ''
|
297 |
-
);
|
298 |
-
}
|
299 |
-
|
300 |
-
$return['max_num_pages'] = ceil( $total_posts / 16 );
|
301 |
-
|
302 |
-
} else {
|
303 |
-
// An invalid type. Display an error message.
|
304 |
-
}
|
305 |
-
|
306 |
-
// Add the search part to the title
|
307 |
-
if ( ! empty( $search ) ) {
|
308 |
-
$return['title'] .= __( ' - Results For:', 'siteorigin-panels' ) . ' <em>' . esc_html( $search ) . '</em>';
|
309 |
-
}
|
310 |
-
|
311 |
-
echo json_encode( $return );
|
312 |
-
|
313 |
-
wp_die();
|
314 |
-
}
|
315 |
-
|
316 |
-
/**
|
317 |
-
* Ajax handler to get an individual prebuilt layout
|
318 |
-
*/
|
319 |
-
function action_get_prebuilt_layout() {
|
320 |
-
if ( empty( $_REQUEST['type'] ) ) {
|
321 |
-
wp_die();
|
322 |
-
}
|
323 |
-
if ( empty( $_REQUEST['lid'] ) ) {
|
324 |
-
wp_die();
|
325 |
-
}
|
326 |
-
if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
|
327 |
-
wp_die();
|
328 |
-
}
|
329 |
-
|
330 |
-
header( 'content-type: application/json' );
|
331 |
-
$panels_data = array();
|
332 |
-
$raw_panels_data = false;
|
333 |
-
|
334 |
-
if ( $_REQUEST['type'] == 'prebuilt' ) {
|
335 |
-
$layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
|
336 |
-
$lid = ! empty( $_REQUEST['lid'] ) ? $_REQUEST['lid'] : false;
|
337 |
-
|
338 |
-
if ( empty( $lid ) || empty( $layouts[ $lid ] ) ) {
|
339 |
-
wp_send_json_error( array(
|
340 |
-
'error' => true,
|
341 |
-
'message' => __( 'Missing layout ID or no such layout exists', 'siteorigin-panels' ),
|
342 |
-
) );
|
343 |
-
}
|
344 |
-
|
345 |
-
$layout = $layouts[ $_REQUEST['lid'] ];
|
346 |
-
|
347 |
-
// Fix the format of this layout
|
348 |
-
if( !empty( $layout[ 'filename' ] ) ) {
|
349 |
-
$filename = $layout[ 'filename' ];
|
350 |
-
// Only accept filenames that end with .json
|
351 |
-
if( substr( $filename, -5, 5 ) === '.json' && file_exists( $filename ) ) {
|
352 |
-
$panels_data = json_decode( file_get_contents( $filename ), true );
|
353 |
-
$layout[ 'widgets' ] = ! empty( $panels_data[ 'widgets' ] ) ? $panels_data[ 'widgets' ] : array();
|
354 |
-
$layout[ 'grids' ] = ! empty( $panels_data[ 'grids' ] ) ? $panels_data[ 'grids' ] : array();
|
355 |
-
$layout[ 'grid_cells' ] = ! empty( $panels_data[ 'grid_cells' ] ) ? $panels_data[ 'grid_cells' ] : array();
|
356 |
-
}
|
357 |
-
}
|
358 |
-
|
359 |
-
// A theme or plugin could use this to change the data in the layout
|
360 |
-
$panels_data = apply_filters( 'siteorigin_panels_prebuilt_layout', $layout, $lid );
|
361 |
-
|
362 |
-
// Remove all the layout specific attributes
|
363 |
-
if ( isset( $panels_data['name'] ) ) unset( $panels_data['name'] );
|
364 |
-
if ( isset( $panels_data['screenshot'] ) ) unset( $panels_data['screenshot'] );
|
365 |
-
if ( isset( $panels_data['filename'] ) ) unset( $panels_data['filename'] );
|
366 |
-
|
367 |
-
$raw_panels_data = true;
|
368 |
-
|
369 |
-
} elseif ( substr( $_REQUEST['type'], 0, 10 ) == 'directory-' ) {
|
370 |
-
$directory_id = str_replace( 'directory-', '', $_REQUEST['type'] );
|
371 |
-
$directories = $this->get_directories();
|
372 |
-
$directory = ! empty( $directories[ $directory_id ] ) ? $directories[ $directory_id ] : false;
|
373 |
-
|
374 |
-
if( ! empty( $directory ) ) {
|
375 |
-
$url = $directory[ 'url' ] . 'layout/' . urlencode( $_REQUEST[ 'lid' ] ) . '/?action=download';
|
376 |
-
if( ! empty( $directory[ 'args' ] ) && is_array( $directory[ 'args' ] ) ) {
|
377 |
-
$url = add_query_arg( $directory[ 'args' ], $url );
|
378 |
-
}
|
379 |
-
|
380 |
-
$response = wp_remote_get( $url );
|
381 |
-
if ( $response['response']['code'] == 200 ) {
|
382 |
-
// For now, we'll just pretend to load this
|
383 |
-
$panels_data = json_decode( $response['body'], true );
|
384 |
-
} else {
|
385 |
-
wp_send_json_error( array(
|
386 |
-
'error' => true,
|
387 |
-
'message' => __( 'There was a problem fetching the layout. Please try again later.', 'siteorigin-panels' ),
|
388 |
-
) );
|
389 |
-
}
|
390 |
-
}
|
391 |
-
$raw_panels_data = true;
|
392 |
-
|
393 |
-
} elseif ( current_user_can( 'edit_post', $_REQUEST['lid'] ) ) {
|
394 |
-
$panels_data = get_post_meta( $_REQUEST['lid'], 'panels_data', true );
|
395 |
-
|
396 |
-
// Clear id and timestamp for SO widgets to prevent 'newer content version' notification in widget forms.
|
397 |
-
foreach ( $panels_data['widgets'] as &$widget ) {
|
398 |
-
unset( $widget['_sow_form_id'] );
|
399 |
-
unset( $widget['_sow_form_timestamp'] );
|
400 |
-
}
|
401 |
-
}
|
402 |
-
|
403 |
-
if( $raw_panels_data ) {
|
404 |
-
// This panels_data is flagged as raw, so it needs to be processed.
|
405 |
-
$panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, false );
|
406 |
-
$panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'], array(), true, true );
|
407 |
-
}
|
408 |
-
|
409 |
-
wp_send_json_success( $panels_data );
|
410 |
-
}
|
411 |
-
|
412 |
-
/**
|
413 |
-
* Ajax handler to import a layout
|
414 |
-
*/
|
415 |
-
function action_import_layout() {
|
416 |
-
if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
|
417 |
-
wp_die();
|
418 |
-
}
|
419 |
-
|
420 |
-
if ( ! empty( $_FILES['panels_import_data']['tmp_name'] ) ) {
|
421 |
-
header( 'content-type:application/json' );
|
422 |
-
$json = file_get_contents( $_FILES['panels_import_data']['tmp_name'] );
|
423 |
-
$panels_data = json_decode( $json, true );
|
424 |
-
$panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, false );
|
425 |
-
$panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'], array(), true, true );
|
426 |
-
$json = json_encode( $panels_data );
|
427 |
-
@unlink( $_FILES['panels_import_data']['tmp_name'] );
|
428 |
-
echo $json;
|
429 |
-
}
|
430 |
-
wp_die();
|
431 |
-
}
|
432 |
-
|
433 |
-
/**
|
434 |
-
* Export a given layout as a JSON file.
|
435 |
-
*/
|
436 |
-
function action_export_layout() {
|
437 |
-
if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
|
438 |
-
wp_die();
|
439 |
-
}
|
440 |
-
|
441 |
-
$export_data = wp_unslash( $_POST['panels_export_data'] );
|
442 |
-
|
443 |
-
$decoded_export_data = json_decode( $export_data, true );
|
444 |
-
|
445 |
-
if ( ! empty( $decoded_export_data['name'] ) ) {
|
446 |
-
$decoded_export_data['id'] = sanitize_title_with_dashes( $decoded_export_data['name'] );
|
447 |
-
$filename = $decoded_export_data['id'];
|
448 |
-
} else {
|
449 |
-
$filename = 'layout-' . date( 'dmY' );
|
450 |
-
}
|
451 |
-
|
452 |
-
|
453 |
-
header( 'content-type: application/json' );
|
454 |
-
header( "Content-Disposition: attachment; filename=$filename.json" );
|
455 |
-
|
456 |
-
echo $export_data;
|
457 |
-
|
458 |
-
wp_die();
|
459 |
-
}
|
460 |
-
|
461 |
-
/**
|
462 |
-
* Enable the directory.
|
463 |
-
*/
|
464 |
-
function action_directory_enable() {
|
465 |
-
if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
|
466 |
-
wp_die();
|
467 |
-
}
|
468 |
-
$user = get_current_user_id();
|
469 |
-
update_user_meta( $user, 'so_panels_directory_enabled', true );
|
470 |
-
wp_die();
|
471 |
-
}
|
472 |
-
|
473 |
-
/**
|
474 |
-
* Load a layout from a json file
|
475 |
-
*
|
476 |
-
* @param $id
|
477 |
-
* @param $name
|
478 |
-
* @param $json_file
|
479 |
-
* @param bool $screenshot
|
480 |
-
*
|
481 |
-
* @return array The data for the layout
|
482 |
-
*/
|
483 |
-
public static function load_layout($id, $name, $json_file, $screenshot = false) {
|
484 |
-
$layout_data = json_decode(file_get_contents($json_file), true);
|
485 |
-
$layout_data = apply_filters('siteorigin_panels_load_layout_' . $id, $layout_data);
|
486 |
-
|
487 |
-
$layout_data = array_merge(array(
|
488 |
-
'name' => $name,
|
489 |
-
'screenshot' => $screenshot,
|
490 |
-
), $layout_data);
|
491 |
-
|
492 |
-
return $layout_data;
|
493 |
-
}
|
494 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class SiteOrigin_Panels_Admin
|
5 |
+
*
|
6 |
+
* Handles all the admin and database interactions.
|
7 |
+
*/
|
8 |
+
class SiteOrigin_Panels_Admin_Layouts {
|
9 |
+
|
10 |
+
const LAYOUT_URL = 'https://layouts.siteorigin.com/';
|
11 |
+
|
12 |
+
function __construct() {
|
13 |
+
// Filter all the available external layout directories.
|
14 |
+
add_filter( 'siteorigin_panels_external_layout_directories', array( $this, 'filter_directories' ), 8 );
|
15 |
+
// Filter all the available local layout folders.
|
16 |
+
add_filter( 'siteorigin_panels_prebuilt_layouts', array( $this, 'get_local_layouts' ), 8 );
|
17 |
+
|
18 |
+
add_action( 'wp_ajax_so_panels_layouts_query', array( $this, 'action_get_prebuilt_layouts' ) );
|
19 |
+
add_action( 'wp_ajax_so_panels_get_layout', array( $this, 'action_get_prebuilt_layout' ) );
|
20 |
+
add_action( 'wp_ajax_so_panels_import_layout', array( $this, 'action_import_layout' ) );
|
21 |
+
add_action( 'wp_ajax_so_panels_export_layout', array( $this, 'action_export_layout' ) );
|
22 |
+
add_action( 'wp_ajax_so_panels_directory_enable', array( $this, 'action_directory_enable' ) );
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @return SiteOrigin_Panels_Admin_Layouts
|
27 |
+
*/
|
28 |
+
public static function single() {
|
29 |
+
static $single;
|
30 |
+
return empty( $single ) ? $single = new self() : $single;
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Add the main SiteOrigin layout directory
|
35 |
+
*/
|
36 |
+
public function filter_directories( $directories ){
|
37 |
+
if ( apply_filters( 'siteorigin_panels_layouts_directory_enabled', true ) ) {
|
38 |
+
$directories['siteorigin'] = array(
|
39 |
+
// The title of the layouts directory in the sidebar.
|
40 |
+
'title' => __( 'Layouts Directory', 'siteorigin-panels' ),
|
41 |
+
// The URL of the directory.
|
42 |
+
'url' => self::LAYOUT_URL,
|
43 |
+
// Any additional arguments to pass to the layouts server
|
44 |
+
'args' => array()
|
45 |
+
);
|
46 |
+
}
|
47 |
+
|
48 |
+
return $directories;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Get all the layout directories.
|
53 |
+
*
|
54 |
+
* @return array
|
55 |
+
*/
|
56 |
+
public function get_directories(){
|
57 |
+
$directories = apply_filters( 'siteorigin_panels_external_layout_directories', array() );
|
58 |
+
if( empty( $directories ) || ! is_array( $directories ) ) {
|
59 |
+
$directories = array();
|
60 |
+
}
|
61 |
+
|
62 |
+
return $directories;
|
63 |
+
}
|
64 |
+
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Looks through local folders in the active theme and any others filtered in by theme and plugins, to find JSON
|
68 |
+
* prebuilt layouts.
|
69 |
+
*
|
70 |
+
*/
|
71 |
+
public function get_local_layouts() {
|
72 |
+
|
73 |
+
// By default we'll look for layouts in a directory in the active theme
|
74 |
+
$layout_folders = array( get_template_directory() . '/siteorigin-page-builder-layouts' );
|
75 |
+
|
76 |
+
// And the child theme if there is one.
|
77 |
+
if ( is_child_theme() ) {
|
78 |
+
$layout_folders[] = get_stylesheet_directory() . '/siteorigin-page-builder-layouts';
|
79 |
+
}
|
80 |
+
|
81 |
+
// This allows themes and plugins to customize where we look for layouts.
|
82 |
+
$layout_folders = apply_filters( 'siteorigin_panels_local_layouts_directories', $layout_folders );
|
83 |
+
|
84 |
+
$layouts = array();
|
85 |
+
foreach ( $layout_folders as $folder ) {
|
86 |
+
$folder = realpath($folder);
|
87 |
+
if ( file_exists( $folder ) && is_dir( $folder ) ) {
|
88 |
+
$files = list_files( $folder, 1 );
|
89 |
+
if ( empty( $files ) ) {
|
90 |
+
continue;
|
91 |
+
}
|
92 |
+
|
93 |
+
foreach ( $files as $file ) {
|
94 |
+
|
95 |
+
if ( function_exists( 'mime_content_type' ) ) {
|
96 |
+
// get file mime type
|
97 |
+
$mime_type = mime_content_type( $file );
|
98 |
+
|
99 |
+
// Valid if text files.
|
100 |
+
$valid_file_type = strpos( $mime_type, 'text/' ) === 0;
|
101 |
+
} else {
|
102 |
+
// If `mime_content_type` isn't available, just check file extension.
|
103 |
+
$ext = pathinfo( $file, PATHINFO_EXTENSION );
|
104 |
+
|
105 |
+
// skip files which don't have a `.json` extension.
|
106 |
+
$valid_file_type = ! empty( $ext ) && $ext === 'json';
|
107 |
+
}
|
108 |
+
|
109 |
+
if ( ! $valid_file_type ) {
|
110 |
+
continue;
|
111 |
+
}
|
112 |
+
|
113 |
+
// get file contents
|
114 |
+
$file_contents = file_get_contents( $file );
|
115 |
+
|
116 |
+
// skip if file_get_contents fails
|
117 |
+
if ( $file_contents === false ) {
|
118 |
+
continue;
|
119 |
+
}
|
120 |
+
|
121 |
+
// json decode
|
122 |
+
$panels_data = json_decode( $file_contents, true );
|
123 |
+
|
124 |
+
if ( ! empty( $panels_data ) ) {
|
125 |
+
// get file name by stripping out folder path and .json extension
|
126 |
+
$file_name = str_replace( array( $folder . '/', '.json' ), '', $file );
|
127 |
+
|
128 |
+
// get name: check for id or name else use filename
|
129 |
+
$panels_data['id'] = sanitize_title_with_dashes( $this->get_layout_id( $panels_data, $file_name ) );
|
130 |
+
|
131 |
+
if ( empty( $panels_data['name'] ) ) {
|
132 |
+
$panels_data['name'] = $file_name;
|
133 |
+
}
|
134 |
+
|
135 |
+
$panels_data['name'] = sanitize_text_field( $panels_data['name'] );
|
136 |
+
|
137 |
+
// get screenshot: check for screenshot prop else try use image file with same filename.
|
138 |
+
$panels_data['screenshot'] = $this->get_layout_file_screenshot( $panels_data, $folder, $file_name );
|
139 |
+
|
140 |
+
// set item on layouts array
|
141 |
+
$layouts[ $panels_data['id'] ] = $panels_data;
|
142 |
+
}
|
143 |
+
}
|
144 |
+
}
|
145 |
+
}
|
146 |
+
|
147 |
+
return $layouts;
|
148 |
+
}
|
149 |
+
|
150 |
+
private function get_layout_id( $layout_data, $fallback ) {
|
151 |
+
if ( ! empty( $layout_data['id'] ) ) {
|
152 |
+
return $layout_data['id'];
|
153 |
+
} else if ( ! empty( $layout_data['name'] ) ) {
|
154 |
+
return $layout_data['name'];
|
155 |
+
} else {
|
156 |
+
return $fallback;
|
157 |
+
}
|
158 |
+
}
|
159 |
+
|
160 |
+
private function get_layout_file_screenshot( $panels_data, $folder_path, $file_name ) {
|
161 |
+
if ( ! empty( $panels_data['screenshot'] ) ) {
|
162 |
+
return $panels_data['screenshot'];
|
163 |
+
} else {
|
164 |
+
$paths = glob( $folder_path . "/$file_name.{jpg,jpeg,gif,png}", GLOB_BRACE );
|
165 |
+
// Highlander Condition. There can be only one.
|
166 |
+
$screenshot_path = empty( $paths ) ? '' : wp_normalize_path( $paths[0] );
|
167 |
+
$wp_content_dir = wp_normalize_path( WP_CONTENT_DIR );
|
168 |
+
$screenshot_url = '';
|
169 |
+
if ( file_exists( $screenshot_path ) &&
|
170 |
+
strrpos( $screenshot_path, $wp_content_dir ) === 0 ) {
|
171 |
+
|
172 |
+
$screenshot_url = str_replace( $wp_content_dir, content_url(), $screenshot_path );
|
173 |
+
}
|
174 |
+
|
175 |
+
return $screenshot_url;
|
176 |
+
}
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Gets all the prebuilt layouts.
|
181 |
+
*/
|
182 |
+
function action_get_prebuilt_layouts() {
|
183 |
+
if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
|
184 |
+
wp_die( __( 'Invalid request.', 'siteorigin-panels' ), 403 );
|
185 |
+
}
|
186 |
+
|
187 |
+
// Get any layouts that the current user could edit.
|
188 |
+
header( 'content-type: application/json' );
|
189 |
+
|
190 |
+
$type = ! empty( $_REQUEST['type'] ) ? $_REQUEST['type'] : 'directory-siteorigin';
|
191 |
+
$search = ! empty( $_REQUEST['search'] ) ? trim( strtolower( $_REQUEST['search'] ) ) : '';
|
192 |
+
$page_num = ! empty( $_REQUEST['page'] ) ? intval( $_REQUEST['page'] ) : 1;
|
193 |
+
|
194 |
+
$return = array(
|
195 |
+
'title' => '',
|
196 |
+
'items' => array()
|
197 |
+
);
|
198 |
+
if ( $type == 'prebuilt' ) {
|
199 |
+
$return['title'] = __( 'Theme Defined Layouts', 'siteorigin-panels' );
|
200 |
+
|
201 |
+
// This is for theme bundled prebuilt directories
|
202 |
+
$layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
|
203 |
+
|
204 |
+
foreach ( $layouts as $id => $vals ) {
|
205 |
+
if ( ! empty( $search ) && strpos( strtolower( $vals['name'] ), $search ) === false ) {
|
206 |
+
continue;
|
207 |
+
}
|
208 |
+
|
209 |
+
$return['items'][] = array(
|
210 |
+
'title' => $vals['name'],
|
211 |
+
'id' => $id,
|
212 |
+
'type' => 'prebuilt',
|
213 |
+
'description' => isset( $vals['description'] ) ? $vals['description'] : '',
|
214 |
+
'screenshot' => ! empty( $vals['screenshot'] ) ? $vals['screenshot'] : ''
|
215 |
+
);
|
216 |
+
}
|
217 |
+
|
218 |
+
$return['max_num_pages'] = 1;
|
219 |
+
} elseif ( substr( $type, 0, 10 ) == 'directory-' ) {
|
220 |
+
$return['title'] = __( 'Layouts Directory', 'siteorigin-panels' );
|
221 |
+
|
222 |
+
// This is a query of the prebuilt layout directory
|
223 |
+
$query = array();
|
224 |
+
if ( ! empty( $search ) ) {
|
225 |
+
$query['search'] = $search;
|
226 |
+
}
|
227 |
+
$query['page'] = $page_num;
|
228 |
+
|
229 |
+
$directory_id = str_replace( 'directory-', '', $type );
|
230 |
+
$directories = $this->get_directories();
|
231 |
+
$directory = ! empty( $directories[ $directory_id ] ) ? $directories[ $directory_id ] : false;
|
232 |
+
|
233 |
+
if( empty( $directory ) ) {
|
234 |
+
return false;
|
235 |
+
}
|
236 |
+
|
237 |
+
$url = add_query_arg( $query, $directory[ 'url' ] . 'wp-admin/admin-ajax.php?action=query_layouts' );
|
238 |
+
if( ! empty( $directory[ 'args' ] ) && is_array( $directory[ 'args' ] ) ) {
|
239 |
+
$url = add_query_arg( $directory[ 'args' ], $url );
|
240 |
+
}
|
241 |
+
|
242 |
+
$url = apply_filters( 'siteorigin_panels_layouts_directory_url', $url );
|
243 |
+
$response = wp_remote_get( $url );
|
244 |
+
|
245 |
+
if ( is_array( $response ) && $response['response']['code'] == 200 ) {
|
246 |
+
$results = json_decode( $response['body'], true );
|
247 |
+
if ( ! empty( $results ) && ! empty( $results['items'] ) ) {
|
248 |
+
foreach ( $results['items'] as $item ) {
|
249 |
+
$item['id'] = $item['slug'];
|
250 |
+
$item['type'] = $type;
|
251 |
+
|
252 |
+
if( empty( $item['screenshot'] ) && ! empty( $item['preview'] ) ) {
|
253 |
+
$preview_url = add_query_arg( 'screenshot', 'true', $item[ 'preview' ] );
|
254 |
+
$item['screenshot'] = 'https://s.wordpress.com/mshots/v1/' . urlencode( $preview_url ) . '?w=700';
|
255 |
+
}
|
256 |
+
|
257 |
+
$return['items'][] = $item;
|
258 |
+
}
|
259 |
+
}
|
260 |
+
|
261 |
+
$return['max_num_pages'] = $results['max_num_pages'];
|
262 |
+
}
|
263 |
+
} elseif ( strpos( $type, 'clone_' ) !== false ) {
|
264 |
+
// Check that the user can view the given page types
|
265 |
+
$post_type = get_post_type_object( str_replace( 'clone_', '', $type ) );
|
266 |
+
if( empty( $post_type ) ) {
|
267 |
+
return;
|
268 |
+
}
|
269 |
+
|
270 |
+
$return['title'] = sprintf( __( 'Clone %s', 'siteorigin-panels' ), esc_html( $post_type->labels->singular_name ) );
|
271 |
+
|
272 |
+
global $wpdb;
|
273 |
+
$user_can_read_private = ( $post_type->name == 'post' && current_user_can( 'read_private_posts' ) || ( $post_type->name == 'page' && current_user_can( 'read_private_pages' ) ) );
|
274 |
+
$include_private = $user_can_read_private ? "OR posts.post_status = 'private' " : "";
|
275 |
+
|
276 |
+
// Select only the posts with the given post type that also have panels_data
|
277 |
+
$results = $wpdb->get_results( "
|
278 |
+
SELECT SQL_CALC_FOUND_ROWS DISTINCT ID, post_title, meta.meta_value
|
279 |
+
FROM {$wpdb->posts} AS posts
|
280 |
+
JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
|
281 |
+
WHERE
|
282 |
+
posts.post_type = '" . esc_sql( $post_type->name ) . "'
|
283 |
+
AND meta.meta_key = 'panels_data'
|
284 |
+
" . ( ! empty( $search ) ? 'AND posts.post_title LIKE "%' . esc_sql( $search ) . '%"' : '' ) . "
|
285 |
+
AND ( posts.post_status = 'publish' OR posts.post_status = 'draft' " . $include_private . ")
|
286 |
+
ORDER BY post_date DESC
|
287 |
+
LIMIT 16 OFFSET " . intval( ( $page_num - 1 ) * 16 ) );
|
288 |
+
$total_posts = $wpdb->get_var( "SELECT FOUND_ROWS();" );
|
289 |
+
|
290 |
+
foreach ( $results as $result ) {
|
291 |
+
$thumbnail = get_the_post_thumbnail_url( $result->ID, array( 400, 300 ) );
|
292 |
+
$return['items'][] = array(
|
293 |
+
'id' => $result->ID,
|
294 |
+
'title' => $result->post_title,
|
295 |
+
'type' => $type,
|
296 |
+
'screenshot' => ! empty( $thumbnail ) ? $thumbnail : ''
|
297 |
+
);
|
298 |
+
}
|
299 |
+
|
300 |
+
$return['max_num_pages'] = ceil( $total_posts / 16 );
|
301 |
+
|
302 |
+
} else {
|
303 |
+
// An invalid type. Display an error message.
|
304 |
+
}
|
305 |
+
|
306 |
+
// Add the search part to the title
|
307 |
+
if ( ! empty( $search ) ) {
|
308 |
+
$return['title'] .= __( ' - Results For:', 'siteorigin-panels' ) . ' <em>' . esc_html( $search ) . '</em>';
|
309 |
+
}
|
310 |
+
|
311 |
+
echo json_encode( $return );
|
312 |
+
|
313 |
+
wp_die();
|
314 |
+
}
|
315 |
+
|
316 |
+
/**
|
317 |
+
* Ajax handler to get an individual prebuilt layout
|
318 |
+
*/
|
319 |
+
function action_get_prebuilt_layout() {
|
320 |
+
if ( empty( $_REQUEST['type'] ) ) {
|
321 |
+
wp_die();
|
322 |
+
}
|
323 |
+
if ( empty( $_REQUEST['lid'] ) ) {
|
324 |
+
wp_die();
|
325 |
+
}
|
326 |
+
if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
|
327 |
+
wp_die();
|
328 |
+
}
|
329 |
+
|
330 |
+
header( 'content-type: application/json' );
|
331 |
+
$panels_data = array();
|
332 |
+
$raw_panels_data = false;
|
333 |
+
|
334 |
+
if ( $_REQUEST['type'] == 'prebuilt' ) {
|
335 |
+
$layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
|
336 |
+
$lid = ! empty( $_REQUEST['lid'] ) ? $_REQUEST['lid'] : false;
|
337 |
+
|
338 |
+
if ( empty( $lid ) || empty( $layouts[ $lid ] ) ) {
|
339 |
+
wp_send_json_error( array(
|
340 |
+
'error' => true,
|
341 |
+
'message' => __( 'Missing layout ID or no such layout exists', 'siteorigin-panels' ),
|
342 |
+
) );
|
343 |
+
}
|
344 |
+
|
345 |
+
$layout = $layouts[ $_REQUEST['lid'] ];
|
346 |
+
|
347 |
+
// Fix the format of this layout
|
348 |
+
if( !empty( $layout[ 'filename' ] ) ) {
|
349 |
+
$filename = $layout[ 'filename' ];
|
350 |
+
// Only accept filenames that end with .json
|
351 |
+
if( substr( $filename, -5, 5 ) === '.json' && file_exists( $filename ) ) {
|
352 |
+
$panels_data = json_decode( file_get_contents( $filename ), true );
|
353 |
+
$layout[ 'widgets' ] = ! empty( $panels_data[ 'widgets' ] ) ? $panels_data[ 'widgets' ] : array();
|
354 |
+
$layout[ 'grids' ] = ! empty( $panels_data[ 'grids' ] ) ? $panels_data[ 'grids' ] : array();
|
355 |
+
$layout[ 'grid_cells' ] = ! empty( $panels_data[ 'grid_cells' ] ) ? $panels_data[ 'grid_cells' ] : array();
|
356 |
+
}
|
357 |
+
}
|
358 |
+
|
359 |
+
// A theme or plugin could use this to change the data in the layout
|
360 |
+
$panels_data = apply_filters( 'siteorigin_panels_prebuilt_layout', $layout, $lid );
|
361 |
+
|
362 |
+
// Remove all the layout specific attributes
|
363 |
+
if ( isset( $panels_data['name'] ) ) unset( $panels_data['name'] );
|
364 |
+
if ( isset( $panels_data['screenshot'] ) ) unset( $panels_data['screenshot'] );
|
365 |
+
if ( isset( $panels_data['filename'] ) ) unset( $panels_data['filename'] );
|
366 |
+
|
367 |
+
$raw_panels_data = true;
|
368 |
+
|
369 |
+
} elseif ( substr( $_REQUEST['type'], 0, 10 ) == 'directory-' ) {
|
370 |
+
$directory_id = str_replace( 'directory-', '', $_REQUEST['type'] );
|
371 |
+
$directories = $this->get_directories();
|
372 |
+
$directory = ! empty( $directories[ $directory_id ] ) ? $directories[ $directory_id ] : false;
|
373 |
+
|
374 |
+
if( ! empty( $directory ) ) {
|
375 |
+
$url = $directory[ 'url' ] . 'layout/' . urlencode( $_REQUEST[ 'lid' ] ) . '/?action=download';
|
376 |
+
if( ! empty( $directory[ 'args' ] ) && is_array( $directory[ 'args' ] ) ) {
|
377 |
+
$url = add_query_arg( $directory[ 'args' ], $url );
|
378 |
+
}
|
379 |
+
|
380 |
+
$response = wp_remote_get( $url );
|
381 |
+
if ( $response['response']['code'] == 200 ) {
|
382 |
+
// For now, we'll just pretend to load this
|
383 |
+
$panels_data = json_decode( $response['body'], true );
|
384 |
+
} else {
|
385 |
+
wp_send_json_error( array(
|
386 |
+
'error' => true,
|
387 |
+
'message' => __( 'There was a problem fetching the layout. Please try again later.', 'siteorigin-panels' ),
|
388 |
+
) );
|
389 |
+
}
|
390 |
+
}
|
391 |
+
$raw_panels_data = true;
|
392 |
+
|
393 |
+
} elseif ( current_user_can( 'edit_post', $_REQUEST['lid'] ) ) {
|
394 |
+
$panels_data = get_post_meta( $_REQUEST['lid'], 'panels_data', true );
|
395 |
+
|
396 |
+
// Clear id and timestamp for SO widgets to prevent 'newer content version' notification in widget forms.
|
397 |
+
foreach ( $panels_data['widgets'] as &$widget ) {
|
398 |
+
unset( $widget['_sow_form_id'] );
|
399 |
+
unset( $widget['_sow_form_timestamp'] );
|
400 |
+
}
|
401 |
+
}
|
402 |
+
|
403 |
+
if( $raw_panels_data ) {
|
404 |
+
// This panels_data is flagged as raw, so it needs to be processed.
|
405 |
+
$panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, false );
|
406 |
+
$panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'], array(), true, true );
|
407 |
+
}
|
408 |
+
|
409 |
+
wp_send_json_success( $panels_data );
|
410 |
+
}
|
411 |
+
|
412 |
+
/**
|
413 |
+
* Ajax handler to import a layout
|
414 |
+
*/
|
415 |
+
function action_import_layout() {
|
416 |
+
if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
|
417 |
+
wp_die();
|
418 |
+
}
|
419 |
+
|
420 |
+
if ( ! empty( $_FILES['panels_import_data']['tmp_name'] ) ) {
|
421 |
+
header( 'content-type:application/json' );
|
422 |
+
$json = file_get_contents( $_FILES['panels_import_data']['tmp_name'] );
|
423 |
+
$panels_data = json_decode( $json, true );
|
424 |
+
$panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, false );
|
425 |
+
$panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'], array(), true, true );
|
426 |
+
$json = json_encode( $panels_data );
|
427 |
+
@unlink( $_FILES['panels_import_data']['tmp_name'] );
|
428 |
+
echo $json;
|
429 |
+
}
|
430 |
+
wp_die();
|
431 |
+
}
|
432 |
+
|
433 |
+
/**
|
434 |
+
* Export a given layout as a JSON file.
|
435 |
+
*/
|
436 |
+
function action_export_layout() {
|
437 |
+
if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
|
438 |
+
wp_die();
|
439 |
+
}
|
440 |
+
|
441 |
+
$export_data = wp_unslash( $_POST['panels_export_data'] );
|
442 |
+
|
443 |
+
$decoded_export_data = json_decode( $export_data, true );
|
444 |
+
|
445 |
+
if ( ! empty( $decoded_export_data['name'] ) ) {
|
446 |
+
$decoded_export_data['id'] = sanitize_title_with_dashes( $decoded_export_data['name'] );
|
447 |
+
$filename = $decoded_export_data['id'];
|
448 |
+
} else {
|
449 |
+
$filename = 'layout-' . date( 'dmY' );
|
450 |
+
}
|
451 |
+
|
452 |
+
|
453 |
+
header( 'content-type: application/json' );
|
454 |
+
header( "Content-Disposition: attachment; filename=$filename.json" );
|
455 |
+
|
456 |
+
echo $export_data;
|
457 |
+
|
458 |
+
wp_die();
|
459 |
+
}
|
460 |
+
|
461 |
+
/**
|
462 |
+
* Enable the directory.
|
463 |
+
*/
|
464 |
+
function action_directory_enable() {
|
465 |
+
if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
|
466 |
+
wp_die();
|
467 |
+
}
|
468 |
+
$user = get_current_user_id();
|
469 |
+
update_user_meta( $user, 'so_panels_directory_enabled', true );
|
470 |
+
wp_die();
|
471 |
+
}
|
472 |
+
|
473 |
+
/**
|
474 |
+
* Load a layout from a json file
|
475 |
+
*
|
476 |
+
* @param $id
|
477 |
+
* @param $name
|
478 |
+
* @param $json_file
|
479 |
+
* @param bool $screenshot
|
480 |
+
*
|
481 |
+
* @return array The data for the layout
|
482 |
+
*/
|
483 |
+
public static function load_layout($id, $name, $json_file, $screenshot = false) {
|
484 |
+
$layout_data = json_decode(file_get_contents($json_file), true);
|
485 |
+
$layout_data = apply_filters('siteorigin_panels_load_layout_' . $id, $layout_data);
|
486 |
+
|
487 |
+
$layout_data = array_merge(array(
|
488 |
+
'name' => $name,
|
489 |
+
'screenshot' => $screenshot,
|
490 |
+
), $layout_data);
|
491 |
+
|
492 |
+
return $layout_data;
|
493 |
+
}
|
494 |
+
}
|
inc/admin-tutorials.php
DELETED
@@ -1,50 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class SiteOrigin_Panels_Admin_Tutorials {
|
4 |
-
|
5 |
-
function __construct() {
|
6 |
-
add_action( 'wp_ajax_so_panels_get_tutorials', array( $this, 'action_get_tutorials' ) );
|
7 |
-
}
|
8 |
-
|
9 |
-
/**
|
10 |
-
* @return SiteOrigin_Panels_Admin_Tutorials
|
11 |
-
*/
|
12 |
-
public static function single() {
|
13 |
-
static $single;
|
14 |
-
return empty( $single ) ? $single = new self() : $single;
|
15 |
-
}
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Get the latest tutorials from SiteOrigin
|
19 |
-
*/
|
20 |
-
public function action_get_tutorials(){
|
21 |
-
if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
|
22 |
-
wp_die();
|
23 |
-
}
|
24 |
-
|
25 |
-
$user = get_current_user_id();
|
26 |
-
update_user_meta( $user, 'so_panels_tutorials_enabled', true );
|
27 |
-
|
28 |
-
header( 'content-type:application/json' );
|
29 |
-
|
30 |
-
$tutorials = get_transient( 'siteorigin_panels_tutorials' );
|
31 |
-
|
32 |
-
if( empty( $tutorials ) ) {
|
33 |
-
$response = wp_remote_get('https://siteorigin.com/wp-json/siteorigin/v1/tutorials/page-builder/');
|
34 |
-
if ( is_array( $response ) && $response['response']['code'] == 200 ) {
|
35 |
-
$tutorials = json_decode( $response['body'] );
|
36 |
-
set_transient( 'siteorigin_panels_tutorials', $tutorials, 86400 );
|
37 |
-
}
|
38 |
-
else {
|
39 |
-
$tutorials = array(
|
40 |
-
'error' => __( 'Error loading latest tutorials. Please try again after a few minutes.', 'siteorigin-panels' ),
|
41 |
-
);
|
42 |
-
}
|
43 |
-
}
|
44 |
-
|
45 |
-
echo json_encode( $tutorials );
|
46 |
-
|
47 |
-
wp_die();
|
48 |
-
}
|
49 |
-
|
50 |
-
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
inc/admin-widget-dialog.php
CHANGED
@@ -1,193 +1,193 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class SiteOrigin_Panels_Admin_Widget_Dialog {
|
4 |
-
|
5 |
-
function __construct() {
|
6 |
-
add_filter( 'siteorigin_panels_widgets', array( $this, 'add_recommended_widgets' ) );
|
7 |
-
add_filter( 'siteorigin_panels_widget_dialog_tabs', array( $this, 'add_widgets_dialog_tabs' ), 20 );
|
8 |
-
}
|
9 |
-
|
10 |
-
/**
|
11 |
-
* @return SiteOrigin_Panels_Admin_Widget_Dialog
|
12 |
-
*/
|
13 |
-
public static function single() {
|
14 |
-
static $single;
|
15 |
-
return empty( $single ) ? $single = new self() : $single;
|
16 |
-
}
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Add some default recommended widgets.
|
20 |
-
*
|
21 |
-
* @param $widgets
|
22 |
-
*
|
23 |
-
* @return array
|
24 |
-
*/
|
25 |
-
function add_recommended_widgets( $widgets ) {
|
26 |
-
|
27 |
-
if ( ! empty( $widgets['WP_Widget_Black_Studio_TinyMCE'] ) ) {
|
28 |
-
$widgets['WP_Widget_Black_Studio_TinyMCE']['groups'] = array( 'recommended' );
|
29 |
-
$widgets['WP_Widget_Black_Studio_TinyMCE']['icon'] = 'dashicons dashicons-edit';
|
30 |
-
}
|
31 |
-
|
32 |
-
if ( siteorigin_panels_setting( 'recommended-widgets' ) ) {
|
33 |
-
// Add in all the widgets bundle widgets
|
34 |
-
$widgets = wp_parse_args(
|
35 |
-
$widgets,
|
36 |
-
include plugin_dir_path( __FILE__ ) . 'data/widgets-bundle.php'
|
37 |
-
);
|
38 |
-
}
|
39 |
-
|
40 |
-
foreach ( $widgets as $class => $data ) {
|
41 |
-
if ( strpos( $class, 'SiteOrigin_Panels_Widgets_' ) === 0 || strpos( $class, 'SiteOrigin_Panels_Widget_' ) === 0 ) {
|
42 |
-
$widgets[ $class ]['groups'] = array( 'panels' );
|
43 |
-
}
|
44 |
-
}
|
45 |
-
|
46 |
-
if ( ! empty( $widgets['SiteOrigin_Panels_Widgets_Layout'] ) ) {
|
47 |
-
$widgets['SiteOrigin_Panels_Widgets_Layout']['icon'] = 'dashicons dashicons-analytics';
|
48 |
-
}
|
49 |
-
|
50 |
-
$wordpress_widgets = array(
|
51 |
-
'WP_Widget_Pages',
|
52 |
-
'WP_Widget_Links',
|
53 |
-
'WP_Widget_Search',
|
54 |
-
'WP_Widget_Archives',
|
55 |
-
'WP_Widget_Meta',
|
56 |
-
'WP_Widget_Calendar',
|
57 |
-
'WP_Widget_Text',
|
58 |
-
'WP_Widget_Categories',
|
59 |
-
'WP_Widget_Recent_Posts',
|
60 |
-
'WP_Widget_Recent_Comments',
|
61 |
-
'WP_Widget_RSS',
|
62 |
-
'WP_Widget_Tag_Cloud',
|
63 |
-
'WP_Nav_Menu_Widget',
|
64 |
-
);
|
65 |
-
|
66 |
-
foreach ( $wordpress_widgets as $wordpress_widget ) {
|
67 |
-
if ( isset( $widgets[ $wordpress_widget ] ) ) {
|
68 |
-
$widgets[ $wordpress_widget ]['groups'] = array( 'wordpress' );
|
69 |
-
$widgets[ $wordpress_widget ]['icon'] = 'dashicons dashicons-wordpress';
|
70 |
-
}
|
71 |
-
}
|
72 |
-
|
73 |
-
// Third-party plugins dettection.
|
74 |
-
foreach ( $widgets as $widget_id => &$widget ) {
|
75 |
-
if ( strpos( $widget_id, 'WC_' ) === 0 || strpos( $widget_id, 'WooCommerce' ) !== false ) {
|
76 |
-
$widget['groups'][] = 'woocommerce';
|
77 |
-
}
|
78 |
-
if ( strpos( $widget_id, 'BBP_' ) === 0 || strpos( $widget_id, 'BBPress' ) !== false ) {
|
79 |
-
$widget['groups'][] = 'bbpress';
|
80 |
-
}
|
81 |
-
if ( strpos( $widget_id, 'Jetpack' ) !== false || strpos( $widget['title'], 'Jetpack' ) !== false ) {
|
82 |
-
$widget['groups'][] = 'jetpack';
|
83 |
-
}
|
84 |
-
}
|
85 |
-
|
86 |
-
return $widgets;
|
87 |
-
}
|
88 |
-
|
89 |
-
/**
|
90 |
-
* Add tabs to the widget dialog
|
91 |
-
*
|
92 |
-
* @param $tabs
|
93 |
-
*
|
94 |
-
* @return array
|
95 |
-
*/
|
96 |
-
function add_widgets_dialog_tabs( $tabs ) {
|
97 |
-
|
98 |
-
$tabs['widgets_bundle'] = array(
|
99 |
-
'title' => __( 'Widgets Bundle', 'siteorigin-panels' ),
|
100 |
-
'filter' => array(
|
101 |
-
'groups' => array( 'so-widgets-bundle' )
|
102 |
-
)
|
103 |
-
);
|
104 |
-
|
105 |
-
if ( class_exists( 'SiteOrigin_Widgets_Bundle' ) ) {
|
106 |
-
// Add a message about enabling more widgets
|
107 |
-
$tabs['widgets_bundle']['message'] = preg_replace(
|
108 |
-
array(
|
109 |
-
'/1\{ *(.*?) *\}/'
|
110 |
-
),
|
111 |
-
array(
|
112 |
-
'<a href="' . admin_url( 'plugins.php?page=so-widgets-plugins' ) . '">$1</a>'
|
113 |
-
),
|
114 |
-
__( 'Enable more widgets in the 1{Widgets Bundle settings}.', 'siteorigin-panels' )
|
115 |
-
);
|
116 |
-
} else {
|
117 |
-
// Add a message about installing the widgets bundle
|
118 |
-
$tabs['widgets_bundle']['message'] = preg_replace(
|
119 |
-
'/1\{ *(.*?) *\}/',
|
120 |
-
'<a href="' . siteorigin_panels_plugin_activation_install_url( 'so-widgets-bundle', __( 'SiteOrigin Widgets Bundle', 'siteorigin-panels' ) ) . '">$1</a>',
|
121 |
-
__( 'Install the 1{Widgets Bundle} to get extra widgets.', 'siteorigin-panels' )
|
122 |
-
);
|
123 |
-
}
|
124 |
-
|
125 |
-
// Add the Widgets Bundle message to the main widgets tab
|
126 |
-
$tabs[0]['message'] = $tabs['widgets_bundle']['message'];
|
127 |
-
|
128 |
-
$tabs['page_builder'] = array(
|
129 |
-
'title' => __( 'Page Builder Widgets', 'siteorigin-panels' ),
|
130 |
-
'message' => preg_replace(
|
131 |
-
array(
|
132 |
-
'/1\{ *(.*?) *\}/'
|
133 |
-
),
|
134 |
-
array(
|
135 |
-
'<a href="' . admin_url( 'options-general.php?page=siteorigin_panels' ) . '">$1</a>'
|
136 |
-
),
|
137 |
-
__( 'You can enable the legacy (PB) widgets in the 1{Page Builder settings}.', 'siteorigin-panels' )
|
138 |
-
),
|
139 |
-
'filter' => array(
|
140 |
-
'groups' => array( 'panels' )
|
141 |
-
)
|
142 |
-
);
|
143 |
-
|
144 |
-
$tabs['wordpress'] = array(
|
145 |
-
'title' => __( 'WordPress Widgets', 'siteorigin-panels' ),
|
146 |
-
'filter' => array(
|
147 |
-
'groups' => array( 'wordpress' )
|
148 |
-
)
|
149 |
-
);
|
150 |
-
|
151 |
-
// Check for woocommerce plugin.
|
152 |
-
if ( defined( 'WOOCOMMERCE_VERSION' ) ) {
|
153 |
-
$tabs['woocommerce'] = array(
|
154 |
-
// TRANSLATORS: The name of WordPress plugin
|
155 |
-
'title' => __( 'WooCommerce', 'woocommerce' ),
|
156 |
-
'filter' => array(
|
157 |
-
'groups' => array( 'woocommerce' )
|
158 |
-
)
|
159 |
-
);
|
160 |
-
}
|
161 |
-
|
162 |
-
// Check for jetpack plugin.
|
163 |
-
if ( defined( 'JETPACK__VERSION' ) ) {
|
164 |
-
$tabs['jetpack'] = array(
|
165 |
-
// TRANSLATORS: The name of WordPress plugin
|
166 |
-
'title' => __( 'Jetpack', 'jetpack' ),
|
167 |
-
'filter' => array(
|
168 |
-
'groups' => array( 'jetpack' )
|
169 |
-
),
|
170 |
-
);
|
171 |
-
}
|
172 |
-
|
173 |
-
// Check for bbpress plugin.
|
174 |
-
if ( function_exists( 'bbpress' ) ) {
|
175 |
-
$tabs['bbpress'] = array(
|
176 |
-
// TRANSLATORS: The name of WordPress plugin
|
177 |
-
'title' => __( 'BBPress', 'bbpress' ),
|
178 |
-
'filter' => array(
|
179 |
-
'groups' => array( 'bbpress' )
|
180 |
-
),
|
181 |
-
);
|
182 |
-
}
|
183 |
-
|
184 |
-
$tabs['recommended'] = array(
|
185 |
-
'title' => __( 'Recommended Widgets', 'siteorigin-panels' ),
|
186 |
-
'filter' => array(
|
187 |
-
'groups' => array( 'recommended' )
|
188 |
-
)
|
189 |
-
);
|
190 |
-
|
191 |
-
return $tabs;
|
192 |
-
}
|
193 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class SiteOrigin_Panels_Admin_Widget_Dialog {
|
4 |
+
|
5 |
+
function __construct() {
|
6 |
+
add_filter( 'siteorigin_panels_widgets', array( $this, 'add_recommended_widgets' ) );
|
7 |
+
add_filter( 'siteorigin_panels_widget_dialog_tabs', array( $this, 'add_widgets_dialog_tabs' ), 20 );
|
8 |
+
}
|
9 |
+
|
10 |
+
/**
|
11 |
+
* @return SiteOrigin_Panels_Admin_Widget_Dialog
|
12 |
+
*/
|
13 |
+
public static function single() {
|
14 |
+
static $single;
|
15 |
+
return empty( $single ) ? $single = new self() : $single;
|
16 |
+
}
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Add some default recommended widgets.
|
20 |
+
*
|
21 |
+
* @param $widgets
|
22 |
+
*
|
23 |
+
* @return array
|
24 |
+
*/
|
25 |
+
function add_recommended_widgets( $widgets ) {
|
26 |
+
|
27 |
+
if ( ! empty( $widgets['WP_Widget_Black_Studio_TinyMCE'] ) ) {
|
28 |
+
$widgets['WP_Widget_Black_Studio_TinyMCE']['groups'] = array( 'recommended' );
|
29 |
+
$widgets['WP_Widget_Black_Studio_TinyMCE']['icon'] = 'dashicons dashicons-edit';
|
30 |
+
}
|
31 |
+
|
32 |
+
if ( siteorigin_panels_setting( 'recommended-widgets' ) ) {
|
33 |
+
// Add in all the widgets bundle widgets
|
34 |
+
$widgets = wp_parse_args(
|
35 |
+
$widgets,
|
36 |
+
include plugin_dir_path( __FILE__ ) . 'data/widgets-bundle.php'
|
37 |
+
);
|
38 |
+
}
|
39 |
+
|
40 |
+
foreach ( $widgets as $class => $data ) {
|
41 |
+
if ( strpos( $class, 'SiteOrigin_Panels_Widgets_' ) === 0 || strpos( $class, 'SiteOrigin_Panels_Widget_' ) === 0 ) {
|
42 |
+
$widgets[ $class ]['groups'] = array( 'panels' );
|
43 |
+
}
|
44 |
+
}
|
45 |
+
|
46 |
+
if ( ! empty( $widgets['SiteOrigin_Panels_Widgets_Layout'] ) ) {
|
47 |
+
$widgets['SiteOrigin_Panels_Widgets_Layout']['icon'] = 'dashicons dashicons-analytics';
|
48 |
+
}
|
49 |
+
|
50 |
+
$wordpress_widgets = array(
|
51 |
+
'WP_Widget_Pages',
|
52 |
+
'WP_Widget_Links',
|
53 |
+
'WP_Widget_Search',
|
54 |
+
'WP_Widget_Archives',
|
55 |
+
'WP_Widget_Meta',
|
56 |
+
'WP_Widget_Calendar',
|
57 |
+
'WP_Widget_Text',
|
58 |
+
'WP_Widget_Categories',
|
59 |
+
'WP_Widget_Recent_Posts',
|
60 |
+
'WP_Widget_Recent_Comments',
|
61 |
+
'WP_Widget_RSS',
|
62 |
+
'WP_Widget_Tag_Cloud',
|
63 |
+
'WP_Nav_Menu_Widget',
|
64 |
+
);
|
65 |
+
|
66 |
+
foreach ( $wordpress_widgets as $wordpress_widget ) {
|
67 |
+
if ( isset( $widgets[ $wordpress_widget ] ) ) {
|
68 |
+
$widgets[ $wordpress_widget ]['groups'] = array( 'wordpress' );
|
69 |
+
$widgets[ $wordpress_widget ]['icon'] = 'dashicons dashicons-wordpress';
|
70 |
+
}
|
71 |
+
}
|
72 |
+
|
73 |
+
// Third-party plugins dettection.
|
74 |
+
foreach ( $widgets as $widget_id => &$widget ) {
|
75 |
+
if ( strpos( $widget_id, 'WC_' ) === 0 || strpos( $widget_id, 'WooCommerce' ) !== false ) {
|
76 |
+
$widget['groups'][] = 'woocommerce';
|
77 |
+
}
|
78 |
+
if ( strpos( $widget_id, 'BBP_' ) === 0 || strpos( $widget_id, 'BBPress' ) !== false ) {
|
79 |
+
$widget['groups'][] = 'bbpress';
|
80 |
+
}
|
81 |
+
if ( strpos( $widget_id, 'Jetpack' ) !== false || strpos( $widget['title'], 'Jetpack' ) !== false ) {
|
82 |
+
$widget['groups'][] = 'jetpack';
|
83 |
+
}
|
84 |
+
}
|
85 |
+
|
86 |
+
return $widgets;
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Add tabs to the widget dialog
|
91 |
+
*
|
92 |
+
* @param $tabs
|
93 |
+
*
|
94 |
+
* @return array
|
95 |
+
*/
|
96 |
+
function add_widgets_dialog_tabs( $tabs ) {
|
97 |
+
|
98 |
+
$tabs['widgets_bundle'] = array(
|
99 |
+
'title' => __( 'Widgets Bundle', 'siteorigin-panels' ),
|
100 |
+
'filter' => array(
|
101 |
+
'groups' => array( 'so-widgets-bundle' )
|
102 |
+
)
|
103 |
+
);
|
104 |
+
|
105 |
+
if ( class_exists( 'SiteOrigin_Widgets_Bundle' ) ) {
|
106 |
+
// Add a message about enabling more widgets
|
107 |
+
$tabs['widgets_bundle']['message'] = preg_replace(
|
108 |
+
array(
|
109 |
+
'/1\{ *(.*?) *\}/'
|
110 |
+
),
|
111 |
+
array(
|
112 |
+
'<a href="' . admin_url( 'plugins.php?page=so-widgets-plugins' ) . '">$1</a>'
|
113 |
+
),
|
114 |
+
__( 'Enable more widgets in the 1{Widgets Bundle settings}.', 'siteorigin-panels' )
|
115 |
+
);
|
116 |
+
} else {
|
117 |
+
// Add a message about installing the widgets bundle
|
118 |
+
$tabs['widgets_bundle']['message'] = preg_replace(
|
119 |
+
'/1\{ *(.*?) *\}/',
|
120 |
+
'<a href="' . siteorigin_panels_plugin_activation_install_url( 'so-widgets-bundle', __( 'SiteOrigin Widgets Bundle', 'siteorigin-panels' ) ) . '">$1</a>',
|
121 |
+
__( 'Install the 1{Widgets Bundle} to get extra widgets.', 'siteorigin-panels' )
|
122 |
+
);
|
123 |
+
}
|
124 |
+
|
125 |
+
// Add the Widgets Bundle message to the main widgets tab
|
126 |
+
$tabs[0]['message'] = $tabs['widgets_bundle']['message'];
|
127 |
+
|
128 |
+
$tabs['page_builder'] = array(
|
129 |
+
'title' => __( 'Page Builder Widgets', 'siteorigin-panels' ),
|
130 |
+
'message' => preg_replace(
|
131 |
+
array(
|
132 |
+
'/1\{ *(.*?) *\}/'
|
133 |
+
),
|
134 |
+
array(
|
135 |
+
'<a href="' . admin_url( 'options-general.php?page=siteorigin_panels' ) . '">$1</a>'
|
136 |
+
),
|
137 |
+
__( 'You can enable the legacy (PB) widgets in the 1{Page Builder settings}.', 'siteorigin-panels' )
|
138 |
+
),
|
139 |
+
'filter' => array(
|
140 |
+
'groups' => array( 'panels' )
|
141 |
+
)
|
142 |
+
);
|
143 |
+
|
144 |
+
$tabs['wordpress'] = array(
|
145 |
+
'title' => __( 'WordPress Widgets', 'siteorigin-panels' ),
|
146 |
+
'filter' => array(
|
147 |
+
'groups' => array( 'wordpress' )
|
148 |
+
)
|
149 |
+
);
|
150 |
+
|
151 |
+
// Check for woocommerce plugin.
|
152 |
+
if ( defined( 'WOOCOMMERCE_VERSION' ) ) {
|
153 |
+
$tabs['woocommerce'] = array(
|
154 |
+
// TRANSLATORS: The name of WordPress plugin
|
155 |
+
'title' => __( 'WooCommerce', 'woocommerce' ),
|
156 |
+
'filter' => array(
|
157 |
+
'groups' => array( 'woocommerce' )
|
158 |
+
)
|
159 |
+
);
|
160 |
+
}
|
161 |
+
|
162 |
+
// Check for jetpack plugin.
|
163 |
+
if ( defined( 'JETPACK__VERSION' ) ) {
|
164 |
+
$tabs['jetpack'] = array(
|
165 |
+
// TRANSLATORS: The name of WordPress plugin
|
166 |
+
'title' => __( 'Jetpack', 'jetpack' ),
|
167 |
+
'filter' => array(
|
168 |
+
'groups' => array( 'jetpack' )
|
169 |
+
),
|
170 |
+
);
|
171 |
+
}
|
172 |
+
|
173 |
+
// Check for bbpress plugin.
|
174 |
+
if ( function_exists( 'bbpress' ) ) {
|
175 |
+
$tabs['bbpress'] = array(
|
176 |
+
// TRANSLATORS: The name of WordPress plugin
|
177 |
+
'title' => __( 'BBPress', 'bbpress' ),
|
178 |
+
'filter' => array(
|
179 |
+
'groups' => array( 'bbpress' )
|
180 |
+
),
|
181 |
+
);
|
182 |
+
}
|
183 |
+
|
184 |
+
$tabs['recommended'] = array(
|
185 |
+
'title' => __( 'Recommended Widgets', 'siteorigin-panels' ),
|
186 |
+
'filter' => array(
|
187 |
+
'groups' => array( 'recommended' )
|
188 |
+
)
|
189 |
+
);
|
190 |
+
|
191 |
+
return $tabs;
|
192 |
+
}
|
193 |
+
}
|
inc/admin.php
CHANGED
@@ -1,1485 +1,1485 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Class SiteOrigin_Panels_Admin
|
5 |
-
*
|
6 |
-
* Handles all the admin and database interactions.
|
7 |
-
*/
|
8 |
-
class SiteOrigin_Panels_Admin {
|
9 |
-
|
10 |
-
/**
|
11 |
-
* @var bool Store that we're in the save post action, to prevent infinite loops
|
12 |
-
*/
|
13 |
-
private $in_save_post;
|
14 |
-
|
15 |
-
function __construct() {
|
16 |
-
|
17 |
-
add_action( 'plugin_action_links_siteorigin-panels/siteorigin-panels.php', array(
|
18 |
-
$this,
|
19 |
-
'plugin_action_links'
|
20 |
-
) );
|
21 |
-
|
22 |
-
add_action( 'plugins_loaded', array( $this, 'admin_init_widget_count' ) );
|
23 |
-
|
24 |
-
add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) );
|
25 |
-
add_action( 'admin_init', array( $this, 'save_home_page' ) );
|
26 |
-
add_action( 'save_post', array( $this, 'save_post' ) );
|
27 |
-
|
28 |
-
add_action( 'after_switch_theme', array( $this, 'update_home_on_theme_change' ) );
|
29 |
-
|
30 |
-
// Enqueuing admin scripts
|
31 |
-
add_action( 'admin_print_scripts-post-new.php', array( $this, 'enqueue_admin_scripts' ) );
|
32 |
-
add_action( 'admin_print_scripts-post.php', array( $this, 'enqueue_admin_scripts' ) );
|
33 |
-
add_action( 'admin_print_scripts-appearance_page_so_panels_home_page', array(
|
34 |
-
$this,
|
35 |
-
'enqueue_admin_scripts'
|
36 |
-
) );
|
37 |
-
add_action( 'admin_print_scripts-widgets.php', array( $this, 'enqueue_admin_scripts' ) );
|
38 |
-
add_action( 'admin_print_scripts-edit.php', array( $this, 'footer_column_css' ) );
|
39 |
-
|
40 |
-
// Enqueue the admin styles
|
41 |
-
add_action( 'admin_print_styles-post-new.php', array( $this, 'enqueue_admin_styles' ) );
|
42 |
-
add_action( 'admin_print_styles-post.php', array( $this, 'enqueue_admin_styles' ) );
|
43 |
-
add_action( 'admin_print_styles-appearance_page_so_panels_home_page', array( $this, 'enqueue_admin_styles' ) );
|
44 |
-
add_action( 'admin_print_styles-widgets.php', array( $this, 'enqueue_admin_styles' ) );
|
45 |
-
|
46 |
-
// The help tab
|
47 |
-
add_action( 'load-page.php', array( $this, 'add_help_tab' ), 12 );
|
48 |
-
add_action( 'load-post-new.php', array( $this, 'add_help_tab' ), 12 );
|
49 |
-
add_action( 'load-appearance_page_so_panels_home_page', array( $this, 'add_help_tab' ), 12 );
|
50 |
-
|
51 |
-
add_action( 'customize_controls_print_footer_scripts', array( $this, 'js_templates' ) );
|
52 |
-
|
53 |
-
// Register all the admin actions
|
54 |
-
add_action( 'wp_ajax_so_panels_builder_content', array( $this, 'action_builder_content' ) );
|
55 |
-
add_action( 'wp_ajax_so_panels_widget_form', array( $this, 'action_widget_form' ) );
|
56 |
-
add_action( 'wp_ajax_so_panels_live_editor_preview', array( $this, 'action_live_editor_preview' ) );
|
57 |
-
add_action( 'wp_ajax_so_panels_layout_block_sanitize', array( $this, 'layout_block_sanitize' ) );
|
58 |
-
add_action( 'wp_ajax_so_panels_layout_block_preview', array( $this, 'layout_block_preview' ) );
|
59 |
-
|
60 |
-
// Initialize the additional admin classes.
|
61 |
-
SiteOrigin_Panels_Admin_Widget_Dialog::single();
|
62 |
-
SiteOrigin_Panels_Admin_Widgets_Bundle::single();
|
63 |
-
SiteOrigin_Panels_Admin_Layouts::single();
|
64 |
-
|
65 |
-
// Check to make sure we have all the correct markup
|
66 |
-
SiteOrigin_Panels_Admin_Dashboard::single();
|
67 |
-
|
68 |
-
$this->in_save_post = false;
|
69 |
-
|
70 |
-
|
71 |
-
// Enqueue Yoast compatibility
|
72 |
-
add_action( 'admin_print_scripts-post-new.php', array( $this, 'enqueue_yoast_compat' ), 100 );
|
73 |
-
add_action( 'admin_print_scripts-post.php', array( $this, 'enqueue_yoast_compat' ), 100 );
|
74 |
-
|
75 |
-
// Block editor specific actions
|
76 |
-
if ( function_exists( 'register_block_type' ) ) {
|
77 |
-
add_action( 'admin_notices', array( $this, 'admin_notices' ) );
|
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 |
-
|
87 |
-
/**
|
88 |
-
* @return SiteOrigin_Panels_Admin
|
89 |
-
*/
|
90 |
-
public static function single() {
|
91 |
-
static $single;
|
92 |
-
return empty( $single ) ? $single = new self() : $single;
|
93 |
-
}
|
94 |
-
|
95 |
-
/**
|
96 |
-
* Do some general admin initialization
|
97 |
-
*/
|
98 |
-
public function admin_init_widget_count(){
|
99 |
-
if( siteorigin_panels_setting( 'admin-widget-count' ) ) {
|
100 |
-
|
101 |
-
// Add the custom columns
|
102 |
-
$post_types = siteorigin_panels_setting( 'post-types' );
|
103 |
-
if( ! empty( $post_types ) ) {
|
104 |
-
foreach( $post_types as $post_type ) {
|
105 |
-
add_filter( 'manage_' . $post_type . 's_columns' , array( $this, 'add_custom_column' ) );
|
106 |
-
add_action( 'manage_' . $post_type . 's_custom_column' , array( $this, 'display_custom_column' ), 10, 2 );
|
107 |
-
}
|
108 |
-
}
|
109 |
-
}
|
110 |
-
}
|
111 |
-
|
112 |
-
/**
|
113 |
-
* Check if this is an admin page.
|
114 |
-
*
|
115 |
-
* @return mixed|void
|
116 |
-
*/
|
117 |
-
static function is_admin() {
|
118 |
-
$screen = get_current_screen();
|
119 |
-
$is_panels_page = ( $screen->base == 'post' && in_array( $screen->id, siteorigin_panels_setting( 'post-types' ) ) ) ||
|
120 |
-
in_array( $screen->base, array( 'appearance_page_so_panels_home_page', 'widgets', 'customize' ) ) ||
|
121 |
-
self::is_block_editor();
|
122 |
-
|
123 |
-
return apply_filters( 'siteorigin_panels_is_admin_page', $is_panels_page );
|
124 |
-
}
|
125 |
-
|
126 |
-
/**
|
127 |
-
* Check if the current page is Gutenberg or the Block Ediotr
|
128 |
-
*
|
129 |
-
* @return bool
|
130 |
-
*/
|
131 |
-
static function is_block_editor() {
|
132 |
-
// This is for the Gutenberg plugin.
|
133 |
-
$is_gutenberg_page = function_exists( 'is_gutenberg_page' ) && is_gutenberg_page();
|
134 |
-
// This is for WP 5 with the integrated block editor.
|
135 |
-
$is_block_editor = false;
|
136 |
-
|
137 |
-
if ( function_exists( 'get_current_screen' ) ) {
|
138 |
-
$current_screen = get_current_screen();
|
139 |
-
if ( $current_screen && method_exists( $current_screen, 'is_block_editor' ) ) {
|
140 |
-
$is_block_editor = $current_screen->is_block_editor();
|
141 |
-
}
|
142 |
-
}
|
143 |
-
|
144 |
-
return $is_gutenberg_page || $is_block_editor;
|
145 |
-
}
|
146 |
-
|
147 |
-
|
148 |
-
/**
|
149 |
-
* Add action links to the plugin list for Page Builder.
|
150 |
-
*
|
151 |
-
* @param $links
|
152 |
-
*
|
153 |
-
* @return array
|
154 |
-
*/
|
155 |
-
function plugin_action_links( $links ) {
|
156 |
-
if( ! is_array( $links ) ) {
|
157 |
-
return $links;
|
158 |
-
}
|
159 |
-
|
160 |
-
unset( $links['edit'] );
|
161 |
-
$links[] = '<a href="http://siteorigin.com/threads/plugin-page-builder/">' . __( 'Support Forum', 'siteorigin-panels' ) . '</a>';
|
162 |
-
|
163 |
-
if( SiteOrigin_Panels::display_premium_teaser() ) {
|
164 |
-
$links[] = '<a href="' . esc_url( SiteOrigin_Panels::premium_url() ) . '" style="color: #3db634" target="_blank" rel="noopener noreferrer">' . __('Addons', 'siteorigin-panels') . '</a>';
|
165 |
-
}
|
166 |
-
|
167 |
-
return $links;
|
168 |
-
}
|
169 |
-
|
170 |
-
/**
|
171 |
-
* Callback to register the Page Builder Metaboxes
|
172 |
-
*/
|
173 |
-
function add_meta_boxes() {
|
174 |
-
|
175 |
-
foreach ( siteorigin_panels_setting( 'post-types' ) as $type ) {
|
176 |
-
add_meta_box(
|
177 |
-
'so-panels-panels',
|
178 |
-
__( 'Page Builder', 'siteorigin-panels' ),
|
179 |
-
array( $this, 'render_meta_boxes' ),
|
180 |
-
( string ) $type,
|
181 |
-
'advanced',
|
182 |
-
'high',
|
183 |
-
array(
|
184 |
-
// Ideally when we have panels data for a page we would set this to false and it would cause the
|
185 |
-
// editor to fall back to classic editor, but that's not the case so we just declare it as a `__back_compat_meta_box`.
|
186 |
-
'__back_compat_meta_box' => true,
|
187 |
-
'__block_editor_compatible_meta_box' => false,
|
188 |
-
)
|
189 |
-
);
|
190 |
-
}
|
191 |
-
}
|
192 |
-
|
193 |
-
/**
|
194 |
-
* Render a panel metabox.
|
195 |
-
*
|
196 |
-
* @param $post
|
197 |
-
*/
|
198 |
-
function render_meta_boxes( $post ) {
|
199 |
-
$panels_data = $this->get_current_admin_panels_data();
|
200 |
-
include plugin_dir_path( __FILE__ ) . '../tpl/metabox-panels.php';
|
201 |
-
}
|
202 |
-
|
203 |
-
/**
|
204 |
-
* Save the panels data
|
205 |
-
*
|
206 |
-
* @param $post_id
|
207 |
-
*
|
208 |
-
* @action save_post
|
209 |
-
*/
|
210 |
-
function save_post( $post_id ) {
|
211 |
-
// Check that everything is valid with this save.
|
212 |
-
if(
|
213 |
-
$this->in_save_post ||
|
214 |
-
( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) ||
|
215 |
-
empty( $_POST['_sopanels_nonce'] ) ||
|
216 |
-
! wp_verify_nonce( $_POST['_sopanels_nonce'], 'save' ) ||
|
217 |
-
! current_user_can( 'edit_post', $post_id ) ||
|
218 |
-
! isset( $_POST['panels_data'] )
|
219 |
-
) {
|
220 |
-
return;
|
221 |
-
}
|
222 |
-
$this->in_save_post = true;
|
223 |
-
// Get post from db as it might have been changed and saved by other plugins.
|
224 |
-
$post = get_post( $post_id );
|
225 |
-
$old_panels_data = get_post_meta( $post_id, 'panels_data', true );
|
226 |
-
$panels_data = json_decode( wp_unslash( $_POST['panels_data'] ), true );
|
227 |
-
|
228 |
-
$panels_data['widgets'] = $this->process_raw_widgets(
|
229 |
-
$panels_data['widgets'],
|
230 |
-
! empty( $old_panels_data['widgets'] ) ? $old_panels_data['widgets'] : false,
|
231 |
-
false
|
232 |
-
);
|
233 |
-
|
234 |
-
if ( siteorigin_panels_setting( 'sidebars-emulator' ) ) {
|
235 |
-
$sidebars_emulator = SiteOrigin_Panels_Sidebars_Emulator::single();
|
236 |
-
$panels_data['widgets'] = $sidebars_emulator->generate_sidebar_widget_ids( $panels_data['widgets'], $post_id );
|
237 |
-
}
|
238 |
-
|
239 |
-
$panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
|
240 |
-
$panels_data = apply_filters( 'siteorigin_panels_data_pre_save', $panels_data, $post, $post_id );
|
241 |
-
|
242 |
-
if ( ! empty( $panels_data['widgets'] ) || ! empty( $panels_data['grids'] ) ) {
|
243 |
-
// Use `update_metadata` instead of `update_post_meta` to prevent saving to parent post when it's a revision, e.g. preview.
|
244 |
-
update_metadata( 'post', $post_id, 'panels_data', map_deep( $panels_data, array( 'SiteOrigin_Panels_Admin', 'double_slash_string' ) ) );
|
245 |
-
|
246 |
-
if( siteorigin_panels_setting( 'copy-content' ) ) {
|
247 |
-
// Store a version of the HTML in post_content
|
248 |
-
$post_parent_id = wp_is_post_revision( $post_id );
|
249 |
-
$layout_id = ( ! empty( $post_parent_id ) ) ? $post_parent_id : $post_id;
|
250 |
-
|
251 |
-
SiteOrigin_Panels_Post_Content_Filters::add_filters();
|
252 |
-
$GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] = true;
|
253 |
-
$post_content = SiteOrigin_Panels::renderer()->render( $layout_id, false, $panels_data );
|
254 |
-
$post_css = SiteOrigin_Panels::renderer()->generate_css( $layout_id, $panels_data );
|
255 |
-
SiteOrigin_Panels_Post_Content_Filters::remove_filters();
|
256 |
-
unset( $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] );
|
257 |
-
|
258 |
-
// Update the post_content
|
259 |
-
$post->post_content = $post_content;
|
260 |
-
if( siteorigin_panels_setting( 'copy-styles' ) ) {
|
261 |
-
$post->post_content .= "\n\n";
|
262 |
-
$post->post_content .= '<style type="text/css" class="panels-style" data-panels-style-for-post="' . intval( $layout_id ) . '">';
|
263 |
-
$post->post_content .= '@import url(' . SiteOrigin_Panels::front_css_url() . '); ';
|
264 |
-
$post->post_content .= $post_css;
|
265 |
-
$post->post_content .= '</style>';
|
266 |
-
}
|
267 |
-
wp_update_post( $post );
|
268 |
-
}
|
269 |
-
|
270 |
-
} else {
|
271 |
-
// There are no widgets or rows, so delete the panels data
|
272 |
-
delete_post_meta( $post_id, 'panels_data' );
|
273 |
-
}
|
274 |
-
|
275 |
-
$this->in_save_post = false;
|
276 |
-
}
|
277 |
-
|
278 |
-
/**
|
279 |
-
* Enqueue the panels admin scripts
|
280 |
-
*
|
281 |
-
* @param string $prefix
|
282 |
-
* @param bool $force Should we force the enqueues
|
283 |
-
*
|
284 |
-
* @action admin_print_scripts-post-new.php
|
285 |
-
* @action admin_print_scripts-post.php
|
286 |
-
* @action admin_print_scripts-appearance_page_so_panels_home_page
|
287 |
-
*/
|
288 |
-
function enqueue_admin_scripts( $prefix = '', $force = false ) {
|
289 |
-
$screen = get_current_screen();
|
290 |
-
if ( $force || self::is_admin() ) {
|
291 |
-
// Media is required for row styles
|
292 |
-
wp_enqueue_media();
|
293 |
-
wp_enqueue_script(
|
294 |
-
'so-panels-admin',
|
295 |
-
siteorigin_panels_url( 'js/siteorigin-panels' . SITEORIGIN_PANELS_VERSION_SUFFIX . SITEORIGIN_PANELS_JS_SUFFIX . '.js' ),
|
296 |
-
array(
|
297 |
-
'jquery',
|
298 |
-
'jquery-ui-resizable',
|
299 |
-
'jquery-ui-sortable',
|
300 |
-
'jquery-ui-draggable',
|
301 |
-
'underscore',
|
302 |
-
'backbone',
|
303 |
-
'plupload',
|
304 |
-
'plupload-all'
|
305 |
-
),
|
306 |
-
SITEORIGIN_PANELS_VERSION,
|
307 |
-
true
|
308 |
-
);
|
309 |
-
add_action( 'admin_footer', array( $this, 'js_templates' ) );
|
310 |
-
|
311 |
-
$widgets = $this->get_widgets();
|
312 |
-
$directory_enabled = get_user_meta( get_current_user_id(), 'so_panels_directory_enabled', true );
|
313 |
-
|
314 |
-
// This is the widget we'll use for default text
|
315 |
-
if( ! empty( $widgets[ 'SiteOrigin_Widget_Editor_Widget' ] ) ) $text_widget = 'SiteOrigin_Widget_Editor_Widget';
|
316 |
-
else if( ! empty( $widgets[ 'WP_Widget_Text' ] ) ) $text_widget = 'WP_Widget_Text';
|
317 |
-
else $text_widget = false;
|
318 |
-
$text_widget = apply_filters( 'siteorigin_panels_text_widget_class', $text_widget );
|
319 |
-
|
320 |
-
$user = wp_get_current_user();
|
321 |
-
|
322 |
-
$load_on_attach = siteorigin_panels_setting( 'load-on-attach' ) || isset( $_GET['siteorigin-page-builder'] );
|
323 |
-
wp_localize_script( 'so-panels-admin', 'panelsOptions', array(
|
324 |
-
'user' => ! empty( $user ) ? $user->ID : 0,
|
325 |
-
'ajaxurl' => wp_nonce_url( admin_url( 'admin-ajax.php' ), 'panels_action', '_panelsnonce' ),
|
326 |
-
'widgets' => $widgets,
|
327 |
-
'text_widget' => $text_widget,
|
328 |
-
'widget_dialog_tabs' => apply_filters( 'siteorigin_panels_widget_dialog_tabs', array(
|
329 |
-
0 => array(
|
330 |
-
'title' => __( 'All Widgets', 'siteorigin-panels' ),
|
331 |
-
'filter' => array(
|
332 |
-
'installed' => true,
|
333 |
-
'groups' => ''
|
334 |
-
)
|
335 |
-
)
|
336 |
-
) ),
|
337 |
-
'row_layouts' => apply_filters( 'siteorigin_panels_row_layouts', array() ),
|
338 |
-
'directory_enabled' => ! empty( $directory_enabled ),
|
339 |
-
'copy_content' => siteorigin_panels_setting( 'copy-content' ),
|
340 |
-
'cache' => array(),
|
341 |
-
'instant_open' => siteorigin_panels_setting( 'instant-open-widgets' ),
|
342 |
-
|
343 |
-
// Settings for the contextual menu
|
344 |
-
'contextual' => array(
|
345 |
-
// Developers can change which widgets are displayed by default using this filter
|
346 |
-
'default_widgets' => apply_filters( 'siteorigin_panels_contextual_default_widgets', array(
|
347 |
-
'SiteOrigin_Widget_Editor_Widget',
|
348 |
-
'SiteOrigin_Widget_Button_Widget',
|
349 |
-
'SiteOrigin_Widget_Image_Widget',
|
350 |
-
'SiteOrigin_Panels_Widgets_Layout',
|
351 |
-
) )
|
352 |
-
),
|
353 |
-
|
354 |
-
// General localization messages
|
355 |
-
'loc' => array(
|
356 |
-
'missing_widget' => array(
|
357 |
-
'title' => __( 'Missing Widget', 'siteorigin-panels' ),
|
358 |
-
'description' => __( "Page Builder doesn't know about this widget.", 'siteorigin-panels' ),
|
359 |
-
),
|
360 |
-
'time' => array(
|
361 |
-
// TRANSLATORS: Number of seconds since
|
362 |
-
'seconds' => __( '%d seconds', 'siteorigin-panels' ),
|
363 |
-
// TRANSLATORS: Number of minutes since
|
364 |
-
'minutes' => __( '%d minutes', 'siteorigin-panels' ),
|
365 |
-
// TRANSLATORS: Number of hours since
|
366 |
-
'hours' => __( '%d hours', 'siteorigin-panels' ),
|
367 |
-
|
368 |
-
// TRANSLATORS: A single second since
|
369 |
-
'second' => __( '%d second', 'siteorigin-panels' ),
|
370 |
-
// TRANSLATORS: A single minute since
|
371 |
-
'minute' => __( '%d minute', 'siteorigin-panels' ),
|
372 |
-
// TRANSLATORS: A single hour since
|
373 |
-
'hour' => __( '%d hour', 'siteorigin-panels' ),
|
374 |
-
|
375 |
-
// TRANSLATORS: Time ago - eg. "1 minute before".
|
376 |
-
'ago' => __( '%s before', 'siteorigin-panels' ),
|
377 |
-
'now' => __( 'Now', 'siteorigin-panels' ),
|
378 |
-
),
|
379 |
-
'history' => array(
|
380 |
-
// History messages
|
381 |
-
'current' => __( 'Current', 'siteorigin-panels' ),
|
382 |
-
'revert' => __( 'Original', 'siteorigin-panels' ),
|
383 |
-
'restore' => __( 'Version restored', 'siteorigin-panels' ),
|
384 |
-
'back_to_editor' => __( 'Converted to editor', 'siteorigin-panels' ),
|
385 |
-
|
386 |
-
// Widgets
|
387 |
-
// TRANSLATORS: Message displayed in the history when a widget is deleted
|
388 |
-
'widget_deleted' => __( 'Widget deleted', 'siteorigin-panels' ),
|
389 |
-
// TRANSLATORS: Message displayed in the history when a widget is added
|
390 |
-
'widget_added' => __( 'Widget added', 'siteorigin-panels' ),
|
391 |
-
// TRANSLATORS: Message displayed in the history when a widget is edited
|
392 |
-
'widget_edited' => __( 'Widget edited', 'siteorigin-panels' ),
|
393 |
-
// TRANSLATORS: Message displayed in the history when a widget is duplicated
|
394 |
-
'widget_duplicated' => __( 'Widget duplicated', 'siteorigin-panels' ),
|
395 |
-
// TRANSLATORS: Message displayed in the history when a widget position is changed
|
396 |
-
'widget_moved' => __( 'Widget moved', 'siteorigin-panels' ),
|
397 |
-
|
398 |
-
// Rows
|
399 |
-
// TRANSLATORS: Message displayed in the history when a row is deleted
|
400 |
-
'row_deleted' => __( 'Row deleted', 'siteorigin-panels' ),
|
401 |
-
// TRANSLATORS: Message displayed in the history when a row is added
|
402 |
-
'row_added' => __( 'Row added', 'siteorigin-panels' ),
|
403 |
-
// TRANSLATORS: Message displayed in the history when a row is edited
|
404 |
-
'row_edited' => __( 'Row edited', 'siteorigin-panels' ),
|
405 |
-
// TRANSLATORS: Message displayed in the history when a row position is changed
|
406 |
-
'row_moved' => __( 'Row moved', 'siteorigin-panels' ),
|
407 |
-
// TRANSLATORS: Message displayed in the history when a row is duplicated
|
408 |
-
'row_duplicated' => __( 'Row duplicated', 'siteorigin-panels' ),
|
409 |
-
// TRANSLATORS: Message displayed in the history when a row is pasted
|
410 |
-
'row_pasted' => __( 'Row pasted', 'siteorigin-panels' ),
|
411 |
-
|
412 |
-
// Cells
|
413 |
-
'cell_resized' => __( 'Cell resized', 'siteorigin-panels' ),
|
414 |
-
|
415 |
-
// Prebuilt
|
416 |
-
'prebuilt_loaded' => __( 'Prebuilt layout loaded', 'siteorigin-panels' ),
|
417 |
-
),
|
418 |
-
|
419 |
-
// general localization
|
420 |
-
'prebuilt_loading' => __( 'Loading prebuilt layout', 'siteorigin-panels' ),
|
421 |
-
'confirm_use_builder' => __( "Would you like to copy this editor's existing content to Page Builder?", 'siteorigin-panels' ),
|
422 |
-
'confirm_stop_builder' => __( "Would you like to clear your Page Builder content and revert to using the standard visual editor?", 'siteorigin-panels' ),
|
423 |
-
// TRANSLATORS: This is the title for a widget called "Layout Builder"
|
424 |
-
'layout_widget' => __( 'Layout Builder Widget', 'siteorigin-panels' ),
|
425 |
-
// TRANSLATORS: A standard confirmation message
|
426 |
-
'dropdown_confirm' => __( 'Are you sure?', 'siteorigin-panels' ),
|
427 |
-
// TRANSLATORS: When a layout file is ready to be inserted. %s is the filename.
|
428 |
-
'ready_to_insert' => __( '%s is ready to insert.', 'siteorigin-panels' ),
|
429 |
-
|
430 |
-
// Everything for the contextual menu
|
431 |
-
'contextual' => array(
|
432 |
-
'add_widget_below' => __( 'Add Widget Below', 'siteorigin-panels' ),
|
433 |
-
'add_widget_cell' => __( 'Add Widget to Cell', 'siteorigin-panels' ),
|
434 |
-
'search_widgets' => __( 'Search Widgets', 'siteorigin-panels' ),
|
435 |
-
|
436 |
-
'add_row' => __( 'Add Row', 'siteorigin-panels' ),
|
437 |
-
'column' => __( 'Column', 'siteorigin-panels' ),
|
438 |
-
|
439 |
-
'cell_actions' => __( 'Cell Actions', 'siteorigin-panels' ),
|
440 |
-
'cell_paste_widget' => __( 'Paste Widget', 'siteorigin-panels' ),
|
441 |
-
|
442 |
-
'widget_actions' => __( 'Widget Actions', 'siteorigin-panels' ),
|
443 |
-
'widget_edit' => __( 'Edit Widget', 'siteorigin-panels' ),
|
444 |
-
'widget_duplicate' => __( 'Duplicate Widget', 'siteorigin-panels' ),
|
445 |
-
'widget_delete' => __( 'Delete Widget', 'siteorigin-panels' ),
|
446 |
-
'widget_copy' => __( 'Copy Widget', 'siteorigin-panels' ),
|
447 |
-
'widget_paste' => __( 'Paste Widget Below', 'siteorigin-panels' ),
|
448 |
-
|
449 |
-
'row_actions' => __( 'Row Actions', 'siteorigin-panels' ),
|
450 |
-
'row_edit' => __( 'Edit Row', 'siteorigin-panels' ),
|
451 |
-
'row_duplicate' => __( 'Duplicate Row', 'siteorigin-panels' ),
|
452 |
-
'row_delete' => __( 'Delete Row', 'siteorigin-panels' ),
|
453 |
-
'row_copy' => __( 'Copy Row', 'siteorigin-panels' ),
|
454 |
-
'row_paste' => __( 'Paste Row', 'siteorigin-panels' ),
|
455 |
-
),
|
456 |
-
'draft' => __( 'Draft', 'siteorigin-panels' ),
|
457 |
-
'untitled' => __( 'Untitled', 'siteorigin-panels' ),
|
458 |
-
'row' => array(
|
459 |
-
'add' => __( 'New Row', 'siteorigin-panels' ),
|
460 |
-
'edit' => __( 'Row', 'siteorigin-panels' ),
|
461 |
-
),
|
462 |
-
'welcomeMessage' => array(
|
463 |
-
'addingDisabled' => __( 'Hmmm... Adding layout elements is not enabled. Please check if Page Builder has been configured to allow adding elements.', 'siteorigin-panels' ),
|
464 |
-
'oneEnabled' => __( 'Add a {{%= items[0] %}} to get started.', 'siteorigin-panels' ),
|
465 |
-
'twoEnabled' => __( 'Add a {{%= items[0] %}} or {{%= items[1] %}} to get started.', 'siteorigin-panels' ),
|
466 |
-
'threeEnabled' => __( 'Add a {{%= items[0] %}}, {{%= items[1] %}} or {{%= items[2] %}} to get started.', 'siteorigin-panels' ),
|
467 |
-
'addWidgetButton' => "<a href='#' class='so-tool-button so-widget-add'>" . __( 'Widget', 'siteorigin-panels' ) . "</a>",
|
468 |
-
'addRowButton' => "<a href='#' class='so-tool-button so-row-add'>" . __( 'Row', 'siteorigin-panels' ) . "</a>",
|
469 |
-
'addPrebuiltButton' => "<a href='#' class='so-tool-button so-prebuilt-add'>" . __( 'Prebuilt Layout', 'siteorigin-panels' ) . "</a>",
|
470 |
-
'docsMessage' => sprintf(
|
471 |
-
__( 'Read our %s if you need help.', 'siteorigin-panels' ),
|
472 |
-
"<a href='https://siteorigin.com/page-builder/documentation/' target='_blank' rel='noopener noreferrer'>" . __( 'documentation', 'siteorigin-panels' ) . "</a>"
|
473 |
-
),
|
474 |
-
),
|
475 |
-
),
|
476 |
-
'plupload' => array(
|
477 |
-
'max_file_size' => wp_max_upload_size() . 'b',
|
478 |
-
'url' => wp_nonce_url( admin_url( 'admin-ajax.php' ), 'panels_action', '_panelsnonce' ),
|
479 |
-
'flash_swf_url' => includes_url( 'js/plupload/plupload.flash.swf' ),
|
480 |
-
'silverlight_xap_url' => includes_url( 'js/plupload/plupload.silverlight.xap' ),
|
481 |
-
'filter_title' => __( 'Page Builder layouts', 'siteorigin-panels' ),
|
482 |
-
'error_message' => __( 'Error uploading or importing file.', 'siteorigin-panels' ),
|
483 |
-
),
|
484 |
-
'wpColorPickerOptions' => apply_filters( 'siteorigin_panels_wpcolorpicker_options', array() ),
|
485 |
-
'prebuiltDefaultScreenshot' => siteorigin_panels_url( 'css/images/prebuilt-default.png' ),
|
486 |
-
'loadOnAttach' => $load_on_attach ,
|
487 |
-
'siteoriginWidgetRegex' => str_replace( '*+', '*', get_shortcode_regex( array( 'siteorigin_widget' ) ) ),
|
488 |
-
'forms' => array(
|
489 |
-
'loadingFailed' => __( 'Unknown error. Failed to load the form. Please check your internet connection, contact your web site administrator, or try again later.', 'siteorigin-panels' ),
|
490 |
-
)
|
491 |
-
) );
|
492 |
-
|
493 |
-
$js_widgets = array();
|
494 |
-
if ( $screen->base != 'widgets' ) {
|
495 |
-
// Render all the widget forms. A lot of widgets use this as a chance to enqueue their scripts
|
496 |
-
$original_post = isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : null; // Make sure widgets don't change the global post.
|
497 |
-
global $wp_widget_factory;
|
498 |
-
foreach ( $wp_widget_factory->widgets as $widget_obj ) {
|
499 |
-
ob_start();
|
500 |
-
$return = $widget_obj->form( array() );
|
501 |
-
// These are the new widgets in WP 4.8 which are largely JS based. They only enqueue their own
|
502 |
-
// scripts on the 'widgets' screen.
|
503 |
-
if ( $this->is_core_js_widget( $widget_obj ) && method_exists( $widget_obj, 'enqueue_admin_scripts' ) ) {
|
504 |
-
$widget_obj->enqueue_admin_scripts();
|
505 |
-
}
|
506 |
-
do_action_ref_array( 'in_widget_form', array( &$widget_obj, &$return, array() ) );
|
507 |
-
ob_end_clean();
|
508 |
-
|
509 |
-
// Need to render templates for new WP 4.8 widgets when not on the 'widgets' screen or in the customizer.
|
510 |
-
if ( $this->is_core_js_widget( $widget_obj ) ) {
|
511 |
-
$js_widgets[] = $widget_obj;
|
512 |
-
}
|
513 |
-
}
|
514 |
-
$GLOBALS['post'] = $original_post;
|
515 |
-
}
|
516 |
-
|
517 |
-
// This gives panels a chance to enqueue scripts too, without having to check the screen ID.
|
518 |
-
if ( $screen->base != 'widgets' && $screen->base != 'customize' ) {
|
519 |
-
foreach ( $js_widgets as $js_widget ) {
|
520 |
-
$js_widget->render_control_template_scripts();
|
521 |
-
}
|
522 |
-
do_action( 'siteorigin_panel_enqueue_admin_scripts' );
|
523 |
-
do_action( 'sidebar_admin_setup' );
|
524 |
-
}
|
525 |
-
}
|
526 |
-
}
|
527 |
-
|
528 |
-
public function enqueue_yoast_compat(){
|
529 |
-
if( self::is_admin() && defined( 'WPSEO_FILE' ) && wp_script_is( 'yoast-seo-metabox' ) ) {
|
530 |
-
wp_enqueue_script(
|
531 |
-
'so-panels-yoast-compat',
|
532 |
-
siteorigin_panels_url( 'js/yoast-compat' . SITEORIGIN_PANELS_JS_SUFFIX . '.js' ),
|
533 |
-
array('jquery', 'yoast-seo-metabox' ),
|
534 |
-
SITEORIGIN_PANELS_VERSION,
|
535 |
-
true
|
536 |
-
);
|
537 |
-
}
|
538 |
-
}
|
539 |
-
|
540 |
-
/**
|
541 |
-
* Enqueue the admin panel styles
|
542 |
-
*
|
543 |
-
* @param string $prefix
|
544 |
-
* @param bool $force Should we force the enqueue
|
545 |
-
*
|
546 |
-
* @action admin_print_styles-post-new.php
|
547 |
-
* @action admin_print_styles-post.php
|
548 |
-
*/
|
549 |
-
function enqueue_admin_styles( $prefix = '', $force = false ) {
|
550 |
-
if ( $force || self::is_admin() ) {
|
551 |
-
wp_enqueue_style(
|
552 |
-
'so-panels-admin',
|
553 |
-
siteorigin_panels_url( 'css/admin' . SITEORIGIN_PANELS_CSS_SUFFIX . '.css' ),
|
554 |
-
array( 'wp-color-picker' ),
|
555 |
-
SITEORIGIN_PANELS_VERSION
|
556 |
-
);
|
557 |
-
do_action( 'siteorigin_panel_enqueue_admin_styles' );
|
558 |
-
}
|
559 |
-
}
|
560 |
-
|
561 |
-
/**
|
562 |
-
* Add a help tab to pages that include a Page Builder interface.
|
563 |
-
*
|
564 |
-
* @param $prefix
|
565 |
-
*/
|
566 |
-
function add_help_tab( $prefix ) {
|
567 |
-
$screen = get_current_screen();
|
568 |
-
if (
|
569 |
-
( $screen->base == 'post' && ( in_array( $screen->id, siteorigin_panels_setting( 'post-types' ) ) || $screen->id == '' ) )
|
570 |
-
|| ( $screen->id == 'appearance_page_so_panels_home_page' )
|
571 |
-
) {
|
572 |
-
$screen->add_help_tab( array(
|
573 |
-
'id' => 'panels-help-tab', //unique id for the tab
|
574 |
-
'title' => __( 'Page Builder', 'siteorigin-panels' ), //unique visible title for the tab
|
575 |
-
'callback' => array( $this, 'help_tab_content' )
|
576 |
-
) );
|
577 |
-
}
|
578 |
-
}
|
579 |
-
|
580 |
-
/**
|
581 |
-
* Display the content for the help tab.
|
582 |
-
*/
|
583 |
-
function help_tab_content() {
|
584 |
-
include plugin_dir_path( __FILE__ ) . '../tpl/help.php';
|
585 |
-
}
|
586 |
-
|
587 |
-
/**
|
588 |
-
* Get the Page Builder data for the current admin page.
|
589 |
-
*
|
590 |
-
* @return array
|
591 |
-
*/
|
592 |
-
function get_current_admin_panels_data() {
|
593 |
-
$screen = get_current_screen();
|
594 |
-
|
595 |
-
// Localize the panels with the panels data
|
596 |
-
if ( $screen->base == 'appearance_page_so_panels_home_page' ) {
|
597 |
-
$home_page_id = get_option( 'page_on_front' );
|
598 |
-
if ( empty( $home_page_id ) ) {
|
599 |
-
$home_page_id = get_option( 'siteorigin_panels_home_page_id' );
|
600 |
-
}
|
601 |
-
|
602 |
-
$panels_data = ! empty( $home_page_id ) ? get_post_meta( $home_page_id, 'panels_data', true ) : null;
|
603 |
-
|
604 |
-
if ( is_null( $panels_data ) ) {
|
605 |
-
// Load the default layout
|
606 |
-
$layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
|
607 |
-
|
608 |
-
$home_name = siteorigin_panels_setting( 'home-page-default' ) ? siteorigin_panels_setting( 'home-page-default' ) : 'home';
|
609 |
-
$panels_data = ! empty( $layouts[ $home_name ] ) ? $layouts[ $home_name ] : current( $layouts );
|
610 |
-
} elseif ( empty( $panels_data ) ) {
|
611 |
-
// The current page_on_front isn't using page builder
|
612 |
-
return false;
|
613 |
-
}
|
614 |
-
|
615 |
-
$panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, 'home' );
|
616 |
-
} else {
|
617 |
-
global $post;
|
618 |
-
if ( ! empty( $post ) ) {
|
619 |
-
$panels_data = get_post_meta( $post->ID, 'panels_data', true );
|
620 |
-
$panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, $post->ID );
|
621 |
-
}
|
622 |
-
}
|
623 |
-
|
624 |
-
if ( empty( $panels_data ) ) {
|
625 |
-
$panels_data = array();
|
626 |
-
}
|
627 |
-
|
628 |
-
return $panels_data;
|
629 |
-
}
|
630 |
-
|
631 |
-
/**
|
632 |
-
* Save home page
|
633 |
-
*/
|
634 |
-
function save_home_page() {
|
635 |
-
if ( ! isset( $_POST['_sopanels_home_nonce'] ) || ! wp_verify_nonce( $_POST['_sopanels_home_nonce'], 'save' ) ) {
|
636 |
-
return;
|
637 |
-
}
|
638 |
-
if ( ! current_user_can( 'edit_theme_options' ) ) {
|
639 |
-
return;
|
640 |
-
}
|
641 |
-
if ( ! isset( $_POST['panels_data'] ) ) {
|
642 |
-
return;
|
643 |
-
}
|
644 |
-
|
645 |
-
// Check that the home page ID is set and the home page exists
|
646 |
-
$page_id = get_option( 'page_on_front' );
|
647 |
-
if ( empty( $page_id ) ) {
|
648 |
-
$page_id = get_option( 'siteorigin_panels_home_page_id' );
|
649 |
-
}
|
650 |
-
|
651 |
-
$post_content = wp_unslash( $_POST['post_content'] );
|
652 |
-
|
653 |
-
if ( ! $page_id || get_post_meta( $page_id, 'panels_data', true ) == '' ) {
|
654 |
-
// Lets create a new page
|
655 |
-
$page_id = wp_insert_post( array(
|
656 |
-
// TRANSLATORS: This is the default name given to a user's home page
|
657 |
-
'post_title' => __( 'Home Page', 'siteorigin-panels' ),
|
658 |
-
'post_status' => ! empty( $_POST['siteorigin_panels_home_enabled'] ) ? 'publish' : 'draft',
|
659 |
-
'post_type' => 'page',
|
660 |
-
'post_content' => $post_content,
|
661 |
-
'comment_status' => 'closed',
|
662 |
-
) );
|
663 |
-
update_option( 'page_on_front', $page_id );
|
664 |
-
update_option( 'siteorigin_panels_home_page_id', $page_id );
|
665 |
-
|
666 |
-
// Action triggered when creating a new home page through the custom home page interface
|
667 |
-
do_action( 'siteorigin_panels_create_home_page', $page_id );
|
668 |
-
} else {
|
669 |
-
// `wp_insert_post` does it's own sanitization, but it seems `wp_update_post` doesn't.
|
670 |
-
$post_content = sanitize_post_field( 'post_content', $post_content, $page_id, 'db' );
|
671 |
-
|
672 |
-
// Update the post with changed content to save revision if necessary.
|
673 |
-
wp_update_post( array( 'ID' => $page_id, 'post_content' => $post_content ) );
|
674 |
-
}
|
675 |
-
|
676 |
-
$page = get_post( $page_id );
|
677 |
-
|
678 |
-
// Save the updated page data
|
679 |
-
$old_panels_data = get_post_meta( $page_id, 'panels_data', true );
|
680 |
-
$panels_data = json_decode( wp_unslash( $_POST['panels_data'] ), true );
|
681 |
-
$panels_data['widgets'] = $this->process_raw_widgets(
|
682 |
-
$panels_data['widgets'],
|
683 |
-
! empty( $old_panels_data['widgets'] ) ? $old_panels_data['widgets'] : false,
|
684 |
-
false
|
685 |
-
);
|
686 |
-
|
687 |
-
if ( siteorigin_panels_setting( 'sidebars-emulator' ) ) {
|
688 |
-
$sidebars_emulator = SiteOrigin_Panels_Sidebars_Emulator::single();
|
689 |
-
$panels_data['widgets'] = $sidebars_emulator->generate_sidebar_widget_ids( $panels_data['widgets'], $page_id );
|
690 |
-
}
|
691 |
-
|
692 |
-
$panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
|
693 |
-
$panels_data = apply_filters( 'siteorigin_panels_data_pre_save', $panels_data, $page, $page_id );
|
694 |
-
|
695 |
-
update_post_meta( $page_id, 'panels_data', map_deep( $panels_data, array( 'SiteOrigin_Panels_Admin', 'double_slash_string' ) ) );
|
696 |
-
|
697 |
-
$template = get_post_meta( $page_id, '_wp_page_template', true );
|
698 |
-
$home_template = siteorigin_panels_setting( 'home-template' );
|
699 |
-
if ( ( $template == '' || $template == 'default' ) && ! empty( $home_template ) ) {
|
700 |
-
// Set the home page template
|
701 |
-
update_post_meta( $page_id, '_wp_page_template', $home_template );
|
702 |
-
}
|
703 |
-
|
704 |
-
if ( ! empty( $_POST['siteorigin_panels_home_enabled'] ) ) {
|
705 |
-
update_option( 'show_on_front', 'page' );
|
706 |
-
update_option( 'page_on_front', $page_id );
|
707 |
-
update_option( 'siteorigin_panels_home_page_id', $page_id );
|
708 |
-
wp_publish_post( $page_id );
|
709 |
-
} else {
|
710 |
-
// We're disabling this home page
|
711 |
-
update_option( 'show_on_front', 'posts' );
|
712 |
-
|
713 |
-
// Change the post status to draft
|
714 |
-
$post = get_post( $page_id );
|
715 |
-
if ( $post->post_status != 'draft' ) {
|
716 |
-
global $wpdb;
|
717 |
-
|
718 |
-
$wpdb->update( $wpdb->posts, array( 'post_status' => 'draft' ), array( 'ID' => $post->ID ) );
|
719 |
-
clean_post_cache( $post->ID );
|
720 |
-
|
721 |
-
$old_status = $post->post_status;
|
722 |
-
$post->post_status = 'draft';
|
723 |
-
wp_transition_post_status( 'draft', $old_status, $post );
|
724 |
-
|
725 |
-
do_action( 'edit_post', $post->ID, $post );
|
726 |
-
do_action( "save_post_{$post->post_type}", $post->ID, $post, true );
|
727 |
-
do_action( 'save_post', $post->ID, $post, true );
|
728 |
-
do_action( 'wp_insert_post', $post->ID, $post, true );
|
729 |
-
}
|
730 |
-
}
|
731 |
-
}
|
732 |
-
|
733 |
-
/**
|
734 |
-
* After the theme is switched, change the template on the home page if the theme supports home page functionality.
|
735 |
-
*/
|
736 |
-
function update_home_on_theme_change() {
|
737 |
-
$page_id = get_option( 'page_on_front' );
|
738 |
-
if ( empty( $page_id ) ) {
|
739 |
-
$page_id = get_option( 'siteorigin_panels_home_page_id' );
|
740 |
-
}
|
741 |
-
|
742 |
-
if ( siteorigin_panels_setting( 'home-page' ) && siteorigin_panels_setting( 'home-template' ) && $page_id && get_post_meta( $page_id, 'panels_data', true ) !== '' ) {
|
743 |
-
// Lets update the home page to use the home template that this theme supports
|
744 |
-
update_post_meta( $page_id, '_wp_page_template', siteorigin_panels_setting( 'home-template' ) );
|
745 |
-
}
|
746 |
-
}
|
747 |
-
|
748 |
-
/**
|
749 |
-
* @return array|mixed|void
|
750 |
-
*/
|
751 |
-
function get_widgets() {
|
752 |
-
global $wp_widget_factory;
|
753 |
-
$widgets = array();
|
754 |
-
foreach ( $wp_widget_factory->widgets as $widget_obj ) {
|
755 |
-
$class = get_class( $widget_obj );
|
756 |
-
$widgets[ $class ] = array(
|
757 |
-
'class' => $class,
|
758 |
-
'title' => ! empty( $widget_obj->name ) ? $widget_obj->name : __( 'Untitled Widget', 'siteorigin-panels' ),
|
759 |
-
'description' => ! empty( $widget_obj->widget_options['description'] ) ? $widget_obj->widget_options['description'] : '',
|
760 |
-
'installed' => true,
|
761 |
-
'groups' => array(),
|
762 |
-
);
|
763 |
-
|
764 |
-
// Get Page Builder specific widget options
|
765 |
-
if ( isset( $widget_obj->widget_options['panels_title'] ) ) {
|
766 |
-
$widgets[ $class ]['panels_title'] = $widget_obj->widget_options['panels_title'];
|
767 |
-
}
|
768 |
-
if ( isset( $widget_obj->widget_options['panels_groups'] ) ) {
|
769 |
-
$widgets[ $class ]['groups'] = $widget_obj->widget_options['panels_groups'];
|
770 |
-
}
|
771 |
-
if ( isset( $widget_obj->widget_options['panels_icon'] ) ) {
|
772 |
-
$widgets[ $class ]['icon'] = $widget_obj->widget_options['panels_icon'];
|
773 |
-
}
|
774 |
-
|
775 |
-
}
|
776 |
-
|
777 |
-
// Other plugins can manipulate the list of widgets. Possibly to add recommended widgets
|
778 |
-
$widgets = apply_filters( 'siteorigin_panels_widgets', $widgets );
|
779 |
-
|
780 |
-
// Exclude these temporarily, as they won't work until we have a reliable way to enqueue their admin form scripts.
|
781 |
-
$to_exclude = array(
|
782 |
-
'Jetpack_Gallery_Widget',
|
783 |
-
'WPCOM_Widget_GooglePlus_Badge',
|
784 |
-
'Jetpack_Widget_Social_Icons',
|
785 |
-
'Jetpack_Twitter_Timeline_Widget'
|
786 |
-
);
|
787 |
-
|
788 |
-
foreach ( $to_exclude as $widget_class ) {
|
789 |
-
if ( in_array( $widget_class, $widgets ) ) {
|
790 |
-
unset( $widgets[ $widget_class ] );
|
791 |
-
}
|
792 |
-
}
|
793 |
-
|
794 |
-
// Sort the widgets alphabetically
|
795 |
-
uasort( $widgets, array( $this, 'widgets_sorter' ) );
|
796 |
-
|
797 |
-
return $widgets;
|
798 |
-
}
|
799 |
-
|
800 |
-
/**
|
801 |
-
* Sorts widgets for get_widgets function by title
|
802 |
-
*
|
803 |
-
* @param $a
|
804 |
-
* @param $b
|
805 |
-
*
|
806 |
-
* @return int
|
807 |
-
*/
|
808 |
-
function widgets_sorter( $a, $b ) {
|
809 |
-
if ( empty( $a['title'] ) ) {
|
810 |
-
return - 1;
|
811 |
-
}
|
812 |
-
if ( empty( $b['title'] ) ) {
|
813 |
-
return 1;
|
814 |
-
}
|
815 |
-
|
816 |
-
return $a['title'] > $b['title'] ? 1 : - 1;
|
817 |
-
}
|
818 |
-
|
819 |
-
/**
|
820 |
-
* Process raw widgets that have come from the Page Builder front end.
|
821 |
-
*
|
822 |
-
* @param array $widgets An array of widgets from panels_data.
|
823 |
-
* @param array $old_widgets
|
824 |
-
* @param bool $escape_classes Should the class names be escaped.
|
825 |
-
* @param bool $force
|
826 |
-
*
|
827 |
-
* @return array
|
828 |
-
*/
|
829 |
-
function process_raw_widgets( $widgets, $old_widgets = array(), $escape_classes = false, $force = false ) {
|
830 |
-
if ( empty( $widgets ) || ! is_array( $widgets ) ) {
|
831 |
-
return array();
|
832 |
-
}
|
833 |
-
|
834 |
-
$old_widgets_by_id = array();
|
835 |
-
if( ! empty( $old_widgets ) ) {
|
836 |
-
foreach( $old_widgets as $widget ) {
|
837 |
-
if( ! empty( $widget[ 'panels_info' ][ 'widget_id' ] ) ) {
|
838 |
-
$old_widgets_by_id[ $widget[ 'panels_info' ][ 'widget_id' ] ] = $widget;
|
839 |
-
unset( $old_widgets_by_id[ $widget[ 'panels_info' ][ 'widget_id' ] ][ 'panels_info' ] );
|
840 |
-
}
|
841 |
-
}
|
842 |
-
}
|
843 |
-
|
844 |
-
foreach( $widgets as $i => & $widget ) {
|
845 |
-
if ( ! is_array( $widget ) ) {
|
846 |
-
continue;
|
847 |
-
}
|
848 |
-
|
849 |
-
if ( is_array( $widget ) ) {
|
850 |
-
$info = (array) ( is_array( $widget['panels_info'] ) ? $widget['panels_info'] : $widget['info'] );
|
851 |
-
} else {
|
852 |
-
$info = array();
|
853 |
-
}
|
854 |
-
unset( $widget['info'] );
|
855 |
-
|
856 |
-
$info[ 'class' ] = apply_filters( 'siteorigin_panels_widget_class', $info[ 'class' ] );
|
857 |
-
|
858 |
-
if ( ! empty( $info['raw'] ) || $force ) {
|
859 |
-
$the_widget = SiteOrigin_Panels::get_widget_instance( $info['class'] );
|
860 |
-
if ( ! empty( $the_widget ) &&
|
861 |
-
method_exists( $the_widget, 'update' ) ) {
|
862 |
-
|
863 |
-
if(
|
864 |
-
! empty( $old_widgets_by_id ) &&
|
865 |
-
! empty( $widget[ 'panels_info' ][ 'widget_id' ] ) &&
|
866 |
-
! empty( $old_widgets_by_id[ $widget[ 'panels_info' ][ 'widget_id' ] ] )
|
867 |
-
){
|
868 |
-
$old_widget = $old_widgets_by_id[ $widget[ 'panels_info' ][ 'widget_id' ] ];
|
869 |
-
}
|
870 |
-
else {
|
871 |
-
$old_widget = $widget;
|
872 |
-
}
|
873 |
-
|
874 |
-
/** @var WP_Widget $the_widget */
|
875 |
-
$the_widget = SiteOrigin_Panels::get_widget_instance( $info['class'] );
|
876 |
-
$instance = $the_widget->update( $widget, $old_widget );
|
877 |
-
$instance = apply_filters( 'widget_update_callback', $instance, $widget, $old_widget, $the_widget );
|
878 |
-
|
879 |
-
$widget = $instance;
|
880 |
-
|
881 |
-
unset( $info['raw'] );
|
882 |
-
}
|
883 |
-
}
|
884 |
-
|
885 |
-
if( $escape_classes ) {
|
886 |
-
// Escaping for namespaced widgets
|
887 |
-
$info[ 'class' ] = preg_replace( '/\\\\+/', '\\\\\\\\', $info['class'] );
|
888 |
-
}
|
889 |
-
|
890 |
-
$widget['panels_info'] = $info;
|
891 |
-
}
|
892 |
-
|
893 |
-
return $widgets;
|
894 |
-
}
|
895 |
-
|
896 |
-
/**
|
897 |
-
* Add all the footer JS templates.
|
898 |
-
*/
|
899 |
-
function js_templates() {
|
900 |
-
include plugin_dir_path( __FILE__ ) . '../tpl/js-templates.php';
|
901 |
-
}
|
902 |
-
|
903 |
-
/**
|
904 |
-
* Render a widget form with all the Page Builder specific fields
|
905 |
-
*
|
906 |
-
* @param string $widget_class The class of the widget
|
907 |
-
* @param array $instance Widget values
|
908 |
-
* @param bool $raw
|
909 |
-
* @param string $widget_number
|
910 |
-
*
|
911 |
-
* @return mixed|string The form
|
912 |
-
*/
|
913 |
-
function render_form( $widget_class, $instance = array(), $raw = false, $widget_number = '{$id}' ) {
|
914 |
-
|
915 |
-
$the_widget = SiteOrigin_Panels::get_widget_instance( $widget_class );
|
916 |
-
// This is a chance for plugins to replace missing widgets
|
917 |
-
$the_widget = apply_filters( 'siteorigin_panels_widget_object', $the_widget, $widget_class );
|
918 |
-
|
919 |
-
if ( empty( $the_widget ) || ! is_a( $the_widget, 'WP_Widget' ) ) {
|
920 |
-
$widgets = $this->get_widgets();
|
921 |
-
|
922 |
-
if ( ! empty( $widgets[ $widget_class ] ) && ! empty( $widgets[ $widget_class ]['plugin'] ) ) {
|
923 |
-
// We know about this widget, show a form about installing it.
|
924 |
-
$install_url = siteorigin_panels_plugin_activation_install_url( $widgets[ $widget_class ]['plugin']['slug'], $widgets[ $widget_class ]['plugin']['name'] );
|
925 |
-
$form =
|
926 |
-
'<div class="panels-missing-widget-form">' .
|
927 |
-
'<p>' .
|
928 |
-
preg_replace(
|
929 |
-
array(
|
930 |
-
'/1\{ *(.*?) *\}/',
|
931 |
-
'/2\{ *(.*?) *\}/',
|
932 |
-
),
|
933 |
-
array(
|
934 |
-
'<a href="' . $install_url . '" target="_blank" rel="noopener noreferrer">$1</a>',
|
935 |
-
'<strong>$1</strong>'
|
936 |
-
),
|
937 |
-
sprintf(
|
938 |
-
__( 'You need to install 1{%1$s} to use the widget 2{%2$s}.', 'siteorigin-panels' ),
|
939 |
-
$widgets[ $widget_class ]['plugin']['name'],
|
940 |
-
$widget_class
|
941 |
-
)
|
942 |
-
) .
|
943 |
-
'</p>' .
|
944 |
-
'<p>' . __( "Save and reload this page to start using the widget after you've installed it.", 'siteorigin-panels' ) . '</p>' .
|
945 |
-
'</div>';
|
946 |
-
} else {
|
947 |
-
// This widget is missing, so show a missing widgets form.
|
948 |
-
$form =
|
949 |
-
'<div class="panels-missing-widget-form"><p>' .
|
950 |
-
preg_replace(
|
951 |
-
array(
|
952 |
-
'/1\{ *(.*?) *\}/',
|
953 |
-
'/2\{ *(.*?) *\}/',
|
954 |
-
),
|
955 |
-
array(
|
956 |
-
'<strong>$1</strong>',
|
957 |
-
'<a href="https://siteorigin.com/thread/" target="_blank" rel="noopener noreferrer">$1</a>'
|
958 |
-
),
|
959 |
-
sprintf(
|
960 |
-
__( '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.', 'siteorigin-panels' ),
|
961 |
-
esc_html( $widget_class )
|
962 |
-
)
|
963 |
-
) .
|
964 |
-
'</p></div>';
|
965 |
-
}
|
966 |
-
|
967 |
-
// Allow other themes and plugins to change the missing widget form
|
968 |
-
return apply_filters( 'siteorigin_panels_missing_widget_form', $form, $widget_class, $instance );
|
969 |
-
}
|
970 |
-
|
971 |
-
if ( $raw ) {
|
972 |
-
$instance = $the_widget->update( $instance, $instance );
|
973 |
-
}
|
974 |
-
|
975 |
-
$the_widget->id = 'temp';
|
976 |
-
$the_widget->number = $widget_number;
|
977 |
-
|
978 |
-
ob_start();
|
979 |
-
if ( $this->is_core_js_widget( $the_widget ) ) {
|
980 |
-
?><div class="widget-content"><?php
|
981 |
-
}
|
982 |
-
$return = $the_widget->form( $instance );
|
983 |
-
do_action_ref_array( 'in_widget_form', array( &$the_widget, &$return, $instance ) );
|
984 |
-
if ( $this->is_core_js_widget( $the_widget ) ) {
|
985 |
-
?>
|
986 |
-
</div>
|
987 |
-
<input type="hidden" name="id_base" class="id_base" value="<?php echo esc_attr( $the_widget->id_base ); ?>" />
|
988 |
-
<?php
|
989 |
-
}
|
990 |
-
$form = ob_get_clean();
|
991 |
-
|
992 |
-
// Convert the widget field naming into ones that Page Builder uses
|
993 |
-
$exp = preg_quote( $the_widget->get_field_name( '____' ) );
|
994 |
-
$exp = str_replace( '____', '(.*?)', $exp );
|
995 |
-
$form = preg_replace( '/' . $exp . '/', 'widgets[' . preg_replace( '/\$(\d)/', '\\\$$1', $widget_number ) . '][$1]', $form );
|
996 |
-
|
997 |
-
$form = apply_filters( 'siteorigin_panels_widget_form', $form, $widget_class, $instance );
|
998 |
-
|
999 |
-
// Add all the information fields
|
1000 |
-
return $form;
|
1001 |
-
}
|
1002 |
-
|
1003 |
-
/**
|
1004 |
-
* Checks whether a widget is considered to be a JS widget. I.e. it needs to have scripts and/or styles enqueued for
|
1005 |
-
* it's admin form to work.
|
1006 |
-
*
|
1007 |
-
* Can remove the whitelist of core widgets when all widgets are following a similar pattern.
|
1008 |
-
*
|
1009 |
-
* @param $widget The widget to be tested.
|
1010 |
-
*
|
1011 |
-
* @return bool Whether or not the widget is considered a JS widget.
|
1012 |
-
*/
|
1013 |
-
function is_core_js_widget( $widget ) {
|
1014 |
-
$js_widgets = array(
|
1015 |
-
'WP_Widget_Custom_HTML',
|
1016 |
-
'WP_Widget_Media_Audio',
|
1017 |
-
'WP_Widget_Media_Gallery',
|
1018 |
-
'WP_Widget_Media_Image',
|
1019 |
-
'WP_Widget_Media_Video',
|
1020 |
-
'WP_Widget_Text',
|
1021 |
-
);
|
1022 |
-
|
1023 |
-
$is_js_widget = in_array( get_class( $widget ), $js_widgets ) &&
|
1024 |
-
// Need to check this for `WP_Widget_Text` which was not a JS widget before 4.8
|
1025 |
-
method_exists( $widget, 'render_control_template_scripts' );
|
1026 |
-
|
1027 |
-
return $is_js_widget;
|
1028 |
-
}
|
1029 |
-
|
1030 |
-
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
1031 |
-
// ADMIN AJAX ACTIONS
|
1032 |
-
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
1033 |
-
|
1034 |
-
/**
|
1035 |
-
* Get builder content based on the submitted panels_data.
|
1036 |
-
*/
|
1037 |
-
function action_builder_content() {
|
1038 |
-
header( 'content-type: text/html' );
|
1039 |
-
|
1040 |
-
if ( ! current_user_can( 'edit_post', $_POST['post_id'] ) ) {
|
1041 |
-
wp_die();
|
1042 |
-
}
|
1043 |
-
|
1044 |
-
if ( empty( $_POST['post_id'] ) || empty( $_POST['panels_data'] ) ) {
|
1045 |
-
echo '';
|
1046 |
-
wp_die();
|
1047 |
-
}
|
1048 |
-
|
1049 |
-
// echo the content
|
1050 |
-
$old_panels_data = get_post_meta( $_POST['post_id'], 'panels_data', true );
|
1051 |
-
$panels_data = json_decode( wp_unslash( $_POST['panels_data'] ), true );
|
1052 |
-
$panels_data['widgets'] = $this->process_raw_widgets(
|
1053 |
-
$panels_data['widgets'],
|
1054 |
-
! empty( $old_panels_data['widgets'] ) ? $old_panels_data['widgets'] : false,
|
1055 |
-
false
|
1056 |
-
);
|
1057 |
-
$panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
|
1058 |
-
|
1059 |
-
// Create a version of the builder data for post content
|
1060 |
-
SiteOrigin_Panels_Post_Content_Filters::add_filters();
|
1061 |
-
$GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] = true;
|
1062 |
-
echo SiteOrigin_Panels::renderer()->render( intval( $_POST['post_id'] ), false, $panels_data );
|
1063 |
-
SiteOrigin_Panels_Post_Content_Filters::remove_filters();
|
1064 |
-
unset( $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] );
|
1065 |
-
|
1066 |
-
wp_die();
|
1067 |
-
}
|
1068 |
-
|
1069 |
-
/**
|
1070 |
-
* Display a widget form with the provided data
|
1071 |
-
*/
|
1072 |
-
function action_widget_form() {
|
1073 |
-
if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
|
1074 |
-
wp_die(
|
1075 |
-
__( 'The supplied nonce is invalid.', 'siteorigin-panels' ),
|
1076 |
-
__( 'Invalid nonce.', 'siteorigin-panels' ),
|
1077 |
-
403
|
1078 |
-
);
|
1079 |
-
}
|
1080 |
-
if ( empty( $_REQUEST['widget'] ) ) {
|
1081 |
-
wp_die(
|
1082 |
-
__( 'Please specify the type of widget form to be rendered.', 'siteorigin-panels' ),
|
1083 |
-
__( 'Missing widget type.', 'siteorigin-panels' ),
|
1084 |
-
400
|
1085 |
-
);
|
1086 |
-
}
|
1087 |
-
|
1088 |
-
$request = array_map( 'stripslashes_deep', $_REQUEST );
|
1089 |
-
|
1090 |
-
$widget_class = $request['widget'];
|
1091 |
-
$widget_class = apply_filters( 'siteorigin_panels_widget_class', $widget_class );
|
1092 |
-
$instance = ! empty( $request['instance'] ) ? json_decode( $request['instance'], true ) : array();
|
1093 |
-
|
1094 |
-
$form = $this->render_form( $widget_class, $instance, $_REQUEST['raw'] == 'true' );
|
1095 |
-
$form = apply_filters( 'siteorigin_panels_ajax_widget_form', $form, $widget_class, $instance );
|
1096 |
-
|
1097 |
-
echo $form;
|
1098 |
-
wp_die();
|
1099 |
-
}
|
1100 |
-
|
1101 |
-
/**
|
1102 |
-
* Preview in the live editor when there is no public view of the item
|
1103 |
-
*/
|
1104 |
-
function action_live_editor_preview() {
|
1105 |
-
if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'live-editor-preview' ) ) {
|
1106 |
-
wp_die();
|
1107 |
-
}
|
1108 |
-
|
1109 |
-
include plugin_dir_path( __FILE__ ) . '../tpl/live-editor-preview.php';
|
1110 |
-
|
1111 |
-
exit();
|
1112 |
-
}
|
1113 |
-
|
1114 |
-
/**
|
1115 |
-
* Preview in the block editor.
|
1116 |
-
*/
|
1117 |
-
public function layout_block_preview() {
|
1118 |
-
|
1119 |
-
if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'layout-block-preview' ) ) {
|
1120 |
-
wp_die();
|
1121 |
-
}
|
1122 |
-
|
1123 |
-
$panels_data = json_decode( wp_unslash( $_POST['panelsData'] ), true );
|
1124 |
-
$builder_id = 'gbp' . uniqid();
|
1125 |
-
$panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'], false, true, true );
|
1126 |
-
$panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
|
1127 |
-
$sowb_active = class_exists( 'SiteOrigin_Widgets_Bundle' );
|
1128 |
-
if ( $sowb_active ) {
|
1129 |
-
// We need this to get our widgets bundle to add it's styles inline for previews.
|
1130 |
-
add_filter( 'siteorigin_widgets_is_preview', '__return_true' );
|
1131 |
-
}
|
1132 |
-
$rendered_layout = SiteOrigin_Panels::renderer()->render( $builder_id, true, $panels_data, $layout_data, true );
|
1133 |
-
|
1134 |
-
// Need to explicitly call `siteorigin_widget_print_styles` because Gutenberg previews don't render a full version of the front end,
|
1135 |
-
// so neither the `wp_head` nor the `wp_footer` actions are called, which usually trigger `siteorigin_widget_print_styles`.
|
1136 |
-
if ( $sowb_active ) {
|
1137 |
-
ob_start();
|
1138 |
-
siteorigin_widget_print_styles();
|
1139 |
-
$rendered_layout .= ob_get_clean();
|
1140 |
-
}
|
1141 |
-
|
1142 |
-
echo $rendered_layout;
|
1143 |
-
wp_die();
|
1144 |
-
}
|
1145 |
-
|
1146 |
-
public function layout_block_sanitize() {
|
1147 |
-
|
1148 |
-
if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'layout-block-sanitize' ) ) {
|
1149 |
-
wp_die();
|
1150 |
-
}
|
1151 |
-
|
1152 |
-
$panels_data = json_decode( wp_unslash( $_POST['panelsData'] ), true );
|
1153 |
-
$panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'], false, true, true );
|
1154 |
-
$panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
|
1155 |
-
|
1156 |
-
wp_send_json( $panels_data );
|
1157 |
-
}
|
1158 |
-
|
1159 |
-
/**
|
1160 |
-
* Add a column that indicates if a column is powered by Page Builder
|
1161 |
-
*
|
1162 |
-
* @param $columns
|
1163 |
-
*
|
1164 |
-
* @return array
|
1165 |
-
*/
|
1166 |
-
function add_custom_column( $columns ){
|
1167 |
-
$index = array_search( 'comments', array_keys( $columns ) );
|
1168 |
-
|
1169 |
-
if( empty( $index ) ) {
|
1170 |
-
$columns = array_merge(
|
1171 |
-
$columns,
|
1172 |
-
array( 'panels' => __( 'Page Builder', 'siteorigin-panels' ) )
|
1173 |
-
);
|
1174 |
-
}
|
1175 |
-
else {
|
1176 |
-
$columns = array_slice( $columns, 0, $index, true ) +
|
1177 |
-
array( 'panels' => __( 'Page Builder', 'siteorigin-panels' ) ) +
|
1178 |
-
array_slice( $columns, $index, count( $columns ) - 1, true );
|
1179 |
-
}
|
1180 |
-
|
1181 |
-
return $columns;
|
1182 |
-
}
|
1183 |
-
|
1184 |
-
function display_custom_column( $column, $post_id ){
|
1185 |
-
if( $column != 'panels' ) return;
|
1186 |
-
|
1187 |
-
$panels_data = get_post_meta( $post_id, 'panels_data', true );
|
1188 |
-
if( ! empty( $panels_data['widgets'] ) ) {
|
1189 |
-
$widgets_count = count( $panels_data['widgets'] );
|
1190 |
-
printf( _n( '%s Widget', '%s Widgets', $widgets_count, 'siteorigin-panels' ), $widgets_count );
|
1191 |
-
}
|
1192 |
-
else {
|
1193 |
-
echo '—';
|
1194 |
-
}
|
1195 |
-
}
|
1196 |
-
|
1197 |
-
public function footer_column_css(){
|
1198 |
-
if( siteorigin_panels_setting( 'admin-widget-count' ) ) {
|
1199 |
-
$screen = get_current_screen();
|
1200 |
-
$post_types = siteorigin_panels_setting( 'post-types' );
|
1201 |
-
|
1202 |
-
if(
|
1203 |
-
$screen->base == 'edit' &&
|
1204 |
-
is_array( $post_types ) &&
|
1205 |
-
in_array( $screen->post_type, $post_types )
|
1206 |
-
){
|
1207 |
-
?><style type="text/css">.column-panels{ width: 10% }</style><?php
|
1208 |
-
}
|
1209 |
-
}
|
1210 |
-
}
|
1211 |
-
|
1212 |
-
/**
|
1213 |
-
* Add double slashes to strings
|
1214 |
-
*
|
1215 |
-
* @param $value
|
1216 |
-
*
|
1217 |
-
* @return string
|
1218 |
-
*/
|
1219 |
-
public static function double_slash_string( $value ){
|
1220 |
-
return is_string( $value ) ? addcslashes( $value, '\\' ) : $value;
|
1221 |
-
}
|
1222 |
-
|
1223 |
-
public function get_layout_directories(){
|
1224 |
-
|
1225 |
-
}
|
1226 |
-
|
1227 |
-
/**
|
1228 |
-
* Display links for various SiteOrigin addons
|
1229 |
-
*/
|
1230 |
-
public static function display_footer_premium_link(){
|
1231 |
-
$links = array(
|
1232 |
-
array(
|
1233 |
-
'text' => __('Get a lightbox addon for SiteOrigin widgets', 'siteorigin-panels'),
|
1234 |
-
'url' => SiteOrigin_Panels::premium_url('plugin/lightbox')
|
1235 |
-
),
|
1236 |
-
array(
|
1237 |
-
'text' => __('Get the row, cell and widget animations addon', 'siteorigin-panels'),
|
1238 |
-
'url' => SiteOrigin_Panels::premium_url('plugin/lightbox')
|
1239 |
-
),
|
1240 |
-
array(
|
1241 |
-
'text' => __('Get premium email support for SiteOrigin Page Builder', 'siteorigin-panels'),
|
1242 |
-
'url' => SiteOrigin_Panels::premium_url()
|
1243 |
-
),
|
1244 |
-
);
|
1245 |
-
$link = $links[array_rand($links)];
|
1246 |
-
|
1247 |
-
?>
|
1248 |
-
<a href="<?php echo esc_url( $link['url'] ) ?>" target="_blank" rel='noopener noreferrer'>
|
1249 |
-
<?php echo esc_html( $link['text'] ) ?>.
|
1250 |
-
</a>
|
1251 |
-
<?php
|
1252 |
-
}
|
1253 |
-
|
1254 |
-
public function admin_notices() {
|
1255 |
-
global $typenow, $pagenow;
|
1256 |
-
$is_new = $pagenow == 'post-new.php';
|
1257 |
-
$post_types = siteorigin_panels_setting( 'post-types' );
|
1258 |
-
$is_panels_type = in_array( $typenow, $post_types );
|
1259 |
-
$use_classic = siteorigin_panels_setting( 'use-classic' );
|
1260 |
-
$show_classic_admin_notice = $is_new && $is_panels_type && $use_classic;
|
1261 |
-
$show_classic_admin_notice = apply_filters( 'so_panels_show_classic_admin_notice', $show_classic_admin_notice );
|
1262 |
-
if ( $show_classic_admin_notice ) {
|
1263 |
-
$settings_url = self_admin_url( 'options-general.php?page=siteorigin_panels' );
|
1264 |
-
$notice = sprintf(
|
1265 |
-
__( 'This post type is set to use the Classic Editor by default for new posts. If you’d like to change this to the block editor, please go to <a href="%s" class="components-notice__action is-link">Page Builder Settings</a> and uncheck <strong>Use Classic Editor for new posts</strong>' ),
|
1266 |
-
$settings_url
|
1267 |
-
);
|
1268 |
-
?>
|
1269 |
-
<div id="siteorigin-panels-use-classic-notice" class="notice notice-info"><p id="use-classic-notice"><?php echo $notice ?></p></div>
|
1270 |
-
<?php
|
1271 |
-
}
|
1272 |
-
}
|
1273 |
-
|
1274 |
-
/**
|
1275 |
-
* Show Classic Editor for existing PB posts.
|
1276 |
-
*
|
1277 |
-
* @param $use_block_editor
|
1278 |
-
* @param $post_type
|
1279 |
-
*
|
1280 |
-
* @return bool
|
1281 |
-
*/
|
1282 |
-
public function show_classic_editor_for_panels( $use_block_editor, $post_type ) {
|
1283 |
-
|
1284 |
-
// For new pages.
|
1285 |
-
if ( isset( $_GET['block-editor'] ) ) {
|
1286 |
-
return $use_block_editor;
|
1287 |
-
} else if ( isset( $_GET['siteorigin-page-builder'] ) ) {
|
1288 |
-
return false;
|
1289 |
-
}
|
1290 |
-
|
1291 |
-
$post_types = siteorigin_panels_setting( 'post-types' );
|
1292 |
-
global $pagenow;
|
1293 |
-
// If the `$post_type` is set to be used by Page Builder for new posts.
|
1294 |
-
$is_new_panels_type = $pagenow == 'post-new.php' && in_array( $post_type, $post_types );
|
1295 |
-
$use_classic = siteorigin_panels_setting( 'use-classic' );
|
1296 |
-
// For existing posts.
|
1297 |
-
global $post;
|
1298 |
-
if ( ! empty( $post ) ) {
|
1299 |
-
// If the post has blocks just allow `$use_block_editor` to decide.
|
1300 |
-
if ( ! has_blocks( $post ) ) {
|
1301 |
-
$panels_data = get_post_meta( $post->ID, 'panels_data', true );
|
1302 |
-
if ( ! empty( $panels_data ) || ( $use_classic && $is_new_panels_type ) ) {
|
1303 |
-
$use_block_editor = false;
|
1304 |
-
}
|
1305 |
-
}
|
1306 |
-
} else if ( $is_new_panels_type ) {
|
1307 |
-
$use_block_editor = false;
|
1308 |
-
}
|
1309 |
-
|
1310 |
-
return $use_block_editor;
|
1311 |
-
}
|
1312 |
-
|
1313 |
-
/**
|
1314 |
-
* This was copied from Gutenberg and slightly modified as a quick way to allow users to create new Page Builder pages
|
1315 |
-
* in the classic editor without requiring the classic editor plugin be installed.
|
1316 |
-
*/
|
1317 |
-
function add_panels_add_new_button() {
|
1318 |
-
global $typenow;
|
1319 |
-
|
1320 |
-
if ( 'wp_block' === $typenow ) {
|
1321 |
-
?>
|
1322 |
-
<style type="text/css">
|
1323 |
-
.page-title-action {
|
1324 |
-
display: none;
|
1325 |
-
}
|
1326 |
-
</style>
|
1327 |
-
<?php
|
1328 |
-
}
|
1329 |
-
|
1330 |
-
if ( ! $this->show_add_new_dropdown_for_type( $typenow ) ) {
|
1331 |
-
return;
|
1332 |
-
}
|
1333 |
-
|
1334 |
-
?>
|
1335 |
-
<style type="text/css">
|
1336 |
-
.split-page-title-action {
|
1337 |
-
display: inline-block;
|
1338 |
-
}
|
1339 |
-
|
1340 |
-
.split-page-title-action a,
|
1341 |
-
.split-page-title-action a:active,
|
1342 |
-
.split-page-title-action .expander:after {
|
1343 |
-
padding: 6px 10px;
|
1344 |
-
position: relative;
|
1345 |
-
top: -3px;
|
1346 |
-
text-decoration: none;
|
1347 |
-
border: 1px solid #ccc;
|
1348 |
-
border-radius: 2px 0px 0px 2px;
|
1349 |
-
background: #f7f7f7;
|
1350 |
-
text-shadow: none;
|
1351 |
-
font-weight: 600;
|
1352 |
-
font-size: 13px;
|
1353 |
-
line-height: normal; /* IE8-IE11 need this for buttons */
|
1354 |
-
color: #0073aa; /* some of these controls are button elements and don't inherit from links */
|
1355 |
-
cursor: pointer;
|
1356 |
-
outline: 0;
|
1357 |
-
}
|
1358 |
-
|
1359 |
-
.split-page-title-action a:hover,
|
1360 |
-
.split-page-title-action .expander:hover:after {
|
1361 |
-
border-color: #008EC2;
|
1362 |
-
background: #00a0d2;
|
1363 |
-
color: #fff;
|
1364 |
-
}
|
1365 |
-
|
1366 |
-
.split-page-title-action a:focus,
|
1367 |
-
.split-page-title-action .expander:focus:after {
|
1368 |
-
border-color: #5b9dd9;
|
1369 |
-
box-shadow: 0 0 2px rgba( 30, 140, 190, 0.8 );
|
1370 |
-
}
|
1371 |
-
|
1372 |
-
.split-page-title-action .expander:after {
|
1373 |
-
content: "\f140";
|
1374 |
-
font: 400 20px/.5 dashicons;
|
1375 |
-
speak: none;
|
1376 |
-
top: 0px;
|
1377 |
-
<?php if ( is_rtl() ) : ?>
|
1378 |
-
right: -1px;
|
1379 |
-
<?php else : ?>
|
1380 |
-
left: -1px;
|
1381 |
-
<?php endif; ?>
|
1382 |
-
position: relative;
|
1383 |
-
vertical-align: top;
|
1384 |
-
text-decoration: none !important;
|
1385 |
-
padding: 4px 5px 5px 4px;
|
1386 |
-
border-radius: 0px 2px 2px 0px;
|
1387 |
-
}
|
1388 |
-
|
1389 |
-
.split-page-title-action .dropdown {
|
1390 |
-
display: none;
|
1391 |
-
}
|
1392 |
-
|
1393 |
-
.split-page-title-action .dropdown.visible {
|
1394 |
-
display: block;
|
1395 |
-
position: absolute;
|
1396 |
-
margin-top: 3px;
|
1397 |
-
z-index: 1;
|
1398 |
-
}
|
1399 |
-
|
1400 |
-
.split-page-title-action .dropdown.visible a {
|
1401 |
-
display: block;
|
1402 |
-
top: 0;
|
1403 |
-
margin: -1px 0;
|
1404 |
-
<?php if ( is_rtl() ) : ?>
|
1405 |
-
padding-left: 9px;
|
1406 |
-
<?php else : ?>
|
1407 |
-
padding-right: 9px;
|
1408 |
-
<?php endif; ?>
|
1409 |
-
}
|
1410 |
-
|
1411 |
-
.split-page-title-action .expander {
|
1412 |
-
outline: none;
|
1413 |
-
}
|
1414 |
-
|
1415 |
-
</style>
|
1416 |
-
<script type="text/javascript">
|
1417 |
-
document.addEventListener( 'DOMContentLoaded', function() {
|
1418 |
-
var buttons = document.getElementsByClassName( 'page-title-action' ),
|
1419 |
-
button = buttons.item( 0 );
|
1420 |
-
|
1421 |
-
if ( ! button ) {
|
1422 |
-
return;
|
1423 |
-
}
|
1424 |
-
|
1425 |
-
var url = button.href;
|
1426 |
-
var urlHasParams = ( -1 !== url.indexOf( '?' ) );
|
1427 |
-
var panelsUrl = url + ( urlHasParams ? '&' : '?' ) + 'siteorigin-page-builder';
|
1428 |
-
var blockEditorUrl = url + ( urlHasParams ? '&' : '?' ) + 'block-editor';
|
1429 |
-
|
1430 |
-
var newbutton = '<span id="split-page-title-action" class="split-page-title-action">';
|
1431 |
-
newbutton += '<a href="' + url + '">' + button.innerText + '</a>';
|
1432 |
-
newbutton += '<span class="expander" tabindex="0" role="button" aria-haspopup="true" aria-label="<?php echo esc_attr( __( 'Toggle editor selection menu', 'siteorigin-panels' ) ); ?>"></span>';
|
1433 |
-
newbutton += '<span class="dropdown"><a href="' + panelsUrl + '"><?php echo esc_html( __( 'SiteOrigin Page Builder', 'siteorigin-panels' ) ); ?></a>';
|
1434 |
-
newbutton += '<a href="' + blockEditorUrl + '"><?php echo esc_html( __( 'Block Editor', 'siteorigin-panels' ) ); ?></a></span></span><span class="page-title-action" style="display:none;"></span>';
|
1435 |
-
|
1436 |
-
button.insertAdjacentHTML( 'afterend', newbutton );
|
1437 |
-
button.parentNode.removeChild( button );
|
1438 |
-
|
1439 |
-
var expander = document.getElementById( 'split-page-title-action' ).getElementsByClassName( 'expander' ).item( 0 );
|
1440 |
-
var dropdown = expander.parentNode.querySelector( '.dropdown' );
|
1441 |
-
function toggleDropdown() {
|
1442 |
-
dropdown.classList.toggle( 'visible' );
|
1443 |
-
}
|
1444 |
-
expander.addEventListener( 'click', function( e ) {
|
1445 |
-
e.preventDefault();
|
1446 |
-
toggleDropdown();
|
1447 |
-
} );
|
1448 |
-
expander.addEventListener( 'keydown', function( e ) {
|
1449 |
-
if ( 13 === e.which || 32 === e.which ) {
|
1450 |
-
e.preventDefault();
|
1451 |
-
toggleDropdown();
|
1452 |
-
}
|
1453 |
-
} );
|
1454 |
-
} );
|
1455 |
-
</script>
|
1456 |
-
<?php
|
1457 |
-
}
|
1458 |
-
|
1459 |
-
private function show_add_new_dropdown_for_type( $post_type ) {
|
1460 |
-
|
1461 |
-
$show = in_array( $post_type, siteorigin_panels_setting( 'post-types' ) );
|
1462 |
-
|
1463 |
-
// WooCommerce product type doesn't support block editor...
|
1464 |
-
$show = $show && ! ( class_exists( 'WooCommerce' ) && $post_type == 'product' );
|
1465 |
-
|
1466 |
-
if ( class_exists( 'SiteOrigin_Premium_Plugin_Cpt_Builder' ) ) {
|
1467 |
-
$show = $show && $post_type != SiteOrigin_Premium_Plugin_Cpt_Builder::POST_TYPE;
|
1468 |
-
$cpt_builder = SiteOrigin_Premium_Plugin_Cpt_Builder::single();
|
1469 |
-
$so_custom_types = $cpt_builder->get_post_types();
|
1470 |
-
$show = $show && ! isset( $so_custom_types[ $post_type ] );
|
1471 |
-
}
|
1472 |
-
|
1473 |
-
return apply_filters( 'so_panels_show_add_new_dropdown_for_type', $show, $post_type );
|
1474 |
-
}
|
1475 |
-
|
1476 |
-
public function add_panels_post_state( $post_states, $post ) {
|
1477 |
-
$panels_data = get_post_meta( $post->ID, 'panels_data', true );
|
1478 |
-
|
1479 |
-
if ( ! empty( $panels_data ) ) {
|
1480 |
-
$post_states[] = __( 'SiteOrigin Page Builder', 'siteorigin-panels' );
|
1481 |
-
}
|
1482 |
-
|
1483 |
-
return $post_states;
|
1484 |
-
}
|
1485 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class SiteOrigin_Panels_Admin
|
5 |
+
*
|
6 |
+
* Handles all the admin and database interactions.
|
7 |
+
*/
|
8 |
+
class SiteOrigin_Panels_Admin {
|
9 |
+
|
10 |
+
/**
|
11 |
+
* @var bool Store that we're in the save post action, to prevent infinite loops
|
12 |
+
*/
|
13 |
+
private $in_save_post;
|
14 |
+
|
15 |
+
function __construct() {
|
16 |
+
|
17 |
+
add_action( 'plugin_action_links_siteorigin-panels/siteorigin-panels.php', array(
|
18 |
+
$this,
|
19 |
+
'plugin_action_links'
|
20 |
+
) );
|
21 |
+
|
22 |
+
add_action( 'plugins_loaded', array( $this, 'admin_init_widget_count' ) );
|
23 |
+
|
24 |
+
add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) );
|
25 |
+
add_action( 'admin_init', array( $this, 'save_home_page' ) );
|
26 |
+
add_action( 'save_post', array( $this, 'save_post' ) );
|
27 |
+
|
28 |
+
add_action( 'after_switch_theme', array( $this, 'update_home_on_theme_change' ) );
|
29 |
+
|
30 |
+
// Enqueuing admin scripts
|
31 |
+
add_action( 'admin_print_scripts-post-new.php', array( $this, 'enqueue_admin_scripts' ) );
|
32 |
+
add_action( 'admin_print_scripts-post.php', array( $this, 'enqueue_admin_scripts' ) );
|
33 |
+
add_action( 'admin_print_scripts-appearance_page_so_panels_home_page', array(
|
34 |
+
$this,
|
35 |
+
'enqueue_admin_scripts'
|
36 |
+
) );
|
37 |
+
add_action( 'admin_print_scripts-widgets.php', array( $this, 'enqueue_admin_scripts' ) );
|
38 |
+
add_action( 'admin_print_scripts-edit.php', array( $this, 'footer_column_css' ) );
|
39 |
+
|
40 |
+
// Enqueue the admin styles
|
41 |
+
add_action( 'admin_print_styles-post-new.php', array( $this, 'enqueue_admin_styles' ) );
|
42 |
+
add_action( 'admin_print_styles-post.php', array( $this, 'enqueue_admin_styles' ) );
|
43 |
+
add_action( 'admin_print_styles-appearance_page_so_panels_home_page', array( $this, 'enqueue_admin_styles' ) );
|
44 |
+
add_action( 'admin_print_styles-widgets.php', array( $this, 'enqueue_admin_styles' ) );
|
45 |
+
|
46 |
+
// The help tab
|
47 |
+
add_action( 'load-page.php', array( $this, 'add_help_tab' ), 12 );
|
48 |
+
add_action( 'load-post-new.php', array( $this, 'add_help_tab' ), 12 );
|
49 |
+
add_action( 'load-appearance_page_so_panels_home_page', array( $this, 'add_help_tab' ), 12 );
|
50 |
+
|
51 |
+
add_action( 'customize_controls_print_footer_scripts', array( $this, 'js_templates' ) );
|
52 |
+
|
53 |
+
// Register all the admin actions
|
54 |
+
add_action( 'wp_ajax_so_panels_builder_content', array( $this, 'action_builder_content' ) );
|
55 |
+
add_action( 'wp_ajax_so_panels_widget_form', array( $this, 'action_widget_form' ) );
|
56 |
+
add_action( 'wp_ajax_so_panels_live_editor_preview', array( $this, 'action_live_editor_preview' ) );
|
57 |
+
add_action( 'wp_ajax_so_panels_layout_block_sanitize', array( $this, 'layout_block_sanitize' ) );
|
58 |
+
add_action( 'wp_ajax_so_panels_layout_block_preview', array( $this, 'layout_block_preview' ) );
|
59 |
+
|
60 |
+
// Initialize the additional admin classes.
|
61 |
+
SiteOrigin_Panels_Admin_Widget_Dialog::single();
|
62 |
+
SiteOrigin_Panels_Admin_Widgets_Bundle::single();
|
63 |
+
SiteOrigin_Panels_Admin_Layouts::single();
|
64 |
+
|
65 |
+
// Check to make sure we have all the correct markup
|
66 |
+
SiteOrigin_Panels_Admin_Dashboard::single();
|
67 |
+
|
68 |
+
$this->in_save_post = false;
|
69 |
+
|
70 |
+
|
71 |
+
// Enqueue Yoast compatibility
|
72 |
+
add_action( 'admin_print_scripts-post-new.php', array( $this, 'enqueue_yoast_compat' ), 100 );
|
73 |
+
add_action( 'admin_print_scripts-post.php', array( $this, 'enqueue_yoast_compat' ), 100 );
|
74 |
+
|
75 |
+
// Block editor specific actions
|
76 |
+
if ( function_exists( 'register_block_type' ) ) {
|
77 |
+
add_action( 'admin_notices', array( $this, 'admin_notices' ) );
|
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 |
+
|
87 |
+
/**
|
88 |
+
* @return SiteOrigin_Panels_Admin
|
89 |
+
*/
|
90 |
+
public static function single() {
|
91 |
+
static $single;
|
92 |
+
return empty( $single ) ? $single = new self() : $single;
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Do some general admin initialization
|
97 |
+
*/
|
98 |
+
public function admin_init_widget_count(){
|
99 |
+
if( siteorigin_panels_setting( 'admin-widget-count' ) ) {
|
100 |
+
|
101 |
+
// Add the custom columns
|
102 |
+
$post_types = siteorigin_panels_setting( 'post-types' );
|
103 |
+
if( ! empty( $post_types ) ) {
|
104 |
+
foreach( $post_types as $post_type ) {
|
105 |
+
add_filter( 'manage_' . $post_type . 's_columns' , array( $this, 'add_custom_column' ) );
|
106 |
+
add_action( 'manage_' . $post_type . 's_custom_column' , array( $this, 'display_custom_column' ), 10, 2 );
|
107 |
+
}
|
108 |
+
}
|
109 |
+
}
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Check if this is an admin page.
|
114 |
+
*
|
115 |
+
* @return mixed|void
|
116 |
+
*/
|
117 |
+
static function is_admin() {
|
118 |
+
$screen = get_current_screen();
|
119 |
+
$is_panels_page = ( $screen->base == 'post' && in_array( $screen->id, siteorigin_panels_setting( 'post-types' ) ) ) ||
|
120 |
+
in_array( $screen->base, array( 'appearance_page_so_panels_home_page', 'widgets', 'customize' ) ) ||
|
121 |
+
self::is_block_editor();
|
122 |
+
|
123 |
+
return apply_filters( 'siteorigin_panels_is_admin_page', $is_panels_page );
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Check if the current page is Gutenberg or the Block Ediotr
|
128 |
+
*
|
129 |
+
* @return bool
|
130 |
+
*/
|
131 |
+
static function is_block_editor() {
|
132 |
+
// This is for the Gutenberg plugin.
|
133 |
+
$is_gutenberg_page = function_exists( 'is_gutenberg_page' ) && is_gutenberg_page();
|
134 |
+
// This is for WP 5 with the integrated block editor.
|
135 |
+
$is_block_editor = false;
|
136 |
+
|
137 |
+
if ( function_exists( 'get_current_screen' ) ) {
|
138 |
+
$current_screen = get_current_screen();
|
139 |
+
if ( $current_screen && method_exists( $current_screen, 'is_block_editor' ) ) {
|
140 |
+
$is_block_editor = $current_screen->is_block_editor();
|
141 |
+
}
|
142 |
+
}
|
143 |
+
|
144 |
+
return $is_gutenberg_page || $is_block_editor;
|
145 |
+
}
|
146 |
+
|
147 |
+
|
148 |
+
/**
|
149 |
+
* Add action links to the plugin list for Page Builder.
|
150 |
+
*
|
151 |
+
* @param $links
|
152 |
+
*
|
153 |
+
* @return array
|
154 |
+
*/
|
155 |
+
function plugin_action_links( $links ) {
|
156 |
+
if( ! is_array( $links ) ) {
|
157 |
+
return $links;
|
158 |
+
}
|
159 |
+
|
160 |
+
unset( $links['edit'] );
|
161 |
+
$links[] = '<a href="http://siteorigin.com/threads/plugin-page-builder/">' . __( 'Support Forum', 'siteorigin-panels' ) . '</a>';
|
162 |
+
|
163 |
+
if( SiteOrigin_Panels::display_premium_teaser() ) {
|
164 |
+
$links[] = '<a href="' . esc_url( SiteOrigin_Panels::premium_url() ) . '" style="color: #3db634" target="_blank" rel="noopener noreferrer">' . __('Addons', 'siteorigin-panels') . '</a>';
|
165 |
+
}
|
166 |
+
|
167 |
+
return $links;
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Callback to register the Page Builder Metaboxes
|
172 |
+
*/
|
173 |
+
function add_meta_boxes() {
|
174 |
+
|
175 |
+
foreach ( siteorigin_panels_setting( 'post-types' ) as $type ) {
|
176 |
+
add_meta_box(
|
177 |
+
'so-panels-panels',
|
178 |
+
__( 'Page Builder', 'siteorigin-panels' ),
|
179 |
+
array( $this, 'render_meta_boxes' ),
|
180 |
+
( string ) $type,
|
181 |
+
'advanced',
|
182 |
+
'high',
|
183 |
+
array(
|
184 |
+
// Ideally when we have panels data for a page we would set this to false and it would cause the
|
185 |
+
// editor to fall back to classic editor, but that's not the case so we just declare it as a `__back_compat_meta_box`.
|
186 |
+
'__back_compat_meta_box' => true,
|
187 |
+
'__block_editor_compatible_meta_box' => false,
|
188 |
+
)
|
189 |
+
);
|
190 |
+
}
|
191 |
+
}
|
192 |
+
|
193 |
+
/**
|
194 |
+
* Render a panel metabox.
|
195 |
+
*
|
196 |
+
* @param $post
|
197 |
+
*/
|
198 |
+
function render_meta_boxes( $post ) {
|
199 |
+
$panels_data = $this->get_current_admin_panels_data();
|
200 |
+
include plugin_dir_path( __FILE__ ) . '../tpl/metabox-panels.php';
|
201 |
+
}
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Save the panels data
|
205 |
+
*
|
206 |
+
* @param $post_id
|
207 |
+
*
|
208 |
+
* @action save_post
|
209 |
+
*/
|
210 |
+
function save_post( $post_id ) {
|
211 |
+
// Check that everything is valid with this save.
|
212 |
+
if(
|
213 |
+
$this->in_save_post ||
|
214 |
+
( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) ||
|
215 |
+
empty( $_POST['_sopanels_nonce'] ) ||
|
216 |
+
! wp_verify_nonce( $_POST['_sopanels_nonce'], 'save' ) ||
|
217 |
+
! current_user_can( 'edit_post', $post_id ) ||
|
218 |
+
! isset( $_POST['panels_data'] )
|
219 |
+
) {
|
220 |
+
return;
|
221 |
+
}
|
222 |
+
$this->in_save_post = true;
|
223 |
+
// Get post from db as it might have been changed and saved by other plugins.
|
224 |
+
$post = get_post( $post_id );
|
225 |
+
$old_panels_data = get_post_meta( $post_id, 'panels_data', true );
|
226 |
+
$panels_data = json_decode( wp_unslash( $_POST['panels_data'] ), true );
|
227 |
+
|
228 |
+
$panels_data['widgets'] = $this->process_raw_widgets(
|
229 |
+
$panels_data['widgets'],
|
230 |
+
! empty( $old_panels_data['widgets'] ) ? $old_panels_data['widgets'] : false,
|
231 |
+
false
|
232 |
+
);
|
233 |
+
|
234 |
+
if ( siteorigin_panels_setting( 'sidebars-emulator' ) ) {
|
235 |
+
$sidebars_emulator = SiteOrigin_Panels_Sidebars_Emulator::single();
|
236 |
+
$panels_data['widgets'] = $sidebars_emulator->generate_sidebar_widget_ids( $panels_data['widgets'], $post_id );
|
237 |
+
}
|
238 |
+
|
239 |
+
$panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
|
240 |
+
$panels_data = apply_filters( 'siteorigin_panels_data_pre_save', $panels_data, $post, $post_id );
|
241 |
+
|
242 |
+
if ( ! empty( $panels_data['widgets'] ) || ! empty( $panels_data['grids'] ) ) {
|
243 |
+
// Use `update_metadata` instead of `update_post_meta` to prevent saving to parent post when it's a revision, e.g. preview.
|
244 |
+
update_metadata( 'post', $post_id, 'panels_data', map_deep( $panels_data, array( 'SiteOrigin_Panels_Admin', 'double_slash_string' ) ) );
|
245 |
+
|
246 |
+
if( siteorigin_panels_setting( 'copy-content' ) ) {
|
247 |
+
// Store a version of the HTML in post_content
|
248 |
+
$post_parent_id = wp_is_post_revision( $post_id );
|
249 |
+
$layout_id = ( ! empty( $post_parent_id ) ) ? $post_parent_id : $post_id;
|
250 |
+
|
251 |
+
SiteOrigin_Panels_Post_Content_Filters::add_filters();
|
252 |
+
$GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] = true;
|
253 |
+
$post_content = SiteOrigin_Panels::renderer()->render( $layout_id, false, $panels_data );
|
254 |
+
$post_css = SiteOrigin_Panels::renderer()->generate_css( $layout_id, $panels_data );
|
255 |
+
SiteOrigin_Panels_Post_Content_Filters::remove_filters();
|
256 |
+
unset( $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] );
|
257 |
+
|
258 |
+
// Update the post_content
|
259 |
+
$post->post_content = $post_content;
|
260 |
+
if( siteorigin_panels_setting( 'copy-styles' ) ) {
|
261 |
+
$post->post_content .= "\n\n";
|
262 |
+
$post->post_content .= '<style type="text/css" class="panels-style" data-panels-style-for-post="' . intval( $layout_id ) . '">';
|
263 |
+
$post->post_content .= '@import url(' . SiteOrigin_Panels::front_css_url() . '); ';
|
264 |
+
$post->post_content .= $post_css;
|
265 |
+
$post->post_content .= '</style>';
|
266 |
+
}
|
267 |
+
wp_update_post( $post );
|
268 |
+
}
|
269 |
+
|
270 |
+
} else {
|
271 |
+
// There are no widgets or rows, so delete the panels data
|
272 |
+
delete_post_meta( $post_id, 'panels_data' );
|
273 |
+
}
|
274 |
+
|
275 |
+
$this->in_save_post = false;
|
276 |
+
}
|
277 |
+
|
278 |
+
/**
|
279 |
+
* Enqueue the panels admin scripts
|
280 |
+
*
|
281 |
+
* @param string $prefix
|
282 |
+
* @param bool $force Should we force the enqueues
|
283 |
+
*
|
284 |
+
* @action admin_print_scripts-post-new.php
|
285 |
+
* @action admin_print_scripts-post.php
|
286 |
+
* @action admin_print_scripts-appearance_page_so_panels_home_page
|
287 |
+
*/
|
288 |
+
function enqueue_admin_scripts( $prefix = '', $force = false ) {
|
289 |
+
$screen = get_current_screen();
|
290 |
+
if ( $force || self::is_admin() ) {
|
291 |
+
// Media is required for row styles
|
292 |
+
wp_enqueue_media();
|
293 |
+
wp_enqueue_script(
|
294 |
+
'so-panels-admin',
|
295 |
+
siteorigin_panels_url( 'js/siteorigin-panels' . SITEORIGIN_PANELS_VERSION_SUFFIX . SITEORIGIN_PANELS_JS_SUFFIX . '.js' ),
|
296 |
+
array(
|
297 |
+
'jquery',
|
298 |
+
'jquery-ui-resizable',
|
299 |
+
'jquery-ui-sortable',
|
300 |
+
'jquery-ui-draggable',
|
301 |
+
'underscore',
|
302 |
+
'backbone',
|
303 |
+
'plupload',
|
304 |
+
'plupload-all'
|
305 |
+
),
|
306 |
+
SITEORIGIN_PANELS_VERSION,
|
307 |
+
true
|
308 |
+
);
|
309 |
+
add_action( 'admin_footer', array( $this, 'js_templates' ) );
|
310 |
+
|
311 |
+
$widgets = $this->get_widgets();
|
312 |
+
$directory_enabled = get_user_meta( get_current_user_id(), 'so_panels_directory_enabled', true );
|
313 |
+
|
314 |
+
// This is the widget we'll use for default text
|
315 |
+
if( ! empty( $widgets[ 'SiteOrigin_Widget_Editor_Widget' ] ) ) $text_widget = 'SiteOrigin_Widget_Editor_Widget';
|
316 |
+
else if( ! empty( $widgets[ 'WP_Widget_Text' ] ) ) $text_widget = 'WP_Widget_Text';
|
317 |
+
else $text_widget = false;
|
318 |
+
$text_widget = apply_filters( 'siteorigin_panels_text_widget_class', $text_widget );
|
319 |
+
|
320 |
+
$user = wp_get_current_user();
|
321 |
+
|
322 |
+
$load_on_attach = siteorigin_panels_setting( 'load-on-attach' ) || isset( $_GET['siteorigin-page-builder'] );
|
323 |
+
wp_localize_script( 'so-panels-admin', 'panelsOptions', array(
|
324 |
+
'user' => ! empty( $user ) ? $user->ID : 0,
|
325 |
+
'ajaxurl' => wp_nonce_url( admin_url( 'admin-ajax.php' ), 'panels_action', '_panelsnonce' ),
|
326 |
+
'widgets' => $widgets,
|
327 |
+
'text_widget' => $text_widget,
|
328 |
+
'widget_dialog_tabs' => apply_filters( 'siteorigin_panels_widget_dialog_tabs', array(
|
329 |
+
0 => array(
|
330 |
+
'title' => __( 'All Widgets', 'siteorigin-panels' ),
|
331 |
+
'filter' => array(
|
332 |
+
'installed' => true,
|
333 |
+
'groups' => ''
|
334 |
+
)
|
335 |
+
)
|
336 |
+
) ),
|
337 |
+
'row_layouts' => apply_filters( 'siteorigin_panels_row_layouts', array() ),
|
338 |
+
'directory_enabled' => ! empty( $directory_enabled ),
|
339 |
+
'copy_content' => siteorigin_panels_setting( 'copy-content' ),
|
340 |
+
'cache' => array(),
|
341 |
+
'instant_open' => siteorigin_panels_setting( 'instant-open-widgets' ),
|
342 |
+
|
343 |
+
// Settings for the contextual menu
|
344 |
+
'contextual' => array(
|
345 |
+
// Developers can change which widgets are displayed by default using this filter
|
346 |
+
'default_widgets' => apply_filters( 'siteorigin_panels_contextual_default_widgets', array(
|
347 |
+
'SiteOrigin_Widget_Editor_Widget',
|
348 |
+
'SiteOrigin_Widget_Button_Widget',
|
349 |
+
'SiteOrigin_Widget_Image_Widget',
|
350 |
+
'SiteOrigin_Panels_Widgets_Layout',
|
351 |
+
) )
|
352 |
+
),
|
353 |
+
|
354 |
+
// General localization messages
|
355 |
+
'loc' => array(
|
356 |
+
'missing_widget' => array(
|
357 |
+
'title' => __( 'Missing Widget', 'siteorigin-panels' ),
|
358 |
+
'description' => __( "Page Builder doesn't know about this widget.", 'siteorigin-panels' ),
|
359 |
+
),
|
360 |
+
'time' => array(
|
361 |
+
// TRANSLATORS: Number of seconds since
|
362 |
+
'seconds' => __( '%d seconds', 'siteorigin-panels' ),
|
363 |
+
// TRANSLATORS: Number of minutes since
|
364 |
+
'minutes' => __( '%d minutes', 'siteorigin-panels' ),
|
365 |
+
// TRANSLATORS: Number of hours since
|
366 |
+
'hours' => __( '%d hours', 'siteorigin-panels' ),
|
367 |
+
|
368 |
+
// TRANSLATORS: A single second since
|
369 |
+
'second' => __( '%d second', 'siteorigin-panels' ),
|
370 |
+
// TRANSLATORS: A single minute since
|
371 |
+
'minute' => __( '%d minute', 'siteorigin-panels' ),
|
372 |
+
// TRANSLATORS: A single hour since
|
373 |
+
'hour' => __( '%d hour', 'siteorigin-panels' ),
|
374 |
+
|
375 |
+
// TRANSLATORS: Time ago - eg. "1 minute before".
|
376 |
+
'ago' => __( '%s before', 'siteorigin-panels' ),
|
377 |
+
'now' => __( 'Now', 'siteorigin-panels' ),
|
378 |
+
),
|
379 |
+
'history' => array(
|
380 |
+
// History messages
|
381 |
+
'current' => __( 'Current', 'siteorigin-panels' ),
|
382 |
+
'revert' => __( 'Original', 'siteorigin-panels' ),
|
383 |
+
'restore' => __( 'Version restored', 'siteorigin-panels' ),
|
384 |
+
'back_to_editor' => __( 'Converted to editor', 'siteorigin-panels' ),
|
385 |
+
|
386 |
+
// Widgets
|
387 |
+
// TRANSLATORS: Message displayed in the history when a widget is deleted
|
388 |
+
'widget_deleted' => __( 'Widget deleted', 'siteorigin-panels' ),
|
389 |
+
// TRANSLATORS: Message displayed in the history when a widget is added
|
390 |
+
'widget_added' => __( 'Widget added', 'siteorigin-panels' ),
|
391 |
+
// TRANSLATORS: Message displayed in the history when a widget is edited
|
392 |
+
'widget_edited' => __( 'Widget edited', 'siteorigin-panels' ),
|
393 |
+
// TRANSLATORS: Message displayed in the history when a widget is duplicated
|
394 |
+
'widget_duplicated' => __( 'Widget duplicated', 'siteorigin-panels' ),
|
395 |
+
// TRANSLATORS: Message displayed in the history when a widget position is changed
|
396 |
+
'widget_moved' => __( 'Widget moved', 'siteorigin-panels' ),
|
397 |
+
|
398 |
+
// Rows
|
399 |
+
// TRANSLATORS: Message displayed in the history when a row is deleted
|
400 |
+
'row_deleted' => __( 'Row deleted', 'siteorigin-panels' ),
|
401 |
+
// TRANSLATORS: Message displayed in the history when a row is added
|
402 |
+
'row_added' => __( 'Row added', 'siteorigin-panels' ),
|
403 |
+
// TRANSLATORS: Message displayed in the history when a row is edited
|
404 |
+
'row_edited' => __( 'Row edited', 'siteorigin-panels' ),
|
405 |
+
// TRANSLATORS: Message displayed in the history when a row position is changed
|
406 |
+
'row_moved' => __( 'Row moved', 'siteorigin-panels' ),
|
407 |
+
// TRANSLATORS: Message displayed in the history when a row is duplicated
|
408 |
+
'row_duplicated' => __( 'Row duplicated', 'siteorigin-panels' ),
|
409 |
+
// TRANSLATORS: Message displayed in the history when a row is pasted
|
410 |
+
'row_pasted' => __( 'Row pasted', 'siteorigin-panels' ),
|
411 |
+
|
412 |
+
// Cells
|
413 |
+
'cell_resized' => __( 'Cell resized', 'siteorigin-panels' ),
|
414 |
+
|
415 |
+
// Prebuilt
|
416 |
+
'prebuilt_loaded' => __( 'Prebuilt layout loaded', 'siteorigin-panels' ),
|
417 |
+
),
|
418 |
+
|
419 |
+
// general localization
|
420 |
+
'prebuilt_loading' => __( 'Loading prebuilt layout', 'siteorigin-panels' ),
|
421 |
+
'confirm_use_builder' => __( "Would you like to copy this editor's existing content to Page Builder?", 'siteorigin-panels' ),
|
422 |
+
'confirm_stop_builder' => __( "Would you like to clear your Page Builder content and revert to using the standard visual editor?", 'siteorigin-panels' ),
|
423 |
+
// TRANSLATORS: This is the title for a widget called "Layout Builder"
|
424 |
+
'layout_widget' => __( 'Layout Builder Widget', 'siteorigin-panels' ),
|
425 |
+
// TRANSLATORS: A standard confirmation message
|
426 |
+
'dropdown_confirm' => __( 'Are you sure?', 'siteorigin-panels' ),
|
427 |
+
// TRANSLATORS: When a layout file is ready to be inserted. %s is the filename.
|
428 |
+
'ready_to_insert' => __( '%s is ready to insert.', 'siteorigin-panels' ),
|
429 |
+
|
430 |
+
// Everything for the contextual menu
|
431 |
+
'contextual' => array(
|
432 |
+
'add_widget_below' => __( 'Add Widget Below', 'siteorigin-panels' ),
|
433 |
+
'add_widget_cell' => __( 'Add Widget to Cell', 'siteorigin-panels' ),
|
434 |
+
'search_widgets' => __( 'Search Widgets', 'siteorigin-panels' ),
|
435 |
+
|
436 |
+
'add_row' => __( 'Add Row', 'siteorigin-panels' ),
|
437 |
+
'column' => __( 'Column', 'siteorigin-panels' ),
|
438 |
+
|
439 |
+
'cell_actions' => __( 'Cell Actions', 'siteorigin-panels' ),
|
440 |
+
'cell_paste_widget' => __( 'Paste Widget', 'siteorigin-panels' ),
|
441 |
+
|
442 |
+
'widget_actions' => __( 'Widget Actions', 'siteorigin-panels' ),
|
443 |
+
'widget_edit' => __( 'Edit Widget', 'siteorigin-panels' ),
|
444 |
+
'widget_duplicate' => __( 'Duplicate Widget', 'siteorigin-panels' ),
|
445 |
+
'widget_delete' => __( 'Delete Widget', 'siteorigin-panels' ),
|
446 |
+
'widget_copy' => __( 'Copy Widget', 'siteorigin-panels' ),
|
447 |
+
'widget_paste' => __( 'Paste Widget Below', 'siteorigin-panels' ),
|
448 |
+
|
449 |
+
'row_actions' => __( 'Row Actions', 'siteorigin-panels' ),
|
450 |
+
'row_edit' => __( 'Edit Row', 'siteorigin-panels' ),
|
451 |
+
'row_duplicate' => __( 'Duplicate Row', 'siteorigin-panels' ),
|
452 |
+
'row_delete' => __( 'Delete Row', 'siteorigin-panels' ),
|
453 |
+
'row_copy' => __( 'Copy Row', 'siteorigin-panels' ),
|
454 |
+
'row_paste' => __( 'Paste Row', 'siteorigin-panels' ),
|
455 |
+
),
|
456 |
+
'draft' => __( 'Draft', 'siteorigin-panels' ),
|
457 |
+
'untitled' => __( 'Untitled', 'siteorigin-panels' ),
|
458 |
+
'row' => array(
|
459 |
+
'add' => __( 'New Row', 'siteorigin-panels' ),
|
460 |
+
'edit' => __( 'Row', 'siteorigin-panels' ),
|
461 |
+
),
|
462 |
+
'welcomeMessage' => array(
|
463 |
+
'addingDisabled' => __( 'Hmmm... Adding layout elements is not enabled. Please check if Page Builder has been configured to allow adding elements.', 'siteorigin-panels' ),
|
464 |
+
'oneEnabled' => __( 'Add a {{%= items[0] %}} to get started.', 'siteorigin-panels' ),
|
465 |
+
'twoEnabled' => __( 'Add a {{%= items[0] %}} or {{%= items[1] %}} to get started.', 'siteorigin-panels' ),
|
466 |
+
'threeEnabled' => __( 'Add a {{%= items[0] %}}, {{%= items[1] %}} or {{%= items[2] %}} to get started.', 'siteorigin-panels' ),
|
467 |
+
'addWidgetButton' => "<a href='#' class='so-tool-button so-widget-add'>" . __( 'Widget', 'siteorigin-panels' ) . "</a>",
|
468 |
+
'addRowButton' => "<a href='#' class='so-tool-button so-row-add'>" . __( 'Row', 'siteorigin-panels' ) . "</a>",
|
469 |
+
'addPrebuiltButton' => "<a href='#' class='so-tool-button so-prebuilt-add'>" . __( 'Prebuilt Layout', 'siteorigin-panels' ) . "</a>",
|
470 |
+
'docsMessage' => sprintf(
|
471 |
+
__( 'Read our %s if you need help.', 'siteorigin-panels' ),
|
472 |
+
"<a href='https://siteorigin.com/page-builder/documentation/' target='_blank' rel='noopener noreferrer'>" . __( 'documentation', 'siteorigin-panels' ) . "</a>"
|
473 |
+
),
|
474 |
+
),
|
475 |
+
),
|
476 |
+
'plupload' => array(
|
477 |
+
'max_file_size' => wp_max_upload_size() . 'b',
|
478 |
+
'url' => wp_nonce_url( admin_url( 'admin-ajax.php' ), 'panels_action', '_panelsnonce' ),
|
479 |
+
'flash_swf_url' => includes_url( 'js/plupload/plupload.flash.swf' ),
|
480 |
+
'silverlight_xap_url' => includes_url( 'js/plupload/plupload.silverlight.xap' ),
|
481 |
+
'filter_title' => __( 'Page Builder layouts', 'siteorigin-panels' ),
|
482 |
+
'error_message' => __( 'Error uploading or importing file.', 'siteorigin-panels' ),
|
483 |
+
),
|
484 |
+
'wpColorPickerOptions' => apply_filters( 'siteorigin_panels_wpcolorpicker_options', array() ),
|
485 |
+
'prebuiltDefaultScreenshot' => siteorigin_panels_url( 'css/images/prebuilt-default.png' ),
|
486 |
+
'loadOnAttach' => $load_on_attach ,
|
487 |
+
'siteoriginWidgetRegex' => str_replace( '*+', '*', get_shortcode_regex( array( 'siteorigin_widget' ) ) ),
|
488 |
+
'forms' => array(
|
489 |
+
'loadingFailed' => __( 'Unknown error. Failed to load the form. Please check your internet connection, contact your web site administrator, or try again later.', 'siteorigin-panels' ),
|
490 |
+
)
|
491 |
+
) );
|
492 |
+
|
493 |
+
$js_widgets = array();
|
494 |
+
if ( $screen->base != 'widgets' ) {
|
495 |
+
// Render all the widget forms. A lot of widgets use this as a chance to enqueue their scripts
|
496 |
+
$original_post = isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : null; // Make sure widgets don't change the global post.
|
497 |
+
global $wp_widget_factory;
|
498 |
+
foreach ( $wp_widget_factory->widgets as $widget_obj ) {
|
499 |
+
ob_start();
|
500 |
+
$return = $widget_obj->form( array() );
|
501 |
+
// These are the new widgets in WP 4.8 which are largely JS based. They only enqueue their own
|
502 |
+
// scripts on the 'widgets' screen.
|
503 |
+
if ( $this->is_core_js_widget( $widget_obj ) && method_exists( $widget_obj, 'enqueue_admin_scripts' ) ) {
|
504 |
+
$widget_obj->enqueue_admin_scripts();
|
505 |
+
}
|
506 |
+
do_action_ref_array( 'in_widget_form', array( &$widget_obj, &$return, array() ) );
|
507 |
+
ob_end_clean();
|
508 |
+
|
509 |
+
// Need to render templates for new WP 4.8 widgets when not on the 'widgets' screen or in the customizer.
|
510 |
+
if ( $this->is_core_js_widget( $widget_obj ) ) {
|
511 |
+
$js_widgets[] = $widget_obj;
|
512 |
+
}
|
513 |
+
}
|
514 |
+
$GLOBALS['post'] = $original_post;
|
515 |
+
}
|
516 |
+
|
517 |
+
// This gives panels a chance to enqueue scripts too, without having to check the screen ID.
|
518 |
+
if ( $screen->base != 'widgets' && $screen->base != 'customize' ) {
|
519 |
+
foreach ( $js_widgets as $js_widget ) {
|
520 |
+
$js_widget->render_control_template_scripts();
|
521 |
+
}
|
522 |
+
do_action( 'siteorigin_panel_enqueue_admin_scripts' );
|
523 |
+
do_action( 'sidebar_admin_setup' );
|
524 |
+
}
|
525 |
+
}
|
526 |
+
}
|
527 |
+
|
528 |
+
public function enqueue_yoast_compat(){
|
529 |
+
if( self::is_admin() && defined( 'WPSEO_FILE' ) && wp_script_is( 'yoast-seo-metabox' ) ) {
|
530 |
+
wp_enqueue_script(
|
531 |
+
'so-panels-yoast-compat',
|
532 |
+
siteorigin_panels_url( 'js/yoast-compat' . SITEORIGIN_PANELS_JS_SUFFIX . '.js' ),
|
533 |
+
array('jquery', 'yoast-seo-metabox' ),
|
534 |
+
SITEORIGIN_PANELS_VERSION,
|
535 |
+
true
|
536 |
+
);
|
537 |
+
}
|
538 |
+
}
|
539 |
+
|
540 |
+
/**
|
541 |
+
* Enqueue the admin panel styles
|
542 |
+
*
|
543 |
+
* @param string $prefix
|
544 |
+
* @param bool $force Should we force the enqueue
|
545 |
+
*
|
546 |
+
* @action admin_print_styles-post-new.php
|
547 |
+
* @action admin_print_styles-post.php
|
548 |
+
*/
|
549 |
+
function enqueue_admin_styles( $prefix = '', $force = false ) {
|
550 |
+
if ( $force || self::is_admin() ) {
|
551 |
+
wp_enqueue_style(
|
552 |
+
'so-panels-admin',
|
553 |
+
siteorigin_panels_url( 'css/admin' . SITEORIGIN_PANELS_CSS_SUFFIX . '.css' ),
|
554 |
+
array( 'wp-color-picker' ),
|
555 |
+
SITEORIGIN_PANELS_VERSION
|
556 |
+
);
|
557 |
+
do_action( 'siteorigin_panel_enqueue_admin_styles' );
|
558 |
+
}
|
559 |
+
}
|
560 |
+
|
561 |
+
/**
|
562 |
+
* Add a help tab to pages that include a Page Builder interface.
|
563 |
+
*
|
564 |
+
* @param $prefix
|
565 |
+
*/
|
566 |
+
function add_help_tab( $prefix ) {
|
567 |
+
$screen = get_current_screen();
|
568 |
+
if (
|
569 |
+
( $screen->base == 'post' && ( in_array( $screen->id, siteorigin_panels_setting( 'post-types' ) ) || $screen->id == '' ) )
|
570 |
+
|| ( $screen->id == 'appearance_page_so_panels_home_page' )
|
571 |
+
) {
|
572 |
+
$screen->add_help_tab( array(
|
573 |
+
'id' => 'panels-help-tab', //unique id for the tab
|
574 |
+
'title' => __( 'Page Builder', 'siteorigin-panels' ), //unique visible title for the tab
|
575 |
+
'callback' => array( $this, 'help_tab_content' )
|
576 |
+
) );
|
577 |
+
}
|
578 |
+
}
|
579 |
+
|
580 |
+
/**
|
581 |
+
* Display the content for the help tab.
|
582 |
+
*/
|
583 |
+
function help_tab_content() {
|
584 |
+
include plugin_dir_path( __FILE__ ) . '../tpl/help.php';
|
585 |
+
}
|
586 |
+
|
587 |
+
/**
|
588 |
+
* Get the Page Builder data for the current admin page.
|
589 |
+
*
|
590 |
+
* @return array
|
591 |
+
*/
|
592 |
+
function get_current_admin_panels_data() {
|
593 |
+
$screen = get_current_screen();
|
594 |
+
|
595 |
+
// Localize the panels with the panels data
|
596 |
+
if ( $screen->base == 'appearance_page_so_panels_home_page' ) {
|
597 |
+
$home_page_id = get_option( 'page_on_front' );
|
598 |
+
if ( empty( $home_page_id ) ) {
|
599 |
+
$home_page_id = get_option( 'siteorigin_panels_home_page_id' );
|
600 |
+
}
|
601 |
+
|
602 |
+
$panels_data = ! empty( $home_page_id ) ? get_post_meta( $home_page_id, 'panels_data', true ) : null;
|
603 |
+
|
604 |
+
if ( is_null( $panels_data ) ) {
|
605 |
+
// Load the default layout
|
606 |
+
$layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
|
607 |
+
|
608 |
+
$home_name = siteorigin_panels_setting( 'home-page-default' ) ? siteorigin_panels_setting( 'home-page-default' ) : 'home';
|
609 |
+
$panels_data = ! empty( $layouts[ $home_name ] ) ? $layouts[ $home_name ] : current( $layouts );
|
610 |
+
} elseif ( empty( $panels_data ) ) {
|
611 |
+
// The current page_on_front isn't using page builder
|
612 |
+
return false;
|
613 |
+
}
|
614 |
+
|
615 |
+
$panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, 'home' );
|
616 |
+
} else {
|
617 |
+
global $post;
|
618 |
+
if ( ! empty( $post ) ) {
|
619 |
+
$panels_data = get_post_meta( $post->ID, 'panels_data', true );
|
620 |
+
$panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, $post->ID );
|
621 |
+
}
|
622 |
+
}
|
623 |
+
|
624 |
+
if ( empty( $panels_data ) ) {
|
625 |
+
$panels_data = array();
|
626 |
+
}
|
627 |
+
|
628 |
+
return $panels_data;
|
629 |
+
}
|
630 |
+
|
631 |
+
/**
|
632 |
+
* Save home page
|
633 |
+
*/
|
634 |
+
function save_home_page() {
|
635 |
+
if ( ! isset( $_POST['_sopanels_home_nonce'] ) || ! wp_verify_nonce( $_POST['_sopanels_home_nonce'], 'save' ) ) {
|
636 |
+
return;
|
637 |
+
}
|
638 |
+
if ( ! current_user_can( 'edit_theme_options' ) ) {
|
639 |
+
return;
|
640 |
+
}
|
641 |
+
if ( ! isset( $_POST['panels_data'] ) ) {
|
642 |
+
return;
|
643 |
+
}
|
644 |
+
|
645 |
+
// Check that the home page ID is set and the home page exists
|
646 |
+
$page_id = get_option( 'page_on_front' );
|
647 |
+
if ( empty( $page_id ) ) {
|
648 |
+
$page_id = get_option( 'siteorigin_panels_home_page_id' );
|
649 |
+
}
|
650 |
+
|
651 |
+
$post_content = wp_unslash( $_POST['post_content'] );
|
652 |
+
|
653 |
+
if ( ! $page_id || get_post_meta( $page_id, 'panels_data', true ) == '' ) {
|
654 |
+
// Lets create a new page
|
655 |
+
$page_id = wp_insert_post( array(
|
656 |
+
// TRANSLATORS: This is the default name given to a user's home page
|
657 |
+
'post_title' => __( 'Home Page', 'siteorigin-panels' ),
|
658 |
+
'post_status' => ! empty( $_POST['siteorigin_panels_home_enabled'] ) ? 'publish' : 'draft',
|
659 |
+
'post_type' => 'page',
|
660 |
+
'post_content' => $post_content,
|
661 |
+
'comment_status' => 'closed',
|
662 |
+
) );
|
663 |
+
update_option( 'page_on_front', $page_id );
|
664 |
+
update_option( 'siteorigin_panels_home_page_id', $page_id );
|
665 |
+
|
666 |
+
// Action triggered when creating a new home page through the custom home page interface
|
667 |
+
do_action( 'siteorigin_panels_create_home_page', $page_id );
|
668 |
+
} else {
|
669 |
+
// `wp_insert_post` does it's own sanitization, but it seems `wp_update_post` doesn't.
|
670 |
+
$post_content = sanitize_post_field( 'post_content', $post_content, $page_id, 'db' );
|
671 |
+
|
672 |
+
// Update the post with changed content to save revision if necessary.
|
673 |
+
wp_update_post( array( 'ID' => $page_id, 'post_content' => $post_content ) );
|
674 |
+
}
|
675 |
+
|
676 |
+
$page = get_post( $page_id );
|
677 |
+
|
678 |
+
// Save the updated page data
|
679 |
+
$old_panels_data = get_post_meta( $page_id, 'panels_data', true );
|
680 |
+
$panels_data = json_decode( wp_unslash( $_POST['panels_data'] ), true );
|
681 |
+
$panels_data['widgets'] = $this->process_raw_widgets(
|
682 |
+
$panels_data['widgets'],
|
683 |
+
! empty( $old_panels_data['widgets'] ) ? $old_panels_data['widgets'] : false,
|
684 |
+
false
|
685 |
+
);
|
686 |
+
|
687 |
+
if ( siteorigin_panels_setting( 'sidebars-emulator' ) ) {
|
688 |
+
$sidebars_emulator = SiteOrigin_Panels_Sidebars_Emulator::single();
|
689 |
+
$panels_data['widgets'] = $sidebars_emulator->generate_sidebar_widget_ids( $panels_data['widgets'], $page_id );
|
690 |
+
}
|
691 |
+
|
692 |
+
$panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
|
693 |
+
$panels_data = apply_filters( 'siteorigin_panels_data_pre_save', $panels_data, $page, $page_id );
|
694 |
+
|
695 |
+
update_post_meta( $page_id, 'panels_data', map_deep( $panels_data, array( 'SiteOrigin_Panels_Admin', 'double_slash_string' ) ) );
|
696 |
+
|
697 |
+
$template = get_post_meta( $page_id, '_wp_page_template', true );
|
698 |
+
$home_template = siteorigin_panels_setting( 'home-template' );
|
699 |
+
if ( ( $template == '' || $template == 'default' ) && ! empty( $home_template ) ) {
|
700 |
+
// Set the home page template
|
701 |
+
update_post_meta( $page_id, '_wp_page_template', $home_template );
|
702 |
+
}
|
703 |
+
|
704 |
+
if ( ! empty( $_POST['siteorigin_panels_home_enabled'] ) ) {
|
705 |
+
update_option( 'show_on_front', 'page' );
|
706 |
+
update_option( 'page_on_front', $page_id );
|
707 |
+
update_option( 'siteorigin_panels_home_page_id', $page_id );
|
708 |
+
wp_publish_post( $page_id );
|
709 |
+
} else {
|
710 |
+
// We're disabling this home page
|
711 |
+
update_option( 'show_on_front', 'posts' );
|
712 |
+
|
713 |
+
// Change the post status to draft
|
714 |
+
$post = get_post( $page_id );
|
715 |
+
if ( $post->post_status != 'draft' ) {
|
716 |
+
global $wpdb;
|
717 |
+
|
718 |
+
$wpdb->update( $wpdb->posts, array( 'post_status' => 'draft' ), array( 'ID' => $post->ID ) );
|
719 |
+
clean_post_cache( $post->ID );
|
720 |
+
|
721 |
+
$old_status = $post->post_status;
|
722 |
+
$post->post_status = 'draft';
|
723 |
+
wp_transition_post_status( 'draft', $old_status, $post );
|
724 |
+
|
725 |
+
do_action( 'edit_post', $post->ID, $post );
|
726 |
+
do_action( "save_post_{$post->post_type}", $post->ID, $post, true );
|
727 |
+
do_action( 'save_post', $post->ID, $post, true );
|
728 |
+
do_action( 'wp_insert_post', $post->ID, $post, true );
|
729 |
+
}
|
730 |
+
}
|
731 |
+
}
|
732 |
+
|
733 |
+
/**
|
734 |
+
* After the theme is switched, change the template on the home page if the theme supports home page functionality.
|
735 |
+
*/
|
736 |
+
function update_home_on_theme_change() {
|
737 |
+
$page_id = get_option( 'page_on_front' );
|
738 |
+
if ( empty( $page_id ) ) {
|
739 |
+
$page_id = get_option( 'siteorigin_panels_home_page_id' );
|
740 |
+
}
|
741 |
+
|
742 |
+
if ( siteorigin_panels_setting( 'home-page' ) && siteorigin_panels_setting( 'home-template' ) && $page_id && get_post_meta( $page_id, 'panels_data', true ) !== '' ) {
|
743 |
+
// Lets update the home page to use the home template that this theme supports
|
744 |
+
update_post_meta( $page_id, '_wp_page_template', siteorigin_panels_setting( 'home-template' ) );
|
745 |
+
}
|
746 |
+
}
|
747 |
+
|
748 |
+
/**
|
749 |
+
* @return array|mixed|void
|
750 |
+
*/
|
751 |
+
function get_widgets() {
|
752 |
+
global $wp_widget_factory;
|
753 |
+
$widgets = array();
|
754 |
+
foreach ( $wp_widget_factory->widgets as $widget_obj ) {
|
755 |
+
$class = get_class( $widget_obj );
|
756 |
+
$widgets[ $class ] = array(
|
757 |
+
'class' => $class,
|
758 |
+
'title' => ! empty( $widget_obj->name ) ? $widget_obj->name : __( 'Untitled Widget', 'siteorigin-panels' ),
|
759 |
+
'description' => ! empty( $widget_obj->widget_options['description'] ) ? $widget_obj->widget_options['description'] : '',
|
760 |
+
'installed' => true,
|
761 |
+
'groups' => array(),
|
762 |
+
);
|
763 |
+
|
764 |
+
// Get Page Builder specific widget options
|
765 |
+
if ( isset( $widget_obj->widget_options['panels_title'] ) ) {
|
766 |
+
$widgets[ $class ]['panels_title'] = $widget_obj->widget_options['panels_title'];
|
767 |
+
}
|
768 |
+
if ( isset( $widget_obj->widget_options['panels_groups'] ) ) {
|
769 |
+
$widgets[ $class ]['groups'] = $widget_obj->widget_options['panels_groups'];
|
770 |
+
}
|
771 |
+
if ( isset( $widget_obj->widget_options['panels_icon'] ) ) {
|
772 |
+
$widgets[ $class ]['icon'] = $widget_obj->widget_options['panels_icon'];
|
773 |
+
}
|
774 |
+
|
775 |
+
}
|
776 |
+
|
777 |
+
// Other plugins can manipulate the list of widgets. Possibly to add recommended widgets
|
778 |
+
$widgets = apply_filters( 'siteorigin_panels_widgets', $widgets );
|
779 |
+
|
780 |
+
// Exclude these temporarily, as they won't work until we have a reliable way to enqueue their admin form scripts.
|
781 |
+
$to_exclude = array(
|
782 |
+
'Jetpack_Gallery_Widget',
|
783 |
+
'WPCOM_Widget_GooglePlus_Badge',
|
784 |
+
'Jetpack_Widget_Social_Icons',
|
785 |
+
'Jetpack_Twitter_Timeline_Widget'
|
786 |
+
);
|
787 |
+
|
788 |
+
foreach ( $to_exclude as $widget_class ) {
|
789 |
+
if ( in_array( $widget_class, $widgets ) ) {
|
790 |
+
unset( $widgets[ $widget_class ] );
|
791 |
+
}
|
792 |
+
}
|
793 |
+
|
794 |
+
// Sort the widgets alphabetically
|
795 |
+
uasort( $widgets, array( $this, 'widgets_sorter' ) );
|
796 |
+
|
797 |
+
return $widgets;
|
798 |
+
}
|
799 |
+
|
800 |
+
/**
|
801 |
+
* Sorts widgets for get_widgets function by title
|
802 |
+
*
|
803 |
+
* @param $a
|
804 |
+
* @param $b
|
805 |
+
*
|
806 |
+
* @return int
|
807 |
+
*/
|
808 |
+
function widgets_sorter( $a, $b ) {
|
809 |
+
if ( empty( $a['title'] ) ) {
|
810 |
+
return - 1;
|
811 |
+
}
|
812 |
+
if ( empty( $b['title'] ) ) {
|
813 |
+
return 1;
|
814 |
+
}
|
815 |
+
|
816 |
+
return $a['title'] > $b['title'] ? 1 : - 1;
|
817 |
+
}
|
818 |
+
|
819 |
+
/**
|
820 |
+
* Process raw widgets that have come from the Page Builder front end.
|
821 |
+
*
|
822 |
+
* @param array $widgets An array of widgets from panels_data.
|
823 |
+
* @param array $old_widgets
|
824 |
+
* @param bool $escape_classes Should the class names be escaped.
|
825 |
+
* @param bool $force
|
826 |
+
*
|
827 |
+
* @return array
|
828 |
+
*/
|
829 |
+
function process_raw_widgets( $widgets, $old_widgets = array(), $escape_classes = false, $force = false ) {
|
830 |
+
if ( empty( $widgets ) || ! is_array( $widgets ) ) {
|
831 |
+
return array();
|
832 |
+
}
|
833 |
+
|
834 |
+
$old_widgets_by_id = array();
|
835 |
+
if( ! empty( $old_widgets ) ) {
|
836 |
+
foreach( $old_widgets as $widget ) {
|
837 |
+
if( ! empty( $widget[ 'panels_info' ][ 'widget_id' ] ) ) {
|
838 |
+
$old_widgets_by_id[ $widget[ 'panels_info' ][ 'widget_id' ] ] = $widget;
|
839 |
+
unset( $old_widgets_by_id[ $widget[ 'panels_info' ][ 'widget_id' ] ][ 'panels_info' ] );
|
840 |
+
}
|
841 |
+
}
|
842 |
+
}
|
843 |
+
|
844 |
+
foreach( $widgets as $i => & $widget ) {
|
845 |
+
if ( ! is_array( $widget ) ) {
|
846 |
+
continue;
|
847 |
+
}
|
848 |
+
|
849 |
+
if ( is_array( $widget ) ) {
|
850 |
+
$info = (array) ( is_array( $widget['panels_info'] ) ? $widget['panels_info'] : $widget['info'] );
|
851 |
+
} else {
|
852 |
+
$info = array();
|
853 |
+
}
|
854 |
+
unset( $widget['info'] );
|
855 |
+
|
856 |
+
$info[ 'class' ] = apply_filters( 'siteorigin_panels_widget_class', $info[ 'class' ] );
|
857 |
+
|
858 |
+
if ( ! empty( $info['raw'] ) || $force ) {
|
859 |
+
$the_widget = SiteOrigin_Panels::get_widget_instance( $info['class'] );
|
860 |
+
if ( ! empty( $the_widget ) &&
|
861 |
+
method_exists( $the_widget, 'update' ) ) {
|
862 |
+
|
863 |
+
if(
|
864 |
+
! empty( $old_widgets_by_id ) &&
|
865 |
+
! empty( $widget[ 'panels_info' ][ 'widget_id' ] ) &&
|
866 |
+
! empty( $old_widgets_by_id[ $widget[ 'panels_info' ][ 'widget_id' ] ] )
|
867 |
+
){
|
868 |
+
$old_widget = $old_widgets_by_id[ $widget[ 'panels_info' ][ 'widget_id' ] ];
|
869 |
+
}
|
870 |
+
else {
|
871 |
+
$old_widget = $widget;
|
872 |
+
}
|
873 |
+
|
874 |
+
/** @var WP_Widget $the_widget */
|
875 |
+
$the_widget = SiteOrigin_Panels::get_widget_instance( $info['class'] );
|
876 |
+
$instance = $the_widget->update( $widget, $old_widget );
|
877 |
+
$instance = apply_filters( 'widget_update_callback', $instance, $widget, $old_widget, $the_widget );
|
878 |
+
|
879 |
+
$widget = $instance;
|
880 |
+
|
881 |
+
unset( $info['raw'] );
|
882 |
+
}
|
883 |
+
}
|
884 |
+
|
885 |
+
if( $escape_classes ) {
|
886 |
+
// Escaping for namespaced widgets
|
887 |
+
$info[ 'class' ] = preg_replace( '/\\\\+/', '\\\\\\\\', $info['class'] );
|
888 |
+
}
|
889 |
+
|
890 |
+
$widget['panels_info'] = $info;
|
891 |
+
}
|
892 |
+
|
893 |
+
return $widgets;
|
894 |
+
}
|
895 |
+
|
896 |
+
/**
|
897 |
+
* Add all the footer JS templates.
|
898 |
+
*/
|
899 |
+
function js_templates() {
|
900 |
+
include plugin_dir_path( __FILE__ ) . '../tpl/js-templates.php';
|
901 |
+
}
|
902 |
+
|
903 |
+
/**
|
904 |
+
* Render a widget form with all the Page Builder specific fields
|
905 |
+
*
|
906 |
+
* @param string $widget_class The class of the widget
|
907 |
+
* @param array $instance Widget values
|
908 |
+
* @param bool $raw
|
909 |
+
* @param string $widget_number
|
910 |
+
*
|
911 |
+
* @return mixed|string The form
|
912 |
+
*/
|
913 |
+
function render_form( $widget_class, $instance = array(), $raw = false, $widget_number = '{$id}' ) {
|
914 |
+
|
915 |
+
$the_widget = SiteOrigin_Panels::get_widget_instance( $widget_class );
|
916 |
+
// This is a chance for plugins to replace missing widgets
|
917 |
+
$the_widget = apply_filters( 'siteorigin_panels_widget_object', $the_widget, $widget_class );
|
918 |
+
|
919 |
+
if ( empty( $the_widget ) || ! is_a( $the_widget, 'WP_Widget' ) ) {
|
920 |
+
$widgets = $this->get_widgets();
|
921 |
+
|
922 |
+
if ( ! empty( $widgets[ $widget_class ] ) && ! empty( $widgets[ $widget_class ]['plugin'] ) ) {
|
923 |
+
// We know about this widget, show a form about installing it.
|
924 |
+
$install_url = siteorigin_panels_plugin_activation_install_url( $widgets[ $widget_class ]['plugin']['slug'], $widgets[ $widget_class ]['plugin']['name'] );
|
925 |
+
$form =
|
926 |
+
'<div class="panels-missing-widget-form">' .
|
927 |
+
'<p>' .
|
928 |
+
preg_replace(
|
929 |
+
array(
|
930 |
+
'/1\{ *(.*?) *\}/',
|
931 |
+
'/2\{ *(.*?) *\}/',
|
932 |
+
),
|
933 |
+
array(
|
934 |
+
'<a href="' . $install_url . '" target="_blank" rel="noopener noreferrer">$1</a>',
|
935 |
+
'<strong>$1</strong>'
|
936 |
+
),
|
937 |
+
sprintf(
|
938 |
+
__( 'You need to install 1{%1$s} to use the widget 2{%2$s}.', 'siteorigin-panels' ),
|
939 |
+
$widgets[ $widget_class ]['plugin']['name'],
|
940 |
+
$widget_class
|
941 |
+
)
|
942 |
+
) .
|
943 |
+
'</p>' .
|
944 |
+
'<p>' . __( "Save and reload this page to start using the widget after you've installed it.", 'siteorigin-panels' ) . '</p>' .
|
945 |
+
'</div>';
|
946 |
+
} else {
|
947 |
+
// This widget is missing, so show a missing widgets form.
|
948 |
+
$form =
|
949 |
+
'<div class="panels-missing-widget-form"><p>' .
|
950 |
+
preg_replace(
|
951 |
+
array(
|
952 |
+
'/1\{ *(.*?) *\}/',
|
953 |
+
'/2\{ *(.*?) *\}/',
|
954 |
+
),
|
955 |
+
array(
|
956 |
+
'<strong>$1</strong>',
|
957 |
+
'<a href="https://siteorigin.com/thread/" target="_blank" rel="noopener noreferrer">$1</a>'
|
958 |
+
),
|
959 |
+
sprintf(
|
960 |
+
__( '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.', 'siteorigin-panels' ),
|
961 |
+
esc_html( $widget_class )
|
962 |
+
)
|
963 |
+
) .
|
964 |
+
'</p></div>';
|
965 |
+
}
|
966 |
+
|
967 |
+
// Allow other themes and plugins to change the missing widget form
|
968 |
+
return apply_filters( 'siteorigin_panels_missing_widget_form', $form, $widget_class, $instance );
|
969 |
+
}
|
970 |
+
|
971 |
+
if ( $raw ) {
|
972 |
+
$instance = $the_widget->update( $instance, $instance );
|
973 |
+
}
|
974 |
+
|
975 |
+
$the_widget->id = 'temp';
|
976 |
+
$the_widget->number = $widget_number;
|
977 |
+
|
978 |
+
ob_start();
|
979 |
+
if ( $this->is_core_js_widget( $the_widget ) ) {
|
980 |
+
?><div class="widget-content"><?php
|
981 |
+
}
|
982 |
+
$return = $the_widget->form( $instance );
|
983 |
+
do_action_ref_array( 'in_widget_form', array( &$the_widget, &$return, $instance ) );
|
984 |
+
if ( $this->is_core_js_widget( $the_widget ) ) {
|
985 |
+
?>
|
986 |
+
</div>
|
987 |
+
<input type="hidden" name="id_base" class="id_base" value="<?php echo esc_attr( $the_widget->id_base ); ?>" />
|
988 |
+
<?php
|
989 |
+
}
|
990 |
+
$form = ob_get_clean();
|
991 |
+
|
992 |
+
// Convert the widget field naming into ones that Page Builder uses
|
993 |
+
$exp = preg_quote( $the_widget->get_field_name( '____' ) );
|
994 |
+
$exp = str_replace( '____', '(.*?)', $exp );
|
995 |
+
$form = preg_replace( '/' . $exp . '/', 'widgets[' . preg_replace( '/\$(\d)/', '\\\$$1', $widget_number ) . '][$1]', $form );
|
996 |
+
|
997 |
+
$form = apply_filters( 'siteorigin_panels_widget_form', $form, $widget_class, $instance );
|
998 |
+
|
999 |
+
// Add all the information fields
|
1000 |
+
return $form;
|
1001 |
+
}
|
1002 |
+
|
1003 |
+
/**
|
1004 |
+
* Checks whether a widget is considered to be a JS widget. I.e. it needs to have scripts and/or styles enqueued for
|
1005 |
+
* it's admin form to work.
|
1006 |
+
*
|
1007 |
+
* Can remove the whitelist of core widgets when all widgets are following a similar pattern.
|
1008 |
+
*
|
1009 |
+
* @param $widget The widget to be tested.
|
1010 |
+
*
|
1011 |
+
* @return bool Whether or not the widget is considered a JS widget.
|
1012 |
+
*/
|
1013 |
+
function is_core_js_widget( $widget ) {
|
1014 |
+
$js_widgets = array(
|
1015 |
+
'WP_Widget_Custom_HTML',
|
1016 |
+
'WP_Widget_Media_Audio',
|
1017 |
+
'WP_Widget_Media_Gallery',
|
1018 |
+
'WP_Widget_Media_Image',
|
1019 |
+
'WP_Widget_Media_Video',
|
1020 |
+
'WP_Widget_Text',
|
1021 |
+
);
|
1022 |
+
|
1023 |
+
$is_js_widget = in_array( get_class( $widget ), $js_widgets ) &&
|
1024 |
+
// Need to check this for `WP_Widget_Text` which was not a JS widget before 4.8
|
1025 |
+
method_exists( $widget, 'render_control_template_scripts' );
|
1026 |
+
|
1027 |
+
return $is_js_widget;
|
1028 |
+
}
|
1029 |
+
|
1030 |
+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
1031 |
+
// ADMIN AJAX ACTIONS
|
1032 |
+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
1033 |
+
|
1034 |
+
/**
|
1035 |
+
* Get builder content based on the submitted panels_data.
|
1036 |
+
*/
|
1037 |
+
function action_builder_content() {
|
1038 |
+
header( 'content-type: text/html' );
|
1039 |
+
|
1040 |
+
if ( ! current_user_can( 'edit_post', $_POST['post_id'] ) ) {
|
1041 |
+
wp_die();
|
1042 |
+
}
|
1043 |
+
|
1044 |
+
if ( empty( $_POST['post_id'] ) || empty( $_POST['panels_data'] ) ) {
|
1045 |
+
echo '';
|
1046 |
+
wp_die();
|
1047 |
+
}
|
1048 |
+
|
1049 |
+
// echo the content
|
1050 |
+
$old_panels_data = get_post_meta( $_POST['post_id'], 'panels_data', true );
|
1051 |
+
$panels_data = json_decode( wp_unslash( $_POST['panels_data'] ), true );
|
1052 |
+
$panels_data['widgets'] = $this->process_raw_widgets(
|
1053 |
+
$panels_data['widgets'],
|
1054 |
+
! empty( $old_panels_data['widgets'] ) ? $old_panels_data['widgets'] : false,
|
1055 |
+
false
|
1056 |
+
);
|
1057 |
+
$panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
|
1058 |
+
|
1059 |
+
// Create a version of the builder data for post content
|
1060 |
+
SiteOrigin_Panels_Post_Content_Filters::add_filters();
|
1061 |
+
$GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] = true;
|
1062 |
+
echo SiteOrigin_Panels::renderer()->render( intval( $_POST['post_id'] ), false, $panels_data );
|
1063 |
+
SiteOrigin_Panels_Post_Content_Filters::remove_filters();
|
1064 |
+
unset( $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] );
|
1065 |
+
|
1066 |
+
wp_die();
|
1067 |
+
}
|
1068 |
+
|
1069 |
+
/**
|
1070 |
+
* Display a widget form with the provided data
|
1071 |
+
*/
|
1072 |
+
function action_widget_form() {
|
1073 |
+
if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
|
1074 |
+
wp_die(
|
1075 |
+
__( 'The supplied nonce is invalid.', 'siteorigin-panels' ),
|
1076 |
+
__( 'Invalid nonce.', 'siteorigin-panels' ),
|
1077 |
+
403
|
1078 |
+
);
|
1079 |
+
}
|
1080 |
+
if ( empty( $_REQUEST['widget'] ) ) {
|
1081 |
+
wp_die(
|
1082 |
+
__( 'Please specify the type of widget form to be rendered.', 'siteorigin-panels' ),
|
1083 |
+
__( 'Missing widget type.', 'siteorigin-panels' ),
|
1084 |
+
400
|
1085 |
+
);
|
1086 |
+
}
|
1087 |
+
|
1088 |
+
$request = array_map( 'stripslashes_deep', $_REQUEST );
|
1089 |
+
|
1090 |
+
$widget_class = $request['widget'];
|
1091 |
+
$widget_class = apply_filters( 'siteorigin_panels_widget_class', $widget_class );
|
1092 |
+
$instance = ! empty( $request['instance'] ) ? json_decode( $request['instance'], true ) : array();
|
1093 |
+
|
1094 |
+
$form = $this->render_form( $widget_class, $instance, $_REQUEST['raw'] == 'true' );
|
1095 |
+
$form = apply_filters( 'siteorigin_panels_ajax_widget_form', $form, $widget_class, $instance );
|
1096 |
+
|
1097 |
+
echo $form;
|
1098 |
+
wp_die();
|
1099 |
+
}
|
1100 |
+
|
1101 |
+
/**
|
1102 |
+
* Preview in the live editor when there is no public view of the item
|
1103 |
+
*/
|
1104 |
+
function action_live_editor_preview() {
|
1105 |
+
if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'live-editor-preview' ) ) {
|
1106 |
+
wp_die();
|
1107 |
+
}
|
1108 |
+
|
1109 |
+
include plugin_dir_path( __FILE__ ) . '../tpl/live-editor-preview.php';
|
1110 |
+
|
1111 |
+
exit();
|
1112 |
+
}
|
1113 |
+
|
1114 |
+
/**
|
1115 |
+
* Preview in the block editor.
|
1116 |
+
*/
|
1117 |
+
public function layout_block_preview() {
|
1118 |
+
|
1119 |
+
if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'layout-block-preview' ) ) {
|
1120 |
+
wp_die();
|
1121 |
+
}
|
1122 |
+
|
1123 |
+
$panels_data = json_decode( wp_unslash( $_POST['panelsData'] ), true );
|
1124 |
+
$builder_id = 'gbp' . uniqid();
|
1125 |
+
$panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'], false, true, true );
|
1126 |
+
$panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
|
1127 |
+
$sowb_active = class_exists( 'SiteOrigin_Widgets_Bundle' );
|
1128 |
+
if ( $sowb_active ) {
|
1129 |
+
// We need this to get our widgets bundle to add it's styles inline for previews.
|
1130 |
+
add_filter( 'siteorigin_widgets_is_preview', '__return_true' );
|
1131 |
+
}
|
1132 |
+
$rendered_layout = SiteOrigin_Panels::renderer()->render( $builder_id, true, $panels_data, $layout_data, true );
|
1133 |
+
|
1134 |
+
// Need to explicitly call `siteorigin_widget_print_styles` because Gutenberg previews don't render a full version of the front end,
|
1135 |
+
// so neither the `wp_head` nor the `wp_footer` actions are called, which usually trigger `siteorigin_widget_print_styles`.
|
1136 |
+
if ( $sowb_active ) {
|
1137 |
+
ob_start();
|
1138 |
+
siteorigin_widget_print_styles();
|
1139 |
+
$rendered_layout .= ob_get_clean();
|
1140 |
+
}
|
1141 |
+
|
1142 |
+
echo $rendered_layout;
|
1143 |
+
wp_die();
|
1144 |
+
}
|
1145 |
+
|
1146 |
+
public function layout_block_sanitize() {
|
1147 |
+
|
1148 |
+
if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'layout-block-sanitize' ) ) {
|
1149 |
+
wp_die();
|
1150 |
+
}
|
1151 |
+
|
1152 |
+
$panels_data = json_decode( wp_unslash( $_POST['panelsData'] ), true );
|
1153 |
+
$panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'], false, true, true );
|
1154 |
+
$panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
|
1155 |
+
|
1156 |
+
wp_send_json( $panels_data );
|
1157 |
+
}
|
1158 |
+
|
1159 |
+
/**
|
1160 |
+
* Add a column that indicates if a column is powered by Page Builder
|
1161 |
+
*
|
1162 |
+
* @param $columns
|
1163 |
+
*
|
1164 |
+
* @return array
|
1165 |
+
*/
|
1166 |
+
function add_custom_column( $columns ){
|
1167 |
+
$index = array_search( 'comments', array_keys( $columns ) );
|
1168 |
+
|
1169 |
+
if( empty( $index ) ) {
|
1170 |
+
$columns = array_merge(
|
1171 |
+
$columns,
|
1172 |
+
array( 'panels' => __( 'Page Builder', 'siteorigin-panels' ) )
|
1173 |
+
);
|
1174 |
+
}
|
1175 |
+
else {
|
1176 |
+
$columns = array_slice( $columns, 0, $index, true ) +
|
1177 |
+
array( 'panels' => __( 'Page Builder', 'siteorigin-panels' ) ) +
|
1178 |
+
array_slice( $columns, $index, count( $columns ) - 1, true );
|
1179 |
+
}
|
1180 |
+
|
1181 |
+
return $columns;
|
1182 |
+
}
|
1183 |
+
|
1184 |
+
function display_custom_column( $column, $post_id ){
|
1185 |
+
if( $column != 'panels' ) return;
|
1186 |
+
|
1187 |
+
$panels_data = get_post_meta( $post_id, 'panels_data', true );
|
1188 |
+
if( ! empty( $panels_data['widgets'] ) ) {
|
1189 |
+
$widgets_count = count( $panels_data['widgets'] );
|
1190 |
+
printf( _n( '%s Widget', '%s Widgets', $widgets_count, 'siteorigin-panels' ), $widgets_count );
|
1191 |
+
}
|
1192 |
+
else {
|
1193 |
+
echo '—';
|
1194 |
+
}
|
1195 |
+
}
|
1196 |
+
|
1197 |
+
public function footer_column_css(){
|
1198 |
+
if( siteorigin_panels_setting( 'admin-widget-count' ) ) {
|
1199 |
+
$screen = get_current_screen();
|
1200 |
+
$post_types = siteorigin_panels_setting( 'post-types' );
|
1201 |
+
|
1202 |
+
if(
|
1203 |
+
$screen->base == 'edit' &&
|
1204 |
+
is_array( $post_types ) &&
|
1205 |
+
in_array( $screen->post_type, $post_types )
|
1206 |
+
){
|
1207 |
+
?><style type="text/css">.column-panels{ width: 10% }</style><?php
|
1208 |
+
}
|
1209 |
+
}
|
1210 |
+
}
|
1211 |
+
|
1212 |
+
/**
|
1213 |
+
* Add double slashes to strings
|
1214 |
+
*
|
1215 |
+
* @param $value
|
1216 |
+
*
|
1217 |
+
* @return string
|
1218 |
+
*/
|
1219 |
+
public static function double_slash_string( $value ){
|
1220 |
+
return is_string( $value ) ? addcslashes( $value, '\\' ) : $value;
|
1221 |
+
}
|
1222 |
+
|
1223 |
+
public function get_layout_directories(){
|
1224 |
+
|
1225 |
+
}
|
1226 |
+
|
1227 |
+
/**
|
1228 |
+
* Display links for various SiteOrigin addons
|
1229 |
+
*/
|
1230 |
+
public static function display_footer_premium_link(){
|
1231 |
+
$links = array(
|
1232 |
+
array(
|
1233 |
+
'text' => __('Get a lightbox addon for SiteOrigin widgets', 'siteorigin-panels'),
|
1234 |
+
'url' => SiteOrigin_Panels::premium_url('plugin/lightbox')
|
1235 |
+
),
|
1236 |
+
array(
|
1237 |
+
'text' => __('Get the row, cell and widget animations addon', 'siteorigin-panels'),
|
1238 |
+
'url' => SiteOrigin_Panels::premium_url('plugin/lightbox')
|
1239 |
+
),
|
1240 |
+
array(
|
1241 |
+
'text' => __('Get premium email support for SiteOrigin Page Builder', 'siteorigin-panels'),
|
1242 |
+
'url' => SiteOrigin_Panels::premium_url()
|
1243 |
+
),
|
1244 |
+
);
|
1245 |
+
$link = $links[array_rand($links)];
|
1246 |
+
|
1247 |
+
?>
|
1248 |
+
<a href="<?php echo esc_url( $link['url'] ) ?>" target="_blank" rel='noopener noreferrer'>
|
1249 |
+
<?php echo esc_html( $link['text'] ) ?>.
|
1250 |
+
</a>
|
1251 |
+
<?php
|
1252 |
+
}
|
1253 |
+
|
1254 |
+
public function admin_notices() {
|
1255 |
+
global $typenow, $pagenow;
|
1256 |
+
$is_new = $pagenow == 'post-new.php';
|
1257 |
+
$post_types = siteorigin_panels_setting( 'post-types' );
|
1258 |
+
$is_panels_type = in_array( $typenow, $post_types );
|
1259 |
+
$use_classic = siteorigin_panels_setting( 'use-classic' );
|
1260 |
+
$show_classic_admin_notice = $is_new && $is_panels_type && $use_classic;
|
1261 |
+
$show_classic_admin_notice = apply_filters( 'so_panels_show_classic_admin_notice', $show_classic_admin_notice );
|
1262 |
+
if ( $show_classic_admin_notice ) {
|
1263 |
+
$settings_url = self_admin_url( 'options-general.php?page=siteorigin_panels' );
|
1264 |
+
$notice = sprintf(
|
1265 |
+
__( 'This post type is set to use the Classic Editor by default for new posts. If you’d like to change this to the block editor, please go to <a href="%s" class="components-notice__action is-link">Page Builder Settings</a> and uncheck <strong>Use Classic Editor for new posts</strong>' ),
|
1266 |
+
$settings_url
|
1267 |
+
);
|
1268 |
+
?>
|
1269 |
+
<div id="siteorigin-panels-use-classic-notice" class="notice notice-info"><p id="use-classic-notice"><?php echo $notice ?></p></div>
|
1270 |
+
<?php
|
1271 |
+
}
|
1272 |
+
}
|
1273 |
+
|
1274 |
+
/**
|
1275 |
+
* Show Classic Editor for existing PB posts.
|
1276 |
+
*
|
1277 |
+
* @param $use_block_editor
|
1278 |
+
* @param $post_type
|
1279 |
+
*
|
1280 |
+
* @return bool
|
1281 |
+
*/
|
1282 |
+
public function show_classic_editor_for_panels( $use_block_editor, $post_type ) {
|
1283 |
+
|
1284 |
+
// For new pages.
|
1285 |
+
if ( isset( $_GET['block-editor'] ) ) {
|
1286 |
+
return $use_block_editor;
|
1287 |
+
} else if ( isset( $_GET['siteorigin-page-builder'] ) ) {
|
1288 |
+
return false;
|
1289 |
+
}
|
1290 |
+
|
1291 |
+
$post_types = siteorigin_panels_setting( 'post-types' );
|
1292 |
+
global $pagenow;
|
1293 |
+
// If the `$post_type` is set to be used by Page Builder for new posts.
|
1294 |
+
$is_new_panels_type = $pagenow == 'post-new.php' && in_array( $post_type, $post_types );
|
1295 |
+
$use_classic = siteorigin_panels_setting( 'use-classic' );
|
1296 |
+
// For existing posts.
|
1297 |
+
global $post;
|
1298 |
+
if ( ! empty( $post ) ) {
|
1299 |
+
// If the post has blocks just allow `$use_block_editor` to decide.
|
1300 |
+
if ( ! has_blocks( $post ) ) {
|
1301 |
+
$panels_data = get_post_meta( $post->ID, 'panels_data', true );
|
1302 |
+
if ( ! empty( $panels_data ) || ( $use_classic && $is_new_panels_type ) ) {
|
1303 |
+
$use_block_editor = false;
|
1304 |
+
}
|
1305 |
+
}
|
1306 |
+
} else if ( $is_new_panels_type ) {
|
1307 |
+
$use_block_editor = false;
|
1308 |
+
}
|
1309 |
+
|
1310 |
+
return $use_block_editor;
|
1311 |
+
}
|
1312 |
+
|
1313 |
+
/**
|
1314 |
+
* This was copied from Gutenberg and slightly modified as a quick way to allow users to create new Page Builder pages
|
1315 |
+
* in the classic editor without requiring the classic editor plugin be installed.
|
1316 |
+
*/
|
1317 |
+
function add_panels_add_new_button() {
|
1318 |
+
global $typenow;
|
1319 |
+
|
1320 |
+
if ( 'wp_block' === $typenow ) {
|
1321 |
+
?>
|
1322 |
+
<style type="text/css">
|
1323 |
+
.page-title-action {
|
1324 |
+
display: none;
|
1325 |
+
}
|
1326 |
+
</style>
|
1327 |
+
<?php
|
1328 |
+
}
|
1329 |
+
|
1330 |
+
if ( ! $this->show_add_new_dropdown_for_type( $typenow ) ) {
|
1331 |
+
return;
|
1332 |
+
}
|
1333 |
+
|
1334 |
+
?>
|
1335 |
+
<style type="text/css">
|
1336 |
+
.split-page-title-action {
|
1337 |
+
display: inline-block;
|
1338 |
+
}
|
1339 |
+
|
1340 |
+
.split-page-title-action a,
|
1341 |
+
.split-page-title-action a:active,
|
1342 |
+
.split-page-title-action .expander:after {
|
1343 |
+
padding: 6px 10px;
|
1344 |
+
position: relative;
|
1345 |
+
top: -3px;
|
1346 |
+
text-decoration: none;
|
1347 |
+
border: 1px solid #ccc;
|
1348 |
+
border-radius: 2px 0px 0px 2px;
|
1349 |
+
background: #f7f7f7;
|
1350 |
+
text-shadow: none;
|
1351 |
+
font-weight: 600;
|
1352 |
+
font-size: 13px;
|
1353 |
+
line-height: normal; /* IE8-IE11 need this for buttons */
|
1354 |
+
color: #0073aa; /* some of these controls are button elements and don't inherit from links */
|
1355 |
+
cursor: pointer;
|
1356 |
+
outline: 0;
|
1357 |
+
}
|
1358 |
+
|
1359 |
+
.split-page-title-action a:hover,
|
1360 |
+
.split-page-title-action .expander:hover:after {
|
1361 |
+
border-color: #008EC2;
|
1362 |
+
background: #00a0d2;
|
1363 |
+
color: #fff;
|
1364 |
+
}
|
1365 |
+
|
1366 |
+
.split-page-title-action a:focus,
|
1367 |
+
.split-page-title-action .expander:focus:after {
|
1368 |
+
border-color: #5b9dd9;
|
1369 |
+
box-shadow: 0 0 2px rgba( 30, 140, 190, 0.8 );
|
1370 |
+
}
|
1371 |
+
|
1372 |
+
.split-page-title-action .expander:after {
|
1373 |
+
content: "\f140";
|
1374 |
+
font: 400 20px/.5 dashicons;
|
1375 |
+
speak: none;
|
1376 |
+
top: 0px;
|
1377 |
+
<?php if ( is_rtl() ) : ?>
|
1378 |
+
right: -1px;
|
1379 |
+
<?php else : ?>
|
1380 |
+
left: -1px;
|
1381 |
+
<?php endif; ?>
|
1382 |
+
position: relative;
|
1383 |
+
vertical-align: top;
|
1384 |
+
text-decoration: none !important;
|
1385 |
+
padding: 4px 5px 5px 4px;
|
1386 |
+
border-radius: 0px 2px 2px 0px;
|
1387 |
+
}
|
1388 |
+
|
1389 |
+
.split-page-title-action .dropdown {
|
1390 |
+
display: none;
|
1391 |
+
}
|
1392 |
+
|
1393 |
+
.split-page-title-action .dropdown.visible {
|
1394 |
+
display: block;
|
1395 |
+
position: absolute;
|
1396 |
+
margin-top: 3px;
|
1397 |
+
z-index: 1;
|
1398 |
+
}
|
1399 |
+
|
1400 |
+
.split-page-title-action .dropdown.visible a {
|
1401 |
+
display: block;
|
1402 |
+
top: 0;
|
1403 |
+
margin: -1px 0;
|
1404 |
+
<?php if ( is_rtl() ) : ?>
|
1405 |
+
padding-left: 9px;
|
1406 |
+
<?php else : ?>
|
1407 |
+
padding-right: 9px;
|
1408 |
+
<?php endif; ?>
|
1409 |
+
}
|
1410 |
+
|
1411 |
+
.split-page-title-action .expander {
|
1412 |
+
outline: none;
|
1413 |
+
}
|
1414 |
+
|
1415 |
+
</style>
|
1416 |
+
<script type="text/javascript">
|
1417 |
+
document.addEventListener( 'DOMContentLoaded', function() {
|
1418 |
+
var buttons = document.getElementsByClassName( 'page-title-action' ),
|
1419 |
+
button = buttons.item( 0 );
|
1420 |
+
|
1421 |
+
if ( ! button ) {
|
1422 |
+
return;
|
1423 |
+
}
|
1424 |
+
|
1425 |
+
var url = button.href;
|
1426 |
+
var urlHasParams = ( -1 !== url.indexOf( '?' ) );
|
1427 |
+
var panelsUrl = url + ( urlHasParams ? '&' : '?' ) + 'siteorigin-page-builder';
|
1428 |
+
var blockEditorUrl = url + ( urlHasParams ? '&' : '?' ) + 'block-editor';
|
1429 |
+
|
1430 |
+
var newbutton = '<span id="split-page-title-action" class="split-page-title-action">';
|
1431 |
+
newbutton += '<a href="' + url + '">' + button.innerText + '</a>';
|
1432 |
+
newbutton += '<span class="expander" tabindex="0" role="button" aria-haspopup="true" aria-label="<?php echo esc_attr( __( 'Toggle editor selection menu', 'siteorigin-panels' ) ); ?>"></span>';
|
1433 |
+
newbutton += '<span class="dropdown"><a href="' + panelsUrl + '"><?php echo esc_html( __( 'SiteOrigin Page Builder', 'siteorigin-panels' ) ); ?></a>';
|
1434 |
+
newbutton += '<a href="' + blockEditorUrl + '"><?php echo esc_html( __( 'Block Editor', 'siteorigin-panels' ) ); ?></a></span></span><span class="page-title-action" style="display:none;"></span>';
|
1435 |
+
|
1436 |
+
button.insertAdjacentHTML( 'afterend', newbutton );
|
1437 |
+
button.parentNode.removeChild( button );
|
1438 |
+
|
1439 |
+
var expander = document.getElementById( 'split-page-title-action' ).getElementsByClassName( 'expander' ).item( 0 );
|
1440 |
+
var dropdown = expander.parentNode.querySelector( '.dropdown' );
|
1441 |
+
function toggleDropdown() {
|
1442 |
+
dropdown.classList.toggle( 'visible' );
|
1443 |
+
}
|
1444 |
+
expander.addEventListener( 'click', function( e ) {
|
1445 |
+
e.preventDefault();
|
1446 |
+
toggleDropdown();
|
1447 |
+
} );
|
1448 |
+
expander.addEventListener( 'keydown', function( e ) {
|
1449 |
+
if ( 13 === e.which || 32 === e.which ) {
|
1450 |
+
e.preventDefault();
|
1451 |
+
toggleDropdown();
|
1452 |
+
}
|
1453 |
+
} );
|
1454 |
+
} );
|
1455 |
+
</script>
|
1456 |
+
<?php
|
1457 |
+
}
|
1458 |
+
|
1459 |
+
private function show_add_new_dropdown_for_type( $post_type ) {
|
1460 |
+
|
1461 |
+
$show = in_array( $post_type, siteorigin_panels_setting( 'post-types' ) );
|
1462 |
+
|
1463 |
+
// WooCommerce product type doesn't support block editor...
|
1464 |
+
$show = $show && ! ( class_exists( 'WooCommerce' ) && $post_type == 'product' );
|
1465 |
+
|
1466 |
+
if ( class_exists( 'SiteOrigin_Premium_Plugin_Cpt_Builder' ) ) {
|
1467 |
+
$show = $show && $post_type != SiteOrigin_Premium_Plugin_Cpt_Builder::POST_TYPE;
|
1468 |
+
$cpt_builder = SiteOrigin_Premium_Plugin_Cpt_Builder::single();
|
1469 |
+
$so_custom_types = $cpt_builder->get_post_types();
|
1470 |
+
$show = $show && ! isset( $so_custom_types[ $post_type ] );
|
1471 |
+
}
|
1472 |
+
|
1473 |
+
return apply_filters( 'so_panels_show_add_new_dropdown_for_type', $show, $post_type );
|
1474 |
+
}
|
1475 |
+
|
1476 |
+
public function add_panels_post_state( $post_states, $post ) {
|
1477 |
+
$panels_data = get_post_meta( $post->ID, 'panels_data', true );
|
1478 |
+
|
1479 |
+
if ( ! empty( $panels_data ) ) {
|
1480 |
+
$post_states[] = __( 'SiteOrigin Page Builder', 'siteorigin-panels' );
|
1481 |
+
}
|
1482 |
+
|
1483 |
+
return $post_states;
|
1484 |
+
}
|
1485 |
+
}
|
inc/cache-renderer.php
CHANGED
@@ -1,37 +1,37 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class SiteOrigin_Panels_Cache_Renderer {
|
4 |
-
|
5 |
-
function __construct() {
|
6 |
-
// Clear cache when the Page Builder version changes
|
7 |
-
add_action( 'siteorigin_panels_version_changed', array( $this, 'clear_cache' ), 10, 0 );
|
8 |
-
|
9 |
-
// When we activate/deactivate a plugin or switch themes that might change rendering
|
10 |
-
add_action( 'activated_plugin', array( $this, 'clear_cache' ), 10, 0 );
|
11 |
-
add_action( 'deactivated_plugin', array( $this, 'clear_cache' ), 10, 0 );
|
12 |
-
add_action( 'switch_theme', array( $this, 'clear_cache' ), 10, 0 );
|
13 |
-
|
14 |
-
// When settings are saved, this is also a good way to force a cache refresh
|
15 |
-
add_action( 'siteorigin_panels_save_settings', array( $this, 'clear_cache' ), 10, 0 );
|
16 |
-
|
17 |
-
// When a single post is saved
|
18 |
-
add_action( 'save_post', array( $this, 'clear_cache' ), 10, 2 );
|
19 |
-
}
|
20 |
-
|
21 |
-
/**
|
22 |
-
* @return SiteOrigin_Panels_Cache_Renderer
|
23 |
-
*/
|
24 |
-
static function single() {
|
25 |
-
static $single;
|
26 |
-
return empty( $single ) ? $single = new self() : $single;
|
27 |
-
}
|
28 |
-
|
29 |
-
/**
|
30 |
-
* Clear post meta cache.
|
31 |
-
*
|
32 |
-
* Keep this around for a bit in attempt to delete any existing caches.
|
33 |
-
*/
|
34 |
-
public function clear_cache(){
|
35 |
-
delete_post_meta_by_key( 'siteorigin_panels_cache' );
|
36 |
-
}
|
37 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class SiteOrigin_Panels_Cache_Renderer {
|
4 |
+
|
5 |
+
function __construct() {
|
6 |
+
// Clear cache when the Page Builder version changes
|
7 |
+
add_action( 'siteorigin_panels_version_changed', array( $this, 'clear_cache' ), 10, 0 );
|
8 |
+
|
9 |
+
// When we activate/deactivate a plugin or switch themes that might change rendering
|
10 |
+
add_action( 'activated_plugin', array( $this, 'clear_cache' ), 10, 0 );
|
11 |
+
add_action( 'deactivated_plugin', array( $this, 'clear_cache' ), 10, 0 );
|
12 |
+
add_action( 'switch_theme', array( $this, 'clear_cache' ), 10, 0 );
|
13 |
+
|
14 |
+
// When settings are saved, this is also a good way to force a cache refresh
|
15 |
+
add_action( 'siteorigin_panels_save_settings', array( $this, 'clear_cache' ), 10, 0 );
|
16 |
+
|
17 |
+
// When a single post is saved
|
18 |
+
add_action( 'save_post', array( $this, 'clear_cache' ), 10, 2 );
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @return SiteOrigin_Panels_Cache_Renderer
|
23 |
+
*/
|
24 |
+
static function single() {
|
25 |
+
static $single;
|
26 |
+
return empty( $single ) ? $single = new self() : $single;
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Clear post meta cache.
|
31 |
+
*
|
32 |
+
* Keep this around for a bit in attempt to delete any existing caches.
|
33 |
+
*/
|
34 |
+
public function clear_cache(){
|
35 |
+
delete_post_meta_by_key( 'siteorigin_panels_cache' );
|
36 |
+
}
|
37 |
+
}
|
inc/css-builder.php
CHANGED
@@ -1,256 +1,256 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
/**
|
5 |
-
* Class SiteOrigin_Panels_Css_Builder
|
6 |
-
*
|
7 |
-
* Use for building CSS for a page.
|
8 |
-
*/
|
9 |
-
class SiteOrigin_Panels_Css_Builder {
|
10 |
-
|
11 |
-
private $css;
|
12 |
-
|
13 |
-
function __construct() {
|
14 |
-
$this->css = array();
|
15 |
-
}
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Add some general CSS.
|
19 |
-
*
|
20 |
-
* @param string $selector
|
21 |
-
* @param array $attributes
|
22 |
-
* @param int $resolution The pixel resolution that this applies to
|
23 |
-
*/
|
24 |
-
public function add_css( $selector, $attributes, $resolution = 1920 ) {
|
25 |
-
$attribute_string = array();
|
26 |
-
foreach ( $attributes as $k => $v ) {
|
27 |
-
|
28 |
-
if( is_array( $v ) ) {
|
29 |
-
for( $i = 0; $i < count( $v ); $i++ ) {
|
30 |
-
if ( ! strlen( (string) $v[ $i ] ) ) continue;
|
31 |
-
$attribute_string[] = esc_html( $k ) . ':' . esc_html( $v[ $i ] );
|
32 |
-
}
|
33 |
-
}
|
34 |
-
else {
|
35 |
-
if ( ! strlen( (string) $v ) ) continue;
|
36 |
-
$attribute_string[] = esc_html( $k ) . ':' . esc_html( $v );
|
37 |
-
}
|
38 |
-
}
|
39 |
-
$attribute_string = implode( ';', $attribute_string );
|
40 |
-
|
41 |
-
// Add everything we need to the CSS selector
|
42 |
-
if ( empty( $this->css[ $resolution ] ) ) {
|
43 |
-
$this->css[ $resolution ] = array();
|
44 |
-
}
|
45 |
-
if ( empty( $this->css[ $resolution ][ $attribute_string ] ) ) {
|
46 |
-
$this->css[ $resolution ][ $attribute_string ] = array();
|
47 |
-
}
|
48 |
-
$this->css[ $resolution ][ $attribute_string ][] = $selector;
|
49 |
-
}
|
50 |
-
|
51 |
-
/**
|
52 |
-
* Add CSS that applies to a row or group of rows.
|
53 |
-
*
|
54 |
-
* @param int $li The layout ID. If false, then the CSS applies to all layouts.
|
55 |
-
* @param int|bool|string $ri The row index. If false, then the CSS applies to all rows.
|
56 |
-
* @param string $sub_selector A sub selector if we need one.
|
57 |
-
* @param array $attributes An array of attributes.
|
58 |
-
* @param int $resolution The pixel resolution that this applies to
|
59 |
-
* @param bool $specify_layout Sometimes for CSS specificity, we need to include the layout ID.
|
60 |
-
*/
|
61 |
-
public function add_row_css( $li, $ri = false, $sub_selector = '', $attributes = array(), $resolution = 1920, $specify_layout = false ) {
|
62 |
-
$selector = array();
|
63 |
-
|
64 |
-
// Special case of `> .panel-row-style` sub_selector
|
65 |
-
if ( $ri === false ) {
|
66 |
-
// This applies to all rows
|
67 |
-
$selector[] = '#pl-' . $li;
|
68 |
-
$selector[] = '.panel-grid';
|
69 |
-
} else {
|
70 |
-
// This applies to a specific row
|
71 |
-
if ( $specify_layout ) {
|
72 |
-
$selector[] = '#pl-' . $li;
|
73 |
-
}
|
74 |
-
if ( is_string( $ri ) ) {
|
75 |
-
$selector[] = '#' . $ri;
|
76 |
-
} else {
|
77 |
-
$selector[] = '#pg-' . $li . '-' . $ri;
|
78 |
-
}
|
79 |
-
}
|
80 |
-
|
81 |
-
$selector = implode( ' ', $selector );
|
82 |
-
$selector = $this->add_sub_selector( $selector, $sub_selector );
|
83 |
-
|
84 |
-
// Add this to the CSS array
|
85 |
-
$this->add_css( $selector, $attributes, $resolution );
|
86 |
-
}
|
87 |
-
|
88 |
-
/**
|
89 |
-
* Add cell specific CSS
|
90 |
-
*
|
91 |
-
* @param int $li The layout ID. If false, then the CSS applies to all layouts.
|
92 |
-
* @param int|bool $ri The row index. If false, then the CSS applies to all rows.
|
93 |
-
* @param int|bool $ci The cell index. If false, then the CSS applies to all rows.
|
94 |
-
* @param string $sub_selector A sub selector if we need one.
|
95 |
-
* @param array $attributes An array of attributes.
|
96 |
-
* @param int $resolution The pixel resolution that this applies to
|
97 |
-
* @param bool $specify_layout Sometimes for CSS specificity, we need to include the layout ID.
|
98 |
-
*/
|
99 |
-
public function add_cell_css( $li, $ri = false, $ci = false, $sub_selector = '', $attributes = array(), $resolution = 1920, $specify_layout = false ) {
|
100 |
-
$selector_parts = array();
|
101 |
-
|
102 |
-
if ( $ri === false && $ci === false ) {
|
103 |
-
// This applies to all cells in the layout
|
104 |
-
$selector_parts[] = '#pl-' . $li;
|
105 |
-
$selector_parts[] = '.panel-grid-cell';
|
106 |
-
} elseif ( $ri !== false && $ci === false ) {
|
107 |
-
// This applies to all cells in a row
|
108 |
-
$sel = '';
|
109 |
-
|
110 |
-
if ( $specify_layout ) {
|
111 |
-
$sel = '#pl-' . $li . ' ';
|
112 |
-
}
|
113 |
-
$sel .= is_string( $ri ) ? ( '#' . $ri ) : '#pg-' . $li . '-' . $ri;
|
114 |
-
|
115 |
-
// If row styles are set, there's a row style wrapper between the row and the cell, so we need to include
|
116 |
-
// the selector for both. This is a somewhat hacky fix, but trying to prevent further breakage in existing
|
117 |
-
// layouts.
|
118 |
-
$sel_with_style = ', ' . $sel . ' > .panel-row-style';
|
119 |
-
|
120 |
-
$sel .= ' > .panel-grid-cell';
|
121 |
-
$sel_with_style .= ' > .panel-grid-cell';
|
122 |
-
|
123 |
-
$selector_parts[] = $sel;
|
124 |
-
$selector_parts[] = $sel_with_style;
|
125 |
-
} elseif ( $ri !== false && $ci !== false ) {
|
126 |
-
// This applies to a specific cell
|
127 |
-
if ( $specify_layout ) {
|
128 |
-
$selector_parts[] = '#pl-' . $li;
|
129 |
-
}
|
130 |
-
$selector_parts[] = '#pgc-' . $li . '-' . $ri . '-' . $ci;
|
131 |
-
}
|
132 |
-
|
133 |
-
$selector = implode( ' ', $selector_parts );
|
134 |
-
if ( ! empty( $sub_selector ) ) {
|
135 |
-
$selector = $this->add_sub_selector( $selector, $sub_selector );
|
136 |
-
}
|
137 |
-
|
138 |
-
// Add this to the CSS array
|
139 |
-
$this->add_css( $selector, $attributes, $resolution );
|
140 |
-
}
|
141 |
-
|
142 |
-
/**
|
143 |
-
* Add widget specific CSS
|
144 |
-
*
|
145 |
-
* @param int $li The layout ID. If false, then the CSS applies to all layouts.
|
146 |
-
* @param int|bool $ri The row index. If false, then the CSS applies to all rows.
|
147 |
-
* @param int|bool $ci The cell index. If false, then the CSS applies to all rows.
|
148 |
-
* @param int|bool $wi The widget index. If false, then CSS applies to all widgets.
|
149 |
-
* @param string $sub_selector A sub selector if we need one.
|
150 |
-
* @param array $attributes An array of attributes.
|
151 |
-
* @param int $resolution The pixel resolution that this applies to
|
152 |
-
* @param bool $specify_layout Sometimes for CSS specificity, we need to include the layout ID.
|
153 |
-
*/
|
154 |
-
public function add_widget_css( $li, $ri = false, $ci = false, $wi = false, $sub_selector, $attributes = array(), $resolution = 1920, $specify_layout = false ) {
|
155 |
-
$selector = array();
|
156 |
-
|
157 |
-
if ( $ri === false && $ci === false && $wi === false ) {
|
158 |
-
// This applies to all widgets in the layout
|
159 |
-
$selector[] = '#pl-' . $li;
|
160 |
-
$selector[] = '.so-panel';
|
161 |
-
} else if ( $ri !== false && $ci === false && $wi === false ) {
|
162 |
-
// This applies to all widgets in a row
|
163 |
-
if ( $specify_layout ) {
|
164 |
-
$selector[] = '#pl-' . $li;
|
165 |
-
}
|
166 |
-
$selector[] = is_string( $ri ) ? ( '#' . $ri ) : '#pg-' . $li . '-' . $ri;
|
167 |
-
$selector[] = '.so-panel';
|
168 |
-
} else if ( $ri !== false && $ci !== false && $wi === false ) {
|
169 |
-
if ( $specify_layout ) {
|
170 |
-
$selector[] = '#pl-' . $li;
|
171 |
-
}
|
172 |
-
$selector[] = '#pgc-' . $li . '-' . $ri . '-' . $ci;
|
173 |
-
$selector[] = '.so-panel';
|
174 |
-
} else {
|
175 |
-
// This applies to a specific widget
|
176 |
-
if ( $specify_layout ) {
|
177 |
-
$selector[] = '#pl-' . $li;
|
178 |
-
}
|
179 |
-
$selector[] = '#panel-' . $li . '-' . $ri . '-' . $ci . '-' . $wi;
|
180 |
-
}
|
181 |
-
|
182 |
-
$selector = implode( ' ', $selector );
|
183 |
-
$selector = $this->add_sub_selector( $selector, $sub_selector );
|
184 |
-
|
185 |
-
// Add this to the CSS array
|
186 |
-
$this->add_css( $selector, $attributes, $resolution );
|
187 |
-
}
|
188 |
-
|
189 |
-
/**
|
190 |
-
* Add a sub selector to the main selector
|
191 |
-
*
|
192 |
-
* @param string $selector
|
193 |
-
* @param string|array $sub_selector
|
194 |
-
*
|
195 |
-
* @return string
|
196 |
-
*/
|
197 |
-
private function add_sub_selector( $selector, $sub_selector ){
|
198 |
-
$return = array();
|
199 |
-
|
200 |
-
if( ! empty( $sub_selector ) ) {
|
201 |
-
if( ! is_array( $sub_selector ) ) $sub_selector = array( $sub_selector );
|
202 |
-
|
203 |
-
foreach( $sub_selector as $sub ) {
|
204 |
-
$return[] = $selector . $sub;
|
205 |
-
}
|
206 |
-
}
|
207 |
-
else {
|
208 |
-
$return = array( $selector );
|
209 |
-
}
|
210 |
-
|
211 |
-
return implode( ', ', $return );
|
212 |
-
}
|
213 |
-
|
214 |
-
/**
|
215 |
-
* Gets the CSS for this particular layout.
|
216 |
-
*/
|
217 |
-
public function get_css() {
|
218 |
-
// Build actual CSS from the array
|
219 |
-
$css_text = '';
|
220 |
-
krsort( $this->css );
|
221 |
-
foreach ( $this->css as $res => $def ) {
|
222 |
-
if( strpos( $res, ':' ) !== false ) {
|
223 |
-
list( $max_res, $min_res ) = explode( ':', $res, 2 );
|
224 |
-
}
|
225 |
-
else {
|
226 |
-
$min_res = false;
|
227 |
-
$max_res = $res;
|
228 |
-
}
|
229 |
-
|
230 |
-
if ( empty( $def ) ) {
|
231 |
-
continue;
|
232 |
-
}
|
233 |
-
|
234 |
-
if ( $max_res === '' && $min_res > 0 ) {
|
235 |
-
$css_text .= '@media (min-width:' . intval( $min_res ) . 'px) {';
|
236 |
-
} elseif ( $max_res < 1920 ) {
|
237 |
-
$css_text .= '@media (max-width:' . intval( $max_res ) . 'px)';
|
238 |
-
if ( ! empty( $min_res ) ) {
|
239 |
-
$css_text .= ' and (min-width:' . intval( $min_res ) . 'px) ';
|
240 |
-
}
|
241 |
-
$css_text .= '{ ';
|
242 |
-
}
|
243 |
-
|
244 |
-
foreach ( $def as $property => $selector ) {
|
245 |
-
$selector = array_unique( $selector );
|
246 |
-
$css_text .= implode( ' , ', $selector ) . ' { ' . $property . ' } ';
|
247 |
-
}
|
248 |
-
|
249 |
-
if ( ( $max_res === '' && $min_res > 0 ) || $max_res < 1920 ) {
|
250 |
-
$css_text .= ' } ';
|
251 |
-
}
|
252 |
-
}
|
253 |
-
|
254 |
-
return $css_text;
|
255 |
-
}
|
256 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Class SiteOrigin_Panels_Css_Builder
|
6 |
+
*
|
7 |
+
* Use for building CSS for a page.
|
8 |
+
*/
|
9 |
+
class SiteOrigin_Panels_Css_Builder {
|
10 |
+
|
11 |
+
private $css;
|
12 |
+
|
13 |
+
function __construct() {
|
14 |
+
$this->css = array();
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Add some general CSS.
|
19 |
+
*
|
20 |
+
* @param string $selector
|
21 |
+
* @param array $attributes
|
22 |
+
* @param int $resolution The pixel resolution that this applies to
|
23 |
+
*/
|
24 |
+
public function add_css( $selector, $attributes, $resolution = 1920 ) {
|
25 |
+
$attribute_string = array();
|
26 |
+
foreach ( $attributes as $k => $v ) {
|
27 |
+
|
28 |
+
if( is_array( $v ) ) {
|
29 |
+
for( $i = 0; $i < count( $v ); $i++ ) {
|
30 |
+
if ( ! strlen( (string) $v[ $i ] ) ) continue;
|
31 |
+
$attribute_string[] = esc_html( $k ) . ':' . esc_html( $v[ $i ] );
|
32 |
+
}
|
33 |
+
}
|
34 |
+
else {
|
35 |
+
if ( ! strlen( (string) $v ) ) continue;
|
36 |
+
$attribute_string[] = esc_html( $k ) . ':' . esc_html( $v );
|
37 |
+
}
|
38 |
+
}
|
39 |
+
$attribute_string = implode( ';', $attribute_string );
|
40 |
+
|
41 |
+
// Add everything we need to the CSS selector
|
42 |
+
if ( empty( $this->css[ $resolution ] ) ) {
|
43 |
+
$this->css[ $resolution ] = array();
|
44 |
+
}
|
45 |
+
if ( empty( $this->css[ $resolution ][ $attribute_string ] ) ) {
|
46 |
+
$this->css[ $resolution ][ $attribute_string ] = array();
|
47 |
+
}
|
48 |
+
$this->css[ $resolution ][ $attribute_string ][] = $selector;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Add CSS that applies to a row or group of rows.
|
53 |
+
*
|
54 |
+
* @param int $li The layout ID. If false, then the CSS applies to all layouts.
|
55 |
+
* @param int|bool|string $ri The row index. If false, then the CSS applies to all rows.
|
56 |
+
* @param string $sub_selector A sub selector if we need one.
|
57 |
+
* @param array $attributes An array of attributes.
|
58 |
+
* @param int $resolution The pixel resolution that this applies to
|
59 |
+
* @param bool $specify_layout Sometimes for CSS specificity, we need to include the layout ID.
|
60 |
+
*/
|
61 |
+
public function add_row_css( $li, $ri = false, $sub_selector = '', $attributes = array(), $resolution = 1920, $specify_layout = false ) {
|
62 |
+
$selector = array();
|
63 |
+
|
64 |
+
// Special case of `> .panel-row-style` sub_selector
|
65 |
+
if ( $ri === false ) {
|
66 |
+
// This applies to all rows
|
67 |
+
$selector[] = '#pl-' . $li;
|
68 |
+
$selector[] = '.panel-grid';
|
69 |
+
} else {
|
70 |
+
// This applies to a specific row
|
71 |
+
if ( $specify_layout ) {
|
72 |
+
$selector[] = '#pl-' . $li;
|
73 |
+
}
|
74 |
+
if ( is_string( $ri ) ) {
|
75 |
+
$selector[] = '#' . $ri;
|
76 |
+
} else {
|
77 |
+
$selector[] = '#pg-' . $li . '-' . $ri;
|
78 |
+
}
|
79 |
+
}
|
80 |
+
|
81 |
+
$selector = implode( ' ', $selector );
|
82 |
+
$selector = $this->add_sub_selector( $selector, $sub_selector );
|
83 |
+
|
84 |
+
// Add this to the CSS array
|
85 |
+
$this->add_css( $selector, $attributes, $resolution );
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Add cell specific CSS
|
90 |
+
*
|
91 |
+
* @param int $li The layout ID. If false, then the CSS applies to all layouts.
|
92 |
+
* @param int|bool $ri The row index. If false, then the CSS applies to all rows.
|
93 |
+
* @param int|bool $ci The cell index. If false, then the CSS applies to all rows.
|
94 |
+
* @param string $sub_selector A sub selector if we need one.
|
95 |
+
* @param array $attributes An array of attributes.
|
96 |
+
* @param int $resolution The pixel resolution that this applies to
|
97 |
+
* @param bool $specify_layout Sometimes for CSS specificity, we need to include the layout ID.
|
98 |
+
*/
|
99 |
+
public function add_cell_css( $li, $ri = false, $ci = false, $sub_selector = '', $attributes = array(), $resolution = 1920, $specify_layout = false ) {
|
100 |
+
$selector_parts = array();
|
101 |
+
|
102 |
+
if ( $ri === false && $ci === false ) {
|
103 |
+
// This applies to all cells in the layout
|
104 |
+
$selector_parts[] = '#pl-' . $li;
|
105 |
+
$selector_parts[] = '.panel-grid-cell';
|
106 |
+
} elseif ( $ri !== false && $ci === false ) {
|
107 |
+
// This applies to all cells in a row
|
108 |
+
$sel = '';
|
109 |
+
|
110 |
+
if ( $specify_layout ) {
|
111 |
+
$sel = '#pl-' . $li . ' ';
|
112 |
+
}
|
113 |
+
$sel .= is_string( $ri ) ? ( '#' . $ri ) : '#pg-' . $li . '-' . $ri;
|
114 |
+
|
115 |
+
// If row styles are set, there's a row style wrapper between the row and the cell, so we need to include
|
116 |
+
// the selector for both. This is a somewhat hacky fix, but trying to prevent further breakage in existing
|
117 |
+
// layouts.
|
118 |
+
$sel_with_style = ', ' . $sel . ' > .panel-row-style';
|
119 |
+
|
120 |
+
$sel .= ' > .panel-grid-cell';
|
121 |
+
$sel_with_style .= ' > .panel-grid-cell';
|
122 |
+
|
123 |
+
$selector_parts[] = $sel;
|
124 |
+
$selector_parts[] = $sel_with_style;
|
125 |
+
} elseif ( $ri !== false && $ci !== false ) {
|
126 |
+
// This applies to a specific cell
|
127 |
+
if ( $specify_layout ) {
|
128 |
+
$selector_parts[] = '#pl-' . $li;
|
129 |
+
}
|
130 |
+
$selector_parts[] = '#pgc-' . $li . '-' . $ri . '-' . $ci;
|
131 |
+
}
|
132 |
+
|
133 |
+
$selector = implode( ' ', $selector_parts );
|
134 |
+
if ( ! empty( $sub_selector ) ) {
|
135 |
+
$selector = $this->add_sub_selector( $selector, $sub_selector );
|
136 |
+
}
|
137 |
+
|
138 |
+
// Add this to the CSS array
|
139 |
+
$this->add_css( $selector, $attributes, $resolution );
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Add widget specific CSS
|
144 |
+
*
|
145 |
+
* @param int $li The layout ID. If false, then the CSS applies to all layouts.
|
146 |
+
* @param int|bool $ri The row index. If false, then the CSS applies to all rows.
|
147 |
+
* @param int|bool $ci The cell index. If false, then the CSS applies to all rows.
|
148 |
+
* @param int|bool $wi The widget index. If false, then CSS applies to all widgets.
|
149 |
+
* @param string $sub_selector A sub selector if we need one.
|
150 |
+
* @param array $attributes An array of attributes.
|
151 |
+
* @param int $resolution The pixel resolution that this applies to
|
152 |
+
* @param bool $specify_layout Sometimes for CSS specificity, we need to include the layout ID.
|
153 |
+
*/
|
154 |
+
public function add_widget_css( $li, $ri = false, $ci = false, $wi = false, $sub_selector, $attributes = array(), $resolution = 1920, $specify_layout = false ) {
|
155 |
+
$selector = array();
|
156 |
+
|
157 |
+
if ( $ri === false && $ci === false && $wi === false ) {
|
158 |
+
// This applies to all widgets in the layout
|
159 |
+
$selector[] = '#pl-' . $li;
|
160 |
+
$selector[] = '.so-panel';
|
161 |
+
} else if ( $ri !== false && $ci === false && $wi === false ) {
|
162 |
+
// This applies to all widgets in a row
|
163 |
+
if ( $specify_layout ) {
|
164 |
+
$selector[] = '#pl-' . $li;
|
165 |
+
}
|
166 |
+
$selector[] = is_string( $ri ) ? ( '#' . $ri ) : '#pg-' . $li . '-' . $ri;
|
167 |
+
$selector[] = '.so-panel';
|
168 |
+
} else if ( $ri !== false && $ci !== false && $wi === false ) {
|
169 |
+
if ( $specify_layout ) {
|
170 |
+
$selector[] = '#pl-' . $li;
|
171 |
+
}
|
172 |
+
$selector[] = '#pgc-' . $li . '-' . $ri . '-' . $ci;
|
173 |
+
$selector[] = '.so-panel';
|
174 |
+
} else {
|
175 |
+
// This applies to a specific widget
|
176 |
+
if ( $specify_layout ) {
|
177 |
+
$selector[] = '#pl-' . $li;
|
178 |
+
}
|
179 |
+
$selector[] = '#panel-' . $li . '-' . $ri . '-' . $ci . '-' . $wi;
|
180 |
+
}
|
181 |
+
|
182 |
+
$selector = implode( ' ', $selector );
|
183 |
+
$selector = $this->add_sub_selector( $selector, $sub_selector );
|
184 |
+
|
185 |
+
// Add this to the CSS array
|
186 |
+
$this->add_css( $selector, $attributes, $resolution );
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* Add a sub selector to the main selector
|
191 |
+
*
|
192 |
+
* @param string $selector
|
193 |
+
* @param string|array $sub_selector
|
194 |
+
*
|
195 |
+
* @return string
|
196 |
+
*/
|
197 |
+
private function add_sub_selector( $selector, $sub_selector ){
|
198 |
+
$return = array();
|
199 |
+
|
200 |
+
if( ! empty( $sub_selector ) ) {
|
201 |
+
if( ! is_array( $sub_selector ) ) $sub_selector = array( $sub_selector );
|
202 |
+
|
203 |
+
foreach( $sub_selector as $sub ) {
|
204 |
+
$return[] = $selector . $sub;
|
205 |
+
}
|
206 |
+
}
|
207 |
+
else {
|
208 |
+
$return = array( $selector );
|
209 |
+
}
|
210 |
+
|
211 |
+
return implode( ', ', $return );
|
212 |
+
}
|
213 |
+
|
214 |
+
/**
|
215 |
+
* Gets the CSS for this particular layout.
|
216 |
+
*/
|
217 |
+
public function get_css() {
|
218 |
+
// Build actual CSS from the array
|
219 |
+
$css_text = '';
|
220 |
+
krsort( $this->css );
|
221 |
+
foreach ( $this->css as $res => $def ) {
|
222 |
+
if( strpos( $res, ':' ) !== false ) {
|
223 |
+
list( $max_res, $min_res ) = explode( ':', $res, 2 );
|
224 |
+
}
|
225 |
+
else {
|
226 |
+
$min_res = false;
|
227 |
+
$max_res = $res;
|
228 |
+
}
|
229 |
+
|
230 |
+
if ( empty( $def ) ) {
|
231 |
+
continue;
|
232 |
+
}
|
233 |
+
|
234 |
+
if ( $max_res === '' && $min_res > 0 ) {
|
235 |
+
$css_text .= '@media (min-width:' . intval( $min_res ) . 'px) {';
|
236 |
+
} elseif ( $max_res < 1920 ) {
|
237 |
+
$css_text .= '@media (max-width:' . intval( $max_res ) . 'px)';
|
238 |
+
if ( ! empty( $min_res ) ) {
|
239 |
+
$css_text .= ' and (min-width:' . intval( $min_res ) . 'px) ';
|
240 |
+
}
|
241 |
+
$css_text .= '{ ';
|
242 |
+
}
|
243 |
+
|
244 |
+
foreach ( $def as $property => $selector ) {
|
245 |
+
$selector = array_unique( $selector );
|
246 |
+
$css_text .= implode( ' , ', $selector ) . ' { ' . $property . ' } ';
|
247 |
+
}
|
248 |
+
|
249 |
+
if ( ( $max_res === '' && $min_res > 0 ) || $max_res < 1920 ) {
|
250 |
+
$css_text .= ' } ';
|
251 |
+
}
|
252 |
+
}
|
253 |
+
|
254 |
+
return $css_text;
|
255 |
+
}
|
256 |
+
}
|
inc/functions.php
CHANGED
@@ -1,106 +1,106 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Contains several legacy and shorthand functions
|
4 |
-
*
|
5 |
-
* @since 3.0
|
6 |
-
*/
|
7 |
-
|
8 |
-
/**
|
9 |
-
* @return mixed|void Are we currently viewing the home page
|
10 |
-
*/
|
11 |
-
function siteorigin_panels_is_home() {
|
12 |
-
return SiteOrigin_Panels::is_home();
|
13 |
-
}
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Check if we're currently viewing a page builder page.
|
17 |
-
*
|
18 |
-
* @param bool $can_edit Also check if the user can edit this page
|
19 |
-
*
|
20 |
-
* @return bool
|
21 |
-
*/
|
22 |
-
function siteorigin_panels_is_panel( $can_edit = false ) {
|
23 |
-
return SiteOrigin_Panels::is_panel( $can_edit );
|
24 |
-
}
|
25 |
-
|
26 |
-
|
27 |
-
function siteorigin_panels_get_home_page_data() {
|
28 |
-
return SiteOrigin_Panels::single()->get_home_page_data();
|
29 |
-
}
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Render Page Builder content
|
33 |
-
*
|
34 |
-
* @param bool $post_id
|
35 |
-
* @param bool $enqueue_css
|
36 |
-
* @param bool $panels_data
|
37 |
-
*
|
38 |
-
* @return string The HTML content.
|
39 |
-
*/
|
40 |
-
function siteorigin_panels_render( $post_id = false, $enqueue_css = true, $panels_data = false ) {
|
41 |
-
return SiteOrigin_Panels::renderer()->render( $post_id, $enqueue_css, $panels_data );
|
42 |
-
}
|
43 |
-
|
44 |
-
/**
|
45 |
-
* Generate the CSS for the page layout.
|
46 |
-
*
|
47 |
-
* @param $post_id
|
48 |
-
* @param $panels_data
|
49 |
-
* @return string
|
50 |
-
*/
|
51 |
-
function siteorigin_panels_generate_css($post_id, $panels_data = false){
|
52 |
-
return SiteOrigin_Panels::renderer()->generate_css( $post_id, $panels_data );
|
53 |
-
}
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Legacy function to process raw widgets.
|
57 |
-
*
|
58 |
-
* @param $widgets
|
59 |
-
* @param $old_widgets
|
60 |
-
* @param $escape_classes
|
61 |
-
*
|
62 |
-
* @return array
|
63 |
-
*/
|
64 |
-
function siteorigin_panels_process_raw_widgets( $widgets, $old_widgets = false, $escape_classes = false ) {
|
65 |
-
return SiteOrigin_Panels_Admin::single()->process_raw_widgets( $widgets, $old_widgets, $escape_classes );
|
66 |
-
}
|
67 |
-
|
68 |
-
function siteorigin_panels_the_widget( $widget_info, $instance, $grid, $cell, $panel, $is_first, $is_last, $post_id = false, $style_wrapper = '' ) {
|
69 |
-
SiteOrigin_Panels::renderer()->the_widget( $widget_info, $instance, $grid, $cell, $panel, $is_first, $is_last, $post_id, $style_wrapper );
|
70 |
-
}
|
71 |
-
|
72 |
-
/**
|
73 |
-
* Get a setting with the given key.
|
74 |
-
*
|
75 |
-
* @param string $key
|
76 |
-
*
|
77 |
-
* @return array|bool|mixed|null
|
78 |
-
*/
|
79 |
-
function siteorigin_panels_setting( $key = '' ) {
|
80 |
-
return SiteOrigin_Panels_Settings::single()->get( $key );
|
81 |
-
}
|
82 |
-
|
83 |
-
function siteorigin_panels_plugin_activation_install_url( $plugin, $plugin_name, $source = false ) {
|
84 |
-
return SiteOrigin_Panels_Admin_Widgets_Bundle::install_url( $plugin, $plugin_name, $source );
|
85 |
-
}
|
86 |
-
|
87 |
-
/**
|
88 |
-
* A null function for compatibility with aTheme themes.
|
89 |
-
*
|
90 |
-
* @return bool
|
91 |
-
*/
|
92 |
-
function siteorigin_panels_activate(){
|
93 |
-
return false;
|
94 |
-
}
|
95 |
-
|
96 |
-
|
97 |
-
/**
|
98 |
-
* Returns the base URL of our widget with `$path` appended.
|
99 |
-
*
|
100 |
-
* @param string $path Extra path to append to the end of the URL.
|
101 |
-
*
|
102 |
-
* @return string Base URL of the widget, with $path appended.
|
103 |
-
*/
|
104 |
-
function siteorigin_panels_url( $path = '' ) {
|
105 |
-
return plugins_url( 'siteorigin-panels/' . $path );
|
106 |
Â
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Contains several legacy and shorthand functions
|
4 |
+
*
|
5 |
+
* @since 3.0
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* @return mixed|void Are we currently viewing the home page
|
10 |
+
*/
|
11 |
+
function siteorigin_panels_is_home() {
|
12 |
+
return SiteOrigin_Panels::is_home();
|
13 |
+
}
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Check if we're currently viewing a page builder page.
|
17 |
+
*
|
18 |
+
* @param bool $can_edit Also check if the user can edit this page
|
19 |
+
*
|
20 |
+
* @return bool
|
21 |
+
*/
|
22 |
+
function siteorigin_panels_is_panel( $can_edit = false ) {
|
23 |
+
return SiteOrigin_Panels::is_panel( $can_edit );
|
24 |
+
}
|
25 |
+
|
26 |
+
|
27 |
+
function siteorigin_panels_get_home_page_data() {
|
28 |
+
return SiteOrigin_Panels::single()->get_home_page_data();
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Render Page Builder content
|
33 |
+
*
|
34 |
+
* @param bool $post_id
|
35 |
+
* @param bool $enqueue_css
|
36 |
+
* @param bool $panels_data
|
37 |
+
*
|
38 |
+
* @return string The HTML content.
|
39 |
+
*/
|
40 |
+
function siteorigin_panels_render( $post_id = false, $enqueue_css = true, $panels_data = false ) {
|
41 |
+
return SiteOrigin_Panels::renderer()->render( $post_id, $enqueue_css, $panels_data );
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Generate the CSS for the page layout.
|
46 |
+
*
|
47 |
+
* @param $post_id
|
48 |
+
* @param $panels_data
|
49 |
+
* @return string
|
50 |
+
*/
|
51 |
+
function siteorigin_panels_generate_css($post_id, $panels_data = false){
|
52 |
+
return SiteOrigin_Panels::renderer()->generate_css( $post_id, $panels_data );
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Legacy function to process raw widgets.
|
57 |
+
*
|
58 |
+
* @param $widgets
|
59 |
+
* @param $old_widgets
|
60 |
+
* @param $escape_classes
|
61 |
+
*
|
62 |
+
* @return array
|
63 |
+
*/
|
64 |
+
function siteorigin_panels_process_raw_widgets( $widgets, $old_widgets = false, $escape_classes = false ) {
|
65 |
+
return SiteOrigin_Panels_Admin::single()->process_raw_widgets( $widgets, $old_widgets, $escape_classes );
|
66 |
+
}
|
67 |
+
|
68 |
+
function siteorigin_panels_the_widget( $widget_info, $instance, $grid, $cell, $panel, $is_first, $is_last, $post_id = false, $style_wrapper = '' ) {
|
69 |
+
SiteOrigin_Panels::renderer()->the_widget( $widget_info, $instance, $grid, $cell, $panel, $is_first, $is_last, $post_id, $style_wrapper );
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Get a setting with the given key.
|
74 |
+
*
|
75 |
+
* @param string $key
|
76 |
+
*
|
77 |
+
* @return array|bool|mixed|null
|
78 |
+
*/
|
79 |
+
function siteorigin_panels_setting( $key = '' ) {
|
80 |
+
return SiteOrigin_Panels_Settings::single()->get( $key );
|
81 |
+
}
|
82 |
+
|
83 |
+
function siteorigin_panels_plugin_activation_install_url( $plugin, $plugin_name, $source = false ) {
|
84 |
+
return SiteOrigin_Panels_Admin_Widgets_Bundle::install_url( $plugin, $plugin_name, $source );
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* A null function for compatibility with aTheme themes.
|
89 |
+
*
|
90 |
+
* @return bool
|
91 |
+
*/
|
92 |
+
function siteorigin_panels_activate(){
|
93 |
+
return false;
|
94 |
+
}
|
95 |
+
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Returns the base URL of our widget with `$path` appended.
|
99 |
+
*
|
100 |
+
* @param string $path Extra path to append to the end of the URL.
|
101 |
+
*
|
102 |
+
* @return string Base URL of the widget, with $path appended.
|
103 |
+
*/
|
104 |
+
function siteorigin_panels_url( $path = '' ) {
|
105 |
+
return plugins_url( 'siteorigin-panels/' . $path );
|
106 |
Â
}
|
inc/live-editor.php
CHANGED
@@ -1,84 +1,84 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* The live editor class. Only loaded when in live editor mode.
|
5 |
-
*
|
6 |
-
* Class SiteOrigin_Panels_Live_Editor
|
7 |
-
*/
|
8 |
-
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
|
16 |
-
add_filter( 'show_admin_bar', '__return_false' );
|
17 |
-
}
|
18 |
-
|
19 |
-
public static function single() {
|
20 |
-
static $single;
|
21 |
-
return empty( $single ) ? $single = new self() : $single;
|
22 |
-
}
|
23 |
-
|
24 |
-
public function xss_headers(){
|
25 |
-
global $post;
|
26 |
-
if(
|
27 |
-
! empty( $_POST['live_editor_panels_data'] ) &&
|
28 |
-
! empty( $post->ID ) &&
|
29 |
-
current_user_can( 'edit_post', $post->ID )
|
30 |
-
) {
|
31 |
-
// Disable XSS protection when in the Live Editor
|
32 |
-
header( 'X-XSS-Protection: 0' );
|
33 |
-
}
|
34 |
-
}
|
35 |
-
|
36 |
-
|
37 |
-
/**
|
38 |
-
* Edit the page builder data when we're viewing the live editor version. This is necessary to ensure updated styles
|
39 |
-
* are rendered in the preview.
|
40 |
-
*
|
41 |
-
* @param $value
|
42 |
-
* @param $post_id
|
43 |
-
* @param $meta_key
|
44 |
-
*
|
45 |
-
* @return array
|
46 |
-
*/
|
47 |
-
function post_metadata( $value, $post_id, $meta_key ) {
|
48 |
-
if (
|
49 |
-
$meta_key == 'panels_data' &&
|
50 |
-
current_user_can( 'edit_post', $post_id ) &&
|
51 |
-
! empty( $_POST['live_editor_panels_data'] ) &&
|
52 |
-
$_POST['live_editor_post_ID'] == $post_id
|
53 |
-
) {
|
54 |
-
$value = array( json_decode( wp_unslash( $_POST['live_editor_panels_data'] ), true ) );
|
55 |
-
}
|
56 |
-
return $value;
|
57 |
-
}
|
58 |
-
|
59 |
-
/**
|
60 |
-
* Load the frontend scripts for the live editor
|
61 |
-
*/
|
62 |
-
function frontend_scripts() {
|
63 |
-
wp_enqueue_script(
|
64 |
-
'live-editor-front',
|
65 |
-
siteorigin_panels_url( 'js/live-editor/live-editor-front' . SITEORIGIN_PANELS_JS_SUFFIX . '.js' ),
|
66 |
-
array( 'jquery' ),
|
67 |
-
SITEORIGIN_PANELS_VERSION
|
68 |
-
);
|
69 |
-
|
70 |
-
wp_enqueue_script(
|
71 |
-
'live-editor-scrollto',
|
72 |
-
siteorigin_panels_url( 'js/live-editor/jquery.scrollTo' . SITEORIGIN_PANELS_JS_SUFFIX . '.js' ),
|
73 |
-
array( 'jquery' ),
|
74 |
-
SITEORIGIN_PANELS_VERSION
|
75 |
-
);
|
76 |
-
|
77 |
-
wp_enqueue_style(
|
78 |
-
'live-editor-front',
|
79 |
-
siteorigin_panels_url( 'css/live-editor-front' . SITEORIGIN_PANELS_CSS_SUFFIX . '.css' ),
|
80 |
-
array(),
|
81 |
-
SITEORIGIN_PANELS_VERSION
|
82 |
-
);
|
83 |
-
}
|
84 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* The live editor class. Only loaded when in live editor mode.
|
5 |
+
*
|
6 |
+
* Class SiteOrigin_Panels_Live_Editor
|
7 |
+
*/
|
8 |
+
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
|
16 |
+
add_filter( 'show_admin_bar', '__return_false' );
|
17 |
+
}
|
18 |
+
|
19 |
+
public static function single() {
|
20 |
+
static $single;
|
21 |
+
return empty( $single ) ? $single = new self() : $single;
|
22 |
+
}
|
23 |
+
|
24 |
+
public function xss_headers(){
|
25 |
+
global $post;
|
26 |
+
if(
|
27 |
+
! empty( $_POST['live_editor_panels_data'] ) &&
|
28 |
+
! empty( $post->ID ) &&
|
29 |
+
current_user_can( 'edit_post', $post->ID )
|
30 |
+
) {
|
31 |
+
// Disable XSS protection when in the Live Editor
|
32 |
+
header( 'X-XSS-Protection: 0' );
|
33 |
+
}
|
34 |
+
}
|
35 |
+
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Edit the page builder data when we're viewing the live editor version. This is necessary to ensure updated styles
|
39 |
+
* are rendered in the preview.
|
40 |
+
*
|
41 |
+
* @param $value
|
42 |
+
* @param $post_id
|
43 |
+
* @param $meta_key
|
44 |
+
*
|
45 |
+
* @return array
|
46 |
+
*/
|
47 |
+
function post_metadata( $value, $post_id, $meta_key ) {
|
48 |
+
if (
|
49 |
+
$meta_key == 'panels_data' &&
|
50 |
+
current_user_can( 'edit_post', $post_id ) &&
|
51 |
+
! empty( $_POST['live_editor_panels_data'] ) &&
|
52 |
+
$_POST['live_editor_post_ID'] == $post_id
|
53 |
+
) {
|
54 |
+
$value = array( json_decode( wp_unslash( $_POST['live_editor_panels_data'] ), true ) );
|
55 |
+
}
|
56 |
+
return $value;
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Load the frontend scripts for the live editor
|
61 |
+
*/
|
62 |
+
function frontend_scripts() {
|
63 |
+
wp_enqueue_script(
|
64 |
+
'live-editor-front',
|
65 |
+
siteorigin_panels_url( 'js/live-editor/live-editor-front' . SITEORIGIN_PANELS_JS_SUFFIX . '.js' ),
|
66 |
+
array( 'jquery' ),
|
67 |
+
SITEORIGIN_PANELS_VERSION
|
68 |
+
);
|
69 |
+
|
70 |
+
wp_enqueue_script(
|
71 |
+
'live-editor-scrollto',
|
72 |
+
siteorigin_panels_url( 'js/live-editor/jquery.scrollTo' . SITEORIGIN_PANELS_JS_SUFFIX . '.js' ),
|
73 |
+
array( 'jquery' ),
|
74 |
+
SITEORIGIN_PANELS_VERSION
|
75 |
+
);
|
76 |
+
|
77 |
+
wp_enqueue_style(
|
78 |
+
'live-editor-front',
|
79 |
+
siteorigin_panels_url( 'css/live-editor-front' . SITEORIGIN_PANELS_CSS_SUFFIX . '.css' ),
|
80 |
+
array(),
|
81 |
+
SITEORIGIN_PANELS_VERSION
|
82 |
+
);
|
83 |
+
}
|
84 |
+
}
|
inc/renderer-legacy.php
CHANGED
@@ -1,168 +1,168 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class SiteOrigin_Panels_Renderer_Legacy extends SiteOrigin_Panels_Renderer {
|
4 |
-
|
5 |
-
public static function single() {
|
6 |
-
static $single;
|
7 |
-
return empty( $single ) ? $single = new self() : $single;
|
8 |
-
}
|
9 |
-
|
10 |
-
/**
|
11 |
-
* Generate the CSS for the page layout.
|
12 |
-
*
|
13 |
-
* @param $post_id
|
14 |
-
* @param $panels_data
|
15 |
-
* @param $layout_data
|
16 |
-
*
|
17 |
-
* @return string
|
18 |
-
*/
|
19 |
-
public function generate_css( $post_id, $panels_data = false, $layout_data = false) {
|
20 |
-
// Exit if we don't have panels data
|
21 |
-
if ( empty( $panels_data ) ) {
|
22 |
-
$panels_data = get_post_meta( $post_id, 'panels_data', true );
|
23 |
-
if( empty( $panels_data ) ) {
|
24 |
-
return '';
|
25 |
-
}
|
26 |
-
}
|
27 |
-
if ( empty( $layout_data ) ) {
|
28 |
-
$layout_data = $this->get_panels_layout_data( $panels_data );
|
29 |
-
$layout_data = apply_filters( 'siteorigin_panels_layout_data', $layout_data, $post_id );
|
30 |
-
}
|
31 |
-
|
32 |
-
// Get some of the default settings
|
33 |
-
$settings = siteorigin_panels_setting();
|
34 |
-
$panels_tablet_width = $settings['tablet-width'];
|
35 |
-
$panels_mobile_width = $settings['mobile-width'];
|
36 |
-
$panels_margin_bottom = $settings['margin-bottom'];
|
37 |
-
$panels_margin_bottom_last_row = $settings['margin-bottom-last-row'];
|
38 |
-
|
39 |
-
$css = new SiteOrigin_Panels_Css_Builder();
|
40 |
-
|
41 |
-
$ci = 0;
|
42 |
-
foreach ( $layout_data as $ri => $row ) {
|
43 |
-
if( empty( $row['cells'] ) ) continue;
|
44 |
-
|
45 |
-
// Let other themes and plugins change the gutter.
|
46 |
-
$gutter = apply_filters( 'siteorigin_panels_css_row_gutter', $settings['margin-sides'] . 'px', $row, $ri, $panels_data );
|
47 |
-
preg_match( '/([0-9\.,]+)(.*)/', $gutter, $gutter_parts );
|
48 |
-
|
49 |
-
$cell_count = count( $row['cells'] );
|
50 |
-
|
51 |
-
// Add the cell sizing
|
52 |
-
foreach( $row['cells'] as $ci => $cell ) {
|
53 |
-
$weight = apply_filters( 'siteorigin_panels_css_cell_weight', $cell['weight'], $row, $ri, $cell, $ci - 1, $panels_data, $post_id );
|
54 |
-
|
55 |
-
// Add the width and ensure we have correct formatting for CSS.
|
56 |
-
$css->add_cell_css( $post_id, $ri, $ci, '', array(
|
57 |
-
'width' => round( $weight * 100, 4 ) . '%',
|
58 |
-
) );
|
59 |
-
}
|
60 |
-
|
61 |
-
if( ! empty( $row['style']['collapse_order'] ) && $row['style']['collapse_order'] == 'right-top') {
|
62 |
-
$css->add_cell_css( $post_id, $ri, false, '', array(
|
63 |
-
'float' => 'right'
|
64 |
-
) );
|
65 |
-
}
|
66 |
-
|
67 |
-
if(
|
68 |
-
$ri != count( $layout_data ) - 1 ||
|
69 |
-
! empty( $row[ 'style' ][ 'bottom_margin' ] ) ||
|
70 |
-
! empty( $panels_margin_bottom_last_row )
|
71 |
-
) {
|
72 |
-
// Filter the bottom margin for this row with the arguments
|
73 |
-
$css->add_row_css( $post_id, $ri, '', array(
|
74 |
-
'margin-bottom' => apply_filters( 'siteorigin_panels_css_row_margin_bottom', $panels_margin_bottom . 'px', $row, $ri, $panels_data, $post_id )
|
75 |
-
) );
|
76 |
-
}
|
77 |
-
|
78 |
-
$margin_half = ( floatval( $gutter_parts[1] ) / 2 ) . $gutter_parts[2];
|
79 |
-
$css->add_row_css($post_id, $ri, '', array(
|
80 |
-
'margin-left' => '-' . $margin_half,
|
81 |
-
'margin-right' => '-' . $margin_half,
|
82 |
-
) );
|
83 |
-
$css->add_cell_css($post_id, $ri, false, '', array(
|
84 |
-
'padding-left' => $margin_half,
|
85 |
-
'padding-right' => $margin_half,
|
86 |
-
) );
|
87 |
-
}
|
88 |
-
|
89 |
-
// Add the bottom margins
|
90 |
-
$css->add_widget_css( $post_id, false, false, false, '', array(
|
91 |
-
'margin-bottom' => apply_filters( 'siteorigin_panels_css_cell_margin_bottom', $panels_margin_bottom . 'px', false, false, $panels_data, $post_id )
|
92 |
-
) );
|
93 |
-
$css->add_widget_css( $post_id, false, false, false, ':last-child', array(
|
94 |
-
'margin-bottom' => apply_filters( 'siteorigin_panels_css_cell_last_margin_bottom', '0px', false, false, $panels_data, $post_id )
|
95 |
-
) );
|
96 |
-
|
97 |
-
if ( $settings['responsive'] ) {
|
98 |
-
|
99 |
-
$css->add_cell_css($post_id, false, false, '', array(
|
100 |
-
'float' => 'none',
|
101 |
-
'width' => 'auto'
|
102 |
-
), $panels_mobile_width);
|
103 |
-
|
104 |
-
$css->add_row_css($post_id, false, '', array(
|
105 |
-
'margin-left' => 0,
|
106 |
-
'margin-right' => 0,
|
107 |
-
), $panels_mobile_width);
|
108 |
-
|
109 |
-
$css->add_cell_css( $post_id, false, false, '', array(
|
110 |
-
'padding' => 0,
|
111 |
-
), $panels_mobile_width );
|
112 |
-
|
113 |
-
// Hide empty cells on mobile
|
114 |
-
$css->add_row_css( $post_id, false, ' .panel-grid-cell-empty', array(
|
115 |
-
'display' => 'none',
|
116 |
-
), $panels_mobile_width );
|
117 |
-
|
118 |
-
// Hide empty cells on mobile
|
119 |
-
$css->add_row_css( $post_id, false, ' .panel-grid-cell-mobile-last', array(
|
120 |
-
'margin-bottom' => '0px',
|
121 |
-
), $panels_mobile_width );
|
122 |
-
|
123 |
-
foreach ( $layout_data as $ri => $row ) {
|
124 |
-
$css->add_cell_css( $post_id, $ri, false, '', array(
|
125 |
-
'margin-bottom' => $panels_margin_bottom . 'px',
|
126 |
-
), $panels_mobile_width );
|
127 |
-
|
128 |
-
$css->add_cell_css( $post_id, $ri, false, ':last-child', array(
|
129 |
-
'margin-bottom' => '0px',
|
130 |
-
), $panels_mobile_width );
|
131 |
-
}
|
132 |
-
}
|
133 |
-
|
134 |
-
foreach ( $panels_data['widgets'] as $widget_id => $widget ) {
|
135 |
-
if ( ! empty( $widget['panels_info']['style']['link_color'] ) ) {
|
136 |
-
$css->add_widget_css( $post_id, $widget['panels_info']['grid'], $widget['panels_info']['cell'], $widget['panels_info']['cell_index'], ' a', array(
|
137 |
-
'color' => $widget['panels_info']['style']['link_color']
|
138 |
-
) );
|
139 |
-
}
|
140 |
-
}
|
141 |
-
|
142 |
-
// Let other plugins and components filter the CSS object.
|
143 |
-
$css = apply_filters( 'siteorigin_panels_css_object', $css, $panels_data, $post_id, $layout_data );
|
144 |
-
|
145 |
-
return $css->get_css();
|
146 |
-
}
|
147 |
-
|
148 |
-
/**
|
149 |
-
* This overwrites the parent function to get the cells in reverse order when using right_on_top collapse mode.
|
150 |
-
*
|
151 |
-
* @param $cells The cells to modify
|
152 |
-
* @param $row The row the cells belong to
|
153 |
-
*
|
154 |
-
* @return mixed
|
155 |
-
*/
|
156 |
-
protected function modify_row_cells( $cells, $row ){
|
157 |
-
if( ! empty( $row['style']['collapse_order'] ) && $row['style']['collapse_order'] == 'right-top') {
|
158 |
-
$cells = array_reverse( $cells, true );
|
159 |
-
}
|
160 |
-
|
161 |
-
return $cells;
|
162 |
-
|
163 |
-
}
|
164 |
-
|
165 |
-
public function front_css_url(){
|
166 |
-
return siteorigin_panels_url( 'css/front' . ( siteorigin_panels_setting( 'legacy-layout' ) ? '-legacy' : '' ) . '.css' );
|
167 |
-
}
|
168 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class SiteOrigin_Panels_Renderer_Legacy extends SiteOrigin_Panels_Renderer {
|
4 |
+
|
5 |
+
public static function single() {
|
6 |
+
static $single;
|
7 |
+
return empty( $single ) ? $single = new self() : $single;
|
8 |
+
}
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Generate the CSS for the page layout.
|
12 |
+
*
|
13 |
+
* @param $post_id
|
14 |
+
* @param $panels_data
|
15 |
+
* @param $layout_data
|
16 |
+
*
|
17 |
+
* @return string
|
18 |
+
*/
|
19 |
+
public function generate_css( $post_id, $panels_data = false, $layout_data = false) {
|
20 |
+
// Exit if we don't have panels data
|
21 |
+
if ( empty( $panels_data ) ) {
|
22 |
+
$panels_data = get_post_meta( $post_id, 'panels_data', true );
|
23 |
+
if( empty( $panels_data ) ) {
|
24 |
+
return '';
|
25 |
+
}
|
26 |
+
}
|
27 |
+
if ( empty( $layout_data ) ) {
|
28 |
+
$layout_data = $this->get_panels_layout_data( $panels_data );
|
29 |
+
$layout_data = apply_filters( 'siteorigin_panels_layout_data', $layout_data, $post_id );
|
30 |
+
}
|
31 |
+
|
32 |
+
// Get some of the default settings
|
33 |
+
$settings = siteorigin_panels_setting();
|
34 |
+
$panels_tablet_width = $settings['tablet-width'];
|
35 |
+
$panels_mobile_width = $settings['mobile-width'];
|
36 |
+
$panels_margin_bottom = $settings['margin-bottom'];
|
37 |
+
$panels_margin_bottom_last_row = $settings['margin-bottom-last-row'];
|
38 |
+
|
39 |
+
$css = new SiteOrigin_Panels_Css_Builder();
|
40 |
+
|
41 |
+
$ci = 0;
|
42 |
+
foreach ( $layout_data as $ri => $row ) {
|
43 |
+
if( empty( $row['cells'] ) ) continue;
|
44 |
+
|
45 |
+
// Let other themes and plugins change the gutter.
|
46 |
+
$gutter = apply_filters( 'siteorigin_panels_css_row_gutter', $settings['margin-sides'] . 'px', $row, $ri, $panels_data );
|
47 |
+
preg_match( '/([0-9\.,]+)(.*)/', $gutter, $gutter_parts );
|
48 |
+
|
49 |
+
$cell_count = count( $row['cells'] );
|
50 |
+
|
51 |
+
// Add the cell sizing
|
52 |
+
foreach( $row['cells'] as $ci => $cell ) {
|
53 |
+
$weight = apply_filters( 'siteorigin_panels_css_cell_weight', $cell['weight'], $row, $ri, $cell, $ci - 1, $panels_data, $post_id );
|
54 |
+
|
55 |
+
// Add the width and ensure we have correct formatting for CSS.
|
56 |
+
$css->add_cell_css( $post_id, $ri, $ci, '', array(
|
57 |
+
'width' => round( $weight * 100, 4 ) . '%',
|
58 |
+
) );
|
59 |
+
}
|
60 |
+
|
61 |
+
if( ! empty( $row['style']['collapse_order'] ) && $row['style']['collapse_order'] == 'right-top') {
|
62 |
+
$css->add_cell_css( $post_id, $ri, false, '', array(
|
63 |
+
'float' => 'right'
|
64 |
+
) );
|
65 |
+
}
|
66 |
+
|
67 |
+
if(
|
68 |
+
$ri != count( $layout_data ) - 1 ||
|
69 |
+
! empty( $row[ 'style' ][ 'bottom_margin' ] ) ||
|
70 |
+
! empty( $panels_margin_bottom_last_row )
|
71 |
+
) {
|
72 |
+
// Filter the bottom margin for this row with the arguments
|
73 |
+
$css->add_row_css( $post_id, $ri, '', array(
|
74 |
+
'margin-bottom' => apply_filters( 'siteorigin_panels_css_row_margin_bottom', $panels_margin_bottom . 'px', $row, $ri, $panels_data, $post_id )
|
75 |
+
) );
|
76 |
+
}
|
77 |
+
|
78 |
+
$margin_half = ( floatval( $gutter_parts[1] ) / 2 ) . $gutter_parts[2];
|
79 |
+
$css->add_row_css($post_id, $ri, '', array(
|
80 |
+
'margin-left' => '-' . $margin_half,
|
81 |
+
'margin-right' => '-' . $margin_half,
|
82 |
+
) );
|
83 |
+
$css->add_cell_css($post_id, $ri, false, '', array(
|
84 |
+
'padding-left' => $margin_half,
|
85 |
+
'padding-right' => $margin_half,
|
86 |
+
) );
|
87 |
+
}
|
88 |
+
|
89 |
+
// Add the bottom margins
|
90 |
+
$css->add_widget_css( $post_id, false, false, false, '', array(
|
91 |
+
'margin-bottom' => apply_filters( 'siteorigin_panels_css_cell_margin_bottom', $panels_margin_bottom . 'px', false, false, $panels_data, $post_id )
|
92 |
+
) );
|
93 |
+
$css->add_widget_css( $post_id, false, false, false, ':last-child', array(
|
94 |
+
'margin-bottom' => apply_filters( 'siteorigin_panels_css_cell_last_margin_bottom', '0px', false, false, $panels_data, $post_id )
|
95 |
+
) );
|
96 |
+
|
97 |
+
if ( $settings['responsive'] ) {
|
98 |
+
|
99 |
+
$css->add_cell_css($post_id, false, false, '', array(
|
100 |
+
'float' => 'none',
|
101 |
+
'width' => 'auto'
|
102 |
+
), $panels_mobile_width);
|
103 |
+
|
104 |
+
$css->add_row_css($post_id, false, '', array(
|
105 |
+
'margin-left' => 0,
|
106 |
+
'margin-right' => 0,
|
107 |
+
), $panels_mobile_width);
|
108 |
+
|
109 |
+
$css->add_cell_css( $post_id, false, false, '', array(
|
110 |
+
'padding' => 0,
|
111 |
+
), $panels_mobile_width );
|
112 |
+
|
113 |
+
// Hide empty cells on mobile
|
114 |
+
$css->add_row_css( $post_id, false, ' .panel-grid-cell-empty', array(
|
115 |
+
'display' => 'none',
|
116 |
+
), $panels_mobile_width );
|
117 |
+
|
118 |
+
// Hide empty cells on mobile
|
119 |
+
$css->add_row_css( $post_id, false, ' .panel-grid-cell-mobile-last', array(
|
120 |
+
'margin-bottom' => '0px',
|
121 |
+
), $panels_mobile_width );
|
122 |
+
|
123 |
+
foreach ( $layout_data as $ri => $row ) {
|
124 |
+
$css->add_cell_css( $post_id, $ri, false, '', array(
|
125 |
+
'margin-bottom' => $panels_margin_bottom . 'px',
|
126 |
+
), $panels_mobile_width );
|
127 |
+
|
128 |
+
$css->add_cell_css( $post_id, $ri, false, ':last-child', array(
|
129 |
+
'margin-bottom' => '0px',
|
130 |
+
), $panels_mobile_width );
|
131 |
+
}
|
132 |
+
}
|
133 |
+
|
134 |
+
foreach ( $panels_data['widgets'] as $widget_id => $widget ) {
|
135 |
+
if ( ! empty( $widget['panels_info']['style']['link_color'] ) ) {
|
136 |
+
$css->add_widget_css( $post_id, $widget['panels_info']['grid'], $widget['panels_info']['cell'], $widget['panels_info']['cell_index'], ' a', array(
|
137 |
+
'color' => $widget['panels_info']['style']['link_color']
|
138 |
+
) );
|
139 |
+
}
|
140 |
+
}
|
141 |
+
|
142 |
+
// Let other plugins and components filter the CSS object.
|
143 |
+
$css = apply_filters( 'siteorigin_panels_css_object', $css, $panels_data, $post_id, $layout_data );
|
144 |
+
|
145 |
+
return $css->get_css();
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* This overwrites the parent function to get the cells in reverse order when using right_on_top collapse mode.
|
150 |
+
*
|
151 |
+
* @param $cells The cells to modify
|
152 |
+
* @param $row The row the cells belong to
|
153 |
+
*
|
154 |
+
* @return mixed
|
155 |
+
*/
|
156 |
+
protected function modify_row_cells( $cells, $row ){
|
157 |
+
if( ! empty( $row['style']['collapse_order'] ) && $row['style']['collapse_order'] == 'right-top') {
|
158 |
+
$cells = array_reverse( $cells, true );
|
159 |
+
}
|
160 |
+
|
161 |
+
return $cells;
|
162 |
+
|
163 |
+
}
|
164 |
+
|
165 |
+
public function front_css_url(){
|
166 |
+
return siteorigin_panels_url( 'css/front' . ( siteorigin_panels_setting( 'legacy-layout' ) ? '-legacy' : '' ) . '.css' );
|
167 |
+
}
|
168 |
+
}
|
inc/renderer.php
CHANGED
@@ -1,864 +1,872 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class SiteOrigin_Panels_Renderer {
|
4 |
-
|
5 |
-
private $inline_css;
|
6 |
-
|
7 |
-
function __construct() {
|
8 |
-
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_styles' ), 1 );
|
9 |
-
$this->inline_css = null;
|
10 |
-
}
|
11 |
-
|
12 |
-
public static function single() {
|
13 |
-
static $single;
|
14 |
-
|
15 |
-
return empty( $single ) ? $single = new self() : $single;
|
16 |
-
}
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Add CSS that needs to go inline.
|
20 |
-
*
|
21 |
-
* @param $post_id
|
22 |
-
* @param $css
|
23 |
-
*/
|
24 |
-
public function add_inline_css( $post_id, $css ) {
|
25 |
-
if ( is_null( $this->inline_css ) ) {
|
26 |
-
// Initialize the inline CSS array and add actions to handle printing.
|
27 |
-
$this->inline_css = array();
|
28 |
-
add_action( 'wp_head', array( $this, 'print_inline_css' ), 12 );
|
29 |
-
add_action( 'wp_footer', array( $this, 'print_inline_css' ) );
|
30 |
-
}
|
31 |
-
|
32 |
-
$this->inline_css[ $post_id ] = $css;
|
33 |
-
|
34 |
-
// Enqueue the front styles, if they haven't already been enqueued
|
35 |
-
if ( ! wp_style_is( 'siteorigin-panels-front', 'enqueued' ) ) {
|
36 |
-
wp_enqueue_style( 'siteorigin-panels-front' );
|
37 |
-
}
|
38 |
-
}
|
39 |
-
|
40 |
-
/**
|
41 |
-
* Generate the CSS for the page layout.
|
42 |
-
*
|
43 |
-
* @param $post_id
|
44 |
-
* @param $panels_data
|
45 |
-
* @param $layout_data
|
46 |
-
*
|
47 |
-
* @return string
|
48 |
-
*/
|
49 |
-
public function generate_css( $post_id, $panels_data = false, $layout_data = false ) {
|
50 |
-
// Exit if we don't have panels data
|
51 |
-
if ( empty( $panels_data ) ) {
|
52 |
-
$panels_data = get_post_meta( $post_id, 'panels_data', true );
|
53 |
-
$panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, $post_id );
|
54 |
-
if ( empty( $panels_data ) ) {
|
55 |
-
return '';
|
56 |
-
}
|
57 |
-
}
|
58 |
-
if ( empty( $layout_data ) ) {
|
59 |
-
$layout_data = $this->get_panels_layout_data( $panels_data );
|
60 |
-
$layout_data = apply_filters( 'siteorigin_panels_layout_data', $layout_data, $post_id );
|
61 |
-
}
|
62 |
-
|
63 |
-
// Get some of the default settings
|
64 |
-
$settings = siteorigin_panels_setting();
|
65 |
-
$panels_tablet_width = $settings['tablet-width'];
|
66 |
-
$panels_mobile_width = $settings['mobile-width'];
|
67 |
-
$
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
$
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
$
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
$
|
112 |
-
$
|
113 |
-
$
|
114 |
-
$
|
115 |
-
$
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
$post_id
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
$
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
'margin-bottom' => 0,
|
183 |
-
), $panels_tablet_width . ':' . ( $panels_mobile_width + 1 )
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
if ( empty( $panels_data )
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
$
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
echo '
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
$
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
$
|
389 |
-
$
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
if (
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
$attributes['
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
$attributes['class'] =
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
*
|
446 |
-
*
|
447 |
-
* @param
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
}
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
'
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
$
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
'
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
$
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
if ( ! empty( $
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
$css_id =
|
573 |
-
break;
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
}
|
594 |
-
|
595 |
-
/**
|
596 |
-
*
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
$
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
$
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
if (
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
'
|
668 |
-
'
|
669 |
-
'
|
670 |
-
);
|
671 |
-
}
|
672 |
-
|
673 |
-
foreach ( $panels_data['
|
674 |
-
$
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
*
|
712 |
-
*
|
713 |
-
*
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
$
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
*
|
767 |
-
*
|
768 |
-
*
|
769 |
-
*
|
770 |
-
*
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
$
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
// Legacy filter, use `
|
796 |
-
$
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
$
|
809 |
-
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
|
816 |
-
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
-
|
821 |
-
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
*
|
837 |
-
*
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
$
|
852 |
-
$wi
|
853 |
-
|
854 |
-
|
855 |
-
|
856 |
-
$
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
864 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class SiteOrigin_Panels_Renderer {
|
4 |
+
|
5 |
+
private $inline_css;
|
6 |
+
|
7 |
+
function __construct() {
|
8 |
+
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_styles' ), 1 );
|
9 |
+
$this->inline_css = null;
|
10 |
+
}
|
11 |
+
|
12 |
+
public static function single() {
|
13 |
+
static $single;
|
14 |
+
|
15 |
+
return empty( $single ) ? $single = new self() : $single;
|
16 |
+
}
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Add CSS that needs to go inline.
|
20 |
+
*
|
21 |
+
* @param $post_id
|
22 |
+
* @param $css
|
23 |
+
*/
|
24 |
+
public function add_inline_css( $post_id, $css ) {
|
25 |
+
if ( is_null( $this->inline_css ) ) {
|
26 |
+
// Initialize the inline CSS array and add actions to handle printing.
|
27 |
+
$this->inline_css = array();
|
28 |
+
add_action( 'wp_head', array( $this, 'print_inline_css' ), 12 );
|
29 |
+
add_action( 'wp_footer', array( $this, 'print_inline_css' ) );
|
30 |
+
}
|
31 |
+
|
32 |
+
$this->inline_css[ $post_id ] = $css;
|
33 |
+
|
34 |
+
// Enqueue the front styles, if they haven't already been enqueued
|
35 |
+
if ( ! wp_style_is( 'siteorigin-panels-front', 'enqueued' ) ) {
|
36 |
+
wp_enqueue_style( 'siteorigin-panels-front' );
|
37 |
+
}
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Generate the CSS for the page layout.
|
42 |
+
*
|
43 |
+
* @param $post_id
|
44 |
+
* @param $panels_data
|
45 |
+
* @param $layout_data
|
46 |
+
*
|
47 |
+
* @return string
|
48 |
+
*/
|
49 |
+
public function generate_css( $post_id, $panels_data = false, $layout_data = false ) {
|
50 |
+
// Exit if we don't have panels data
|
51 |
+
if ( empty( $panels_data ) ) {
|
52 |
+
$panels_data = get_post_meta( $post_id, 'panels_data', true );
|
53 |
+
$panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, $post_id );
|
54 |
+
if ( empty( $panels_data ) ) {
|
55 |
+
return '';
|
56 |
+
}
|
57 |
+
}
|
58 |
+
if ( empty( $layout_data ) ) {
|
59 |
+
$layout_data = $this->get_panels_layout_data( $panels_data );
|
60 |
+
$layout_data = apply_filters( 'siteorigin_panels_layout_data', $layout_data, $post_id );
|
61 |
+
}
|
62 |
+
|
63 |
+
// Get some of the default settings
|
64 |
+
$settings = siteorigin_panels_setting();
|
65 |
+
$panels_tablet_width = $settings['tablet-width'];
|
66 |
+
$panels_mobile_width = $settings['mobile-width'];
|
67 |
+
$panels_margin_bottom_last_row = $settings['margin-bottom-last-row'];
|
68 |
+
|
69 |
+
$css = new SiteOrigin_Panels_Css_Builder();
|
70 |
+
|
71 |
+
$ci = 0;
|
72 |
+
foreach ( $layout_data as $ri => $row ) {
|
73 |
+
|
74 |
+
// Filter the bottom margin for this row with the arguments
|
75 |
+
$panels_margin_bottom = apply_filters( 'siteorigin_panels_css_row_margin_bottom', $settings['margin-bottom'] . 'px', $row, $ri, $panels_data, $post_id );
|
76 |
+
$panels_mobile_margin_bottom = apply_filters( 'siteorigin_panels_css_row_mobile_margin_bottom', $settings['margin-bottom'] . 'px', $row, $ri, $panels_data, $post_id );
|
77 |
+
|
78 |
+
if ( empty( $row['cells'] ) ) {
|
79 |
+
continue;
|
80 |
+
}
|
81 |
+
|
82 |
+
// Let other themes and plugins change the gutter.
|
83 |
+
$gutter = apply_filters( 'siteorigin_panels_css_row_gutter', $settings['margin-sides'] . 'px', $row, $ri, $panels_data );
|
84 |
+
preg_match( '/([0-9\.,]+)(.*)/', $gutter, $gutter_parts );
|
85 |
+
|
86 |
+
$cell_count = count( $row['cells'] );
|
87 |
+
|
88 |
+
// Add the cell sizing
|
89 |
+
foreach ( $row['cells'] as $ci => $cell ) {
|
90 |
+
$weight = apply_filters( 'siteorigin_panels_css_cell_weight', $cell['weight'], $row, $ri, $cell, $ci - 1, $panels_data, $post_id );
|
91 |
+
$rounded_width = round( $weight * 100, 4 ) . '%';
|
92 |
+
$calc_width = 'calc(' . $rounded_width . ' - ( ' . ( 1 - $weight ) . ' * ' . $gutter . ' ) )';
|
93 |
+
|
94 |
+
// Add the width and ensure we have correct formatting for CSS.
|
95 |
+
$css->add_cell_css( $post_id, $ri, $ci, '', array(
|
96 |
+
'width' => array(
|
97 |
+
// For some locales PHP uses ',' for decimal separation.
|
98 |
+
// This seems to happen when a plugin calls `setlocale(LC_ALL, 'de_DE');` or `setlocale(LC_NUMERIC, 'de_DE');`
|
99 |
+
// This should prevent issues with column sizes in these cases.
|
100 |
+
str_replace( ',', '.', $rounded_width ),
|
101 |
+
str_replace( ',', '.', intval($gutter) ? $calc_width : '' ), // Exclude if there's a zero gutter
|
102 |
+
)
|
103 |
+
) );
|
104 |
+
|
105 |
+
// Add in any widget specific CSS
|
106 |
+
foreach ( $cell['widgets'] as $wi => $widget ) {
|
107 |
+
$widget_style_data = ! empty( $widget['panels_info']['style'] ) ? $widget['panels_info']['style'] : array();
|
108 |
+
$widget_css = apply_filters(
|
109 |
+
'siteorigin_panels_css_widget_css',
|
110 |
+
array(),
|
111 |
+
$widget_style_data,
|
112 |
+
$row,
|
113 |
+
$ri,
|
114 |
+
$cell,
|
115 |
+
$ci - 1,
|
116 |
+
$widget,
|
117 |
+
$wi,
|
118 |
+
$panels_data,
|
119 |
+
$post_id
|
120 |
+
);
|
121 |
+
|
122 |
+
$css->add_widget_css(
|
123 |
+
$post_id,
|
124 |
+
$ri,
|
125 |
+
$ci,
|
126 |
+
$wi,
|
127 |
+
'',
|
128 |
+
$widget_css,
|
129 |
+
1920,
|
130 |
+
true
|
131 |
+
);
|
132 |
+
}
|
133 |
+
}
|
134 |
+
|
135 |
+
if (
|
136 |
+
$ri != count( $layout_data ) - 1 ||
|
137 |
+
! empty( $row['style']['bottom_margin'] ) ||
|
138 |
+
! empty( $panels_margin_bottom_last_row )
|
139 |
+
) {
|
140 |
+
$css->add_row_css( $post_id, $ri, '', array(
|
141 |
+
'margin-bottom' => $panels_margin_bottom
|
142 |
+
) );
|
143 |
+
}
|
144 |
+
|
145 |
+
$collapse_order = ! empty( $row['style']['collapse_order'] ) ? $row['style']['collapse_order'] : ( ! is_rtl() ? 'left-top' : 'right-top' );
|
146 |
+
|
147 |
+
if ( $settings['responsive'] && empty( $row['style']['collapse_behaviour'] ) ) {
|
148 |
+
// The default collapse behaviour
|
149 |
+
if (
|
150 |
+
$settings['tablet-layout'] &&
|
151 |
+
$cell_count >= 3 &&
|
152 |
+
$panels_tablet_width > $panels_mobile_width
|
153 |
+
) {
|
154 |
+
// Tablet responsive css for the row
|
155 |
+
|
156 |
+
$css->add_row_css( $post_id, $ri, array(
|
157 |
+
'.panel-no-style',
|
158 |
+
'.panel-has-style > .panel-row-style'
|
159 |
+
), array(
|
160 |
+
'-ms-flex-wrap' => $collapse_order == 'left-top' ? 'wrap' : 'wrap-reverse',
|
161 |
+
'-webkit-flex-wrap' => $collapse_order == 'left-top' ? 'wrap' : 'wrap-reverse',
|
162 |
+
'flex-wrap' => $collapse_order == 'left-top' ? 'wrap' : 'wrap-reverse',
|
163 |
+
), $panels_tablet_width . ':' . ( $panels_mobile_width + 1 ) );
|
164 |
+
|
165 |
+
$css->add_cell_css( $post_id, $ri, false, '', array(
|
166 |
+
'-ms-flex' => '0 1 50%',
|
167 |
+
'-webkit-flex' => '0 1 50%',
|
168 |
+
'flex' => '0 1 50%',
|
169 |
+
'margin-right' => '0',
|
170 |
+
'margin-bottom' => $panels_margin_bottom,
|
171 |
+
), $panels_tablet_width . ':' . ( $panels_mobile_width + 1 ) );
|
172 |
+
|
173 |
+
|
174 |
+
$remove_bottom_margin = ':nth-';
|
175 |
+
if ( $collapse_order == 'left-top' ) {
|
176 |
+
$remove_bottom_margin .= 'last-child(' . ( count( $row['cells'] ) % 2 == 0 ? '-n+2' : '1' ) . ')';
|
177 |
+
} else {
|
178 |
+
$remove_bottom_margin .= 'child(-n+2)';
|
179 |
+
}
|
180 |
+
|
181 |
+
$css->add_cell_css( $post_id, $ri, false, $remove_bottom_margin, array(
|
182 |
+
'margin-bottom' => 0,
|
183 |
+
), $panels_tablet_width . ':' . ( $panels_mobile_width + 1 )
|
184 |
+
);
|
185 |
+
|
186 |
+
if ( ! empty( $gutter_parts[1] ) ) {
|
187 |
+
// Tablet responsive css for cells
|
188 |
+
|
189 |
+
$css->add_cell_css( $post_id, $ri, false, ':nth-child(even)', array(
|
190 |
+
'padding-left' => ( floatval( $gutter_parts[1] / 2 ) . $gutter_parts[2] ),
|
191 |
+
), $panels_tablet_width . ':' . ( $panels_mobile_width + 1 ) );
|
192 |
+
|
193 |
+
$css->add_cell_css( $post_id, $ri, false, ':nth-child(odd)', array(
|
194 |
+
'padding-right' => ( floatval( $gutter_parts[1] / 2 ) . $gutter_parts[2] ),
|
195 |
+
), $panels_tablet_width . ':' . ( $panels_mobile_width + 1 ) );
|
196 |
+
}
|
197 |
+
|
198 |
+
}
|
199 |
+
|
200 |
+
// Mobile Responsive
|
201 |
+
$css->add_row_css( $post_id, $ri, array(
|
202 |
+
'.panel-no-style',
|
203 |
+
'.panel-has-style > .panel-row-style'
|
204 |
+
), array(
|
205 |
+
'-webkit-flex-direction' => $collapse_order == 'left-top' ? 'column' : 'column-reverse',
|
206 |
+
'-ms-flex-direction' => $collapse_order == 'left-top' ? 'column' : 'column-reverse',
|
207 |
+
'flex-direction' => $collapse_order == 'left-top' ? 'column' : 'column-reverse',
|
208 |
+
), $panels_mobile_width );
|
209 |
+
|
210 |
+
$css->add_cell_css( $post_id, $ri, false, '', array(
|
211 |
+
'width' => '100%',
|
212 |
+
'margin-right' => 0,
|
213 |
+
), $panels_mobile_width );
|
214 |
+
|
215 |
+
|
216 |
+
foreach ( $row['cells'] as $ci => $cell ) {
|
217 |
+
if ( ( $collapse_order == 'left-top' && $ci != $cell_count - 1 ) || ( $collapse_order == 'right-top' && $ci !== 0 ) ) {
|
218 |
+
$css->add_cell_css( $post_id, $ri, $ci, '', array(
|
219 |
+
'margin-bottom' => $panels_mobile_margin_bottom
|
220 |
+
), $panels_mobile_width );
|
221 |
+
}
|
222 |
+
}
|
223 |
+
|
224 |
+
if( $panels_mobile_margin_bottom != $panels_margin_bottom ) {
|
225 |
+
// If we need a different bottom margin for
|
226 |
+
$css->add_row_css( $post_id, $ri, '', array(
|
227 |
+
'margin-bottom' => $panels_mobile_margin_bottom
|
228 |
+
), $panels_mobile_width );
|
229 |
+
}
|
230 |
+
|
231 |
+
|
232 |
+
} // End of responsive code
|
233 |
+
|
234 |
+
}
|
235 |
+
|
236 |
+
// Add the bottom margins
|
237 |
+
$css->add_widget_css( $post_id, false, false, false, '', array(
|
238 |
+
'margin-bottom' => apply_filters( 'siteorigin_panels_css_cell_margin_bottom', $settings['margin-bottom'] . 'px', false, false, $panels_data, $post_id )
|
239 |
+
) );
|
240 |
+
$css->add_widget_css( $post_id, false, false, false, ':last-child', array(
|
241 |
+
'margin-bottom' => apply_filters( 'siteorigin_panels_css_cell_last_margin_bottom', '0px', false, false, $panels_data, $post_id )
|
242 |
+
) );
|
243 |
+
|
244 |
+
if ( $settings['responsive'] ) {
|
245 |
+
$css->add_cell_css( $post_id, false, false, '', array(
|
246 |
+
'padding' => 0,
|
247 |
+
), $panels_mobile_width );
|
248 |
+
|
249 |
+
// Hide empty cells on mobile
|
250 |
+
$css->add_row_css( $post_id, false, ' .panel-grid-cell-empty', array(
|
251 |
+
'display' => 'none',
|
252 |
+
), $panels_mobile_width );
|
253 |
+
|
254 |
+
// Hide empty cells on mobile
|
255 |
+
$css->add_row_css( $post_id, false, ' .panel-grid-cell-mobile-last', array(
|
256 |
+
'margin-bottom' => '0px',
|
257 |
+
), $panels_mobile_width );
|
258 |
+
}
|
259 |
+
|
260 |
+
// Let other plugins and components filter the CSS object.
|
261 |
+
$css = apply_filters( 'siteorigin_panels_css_object', $css, $panels_data, $post_id, $layout_data );
|
262 |
+
|
263 |
+
return $css->get_css();
|
264 |
+
}
|
265 |
+
|
266 |
+
/**
|
267 |
+
* Render the panels.
|
268 |
+
*
|
269 |
+
* @param int|string|bool $post_id The Post ID or 'home'.
|
270 |
+
* @param bool $enqueue_css Should we also enqueue the layout CSS.
|
271 |
+
* @param array|bool $panels_data Existing panels data. By default load from settings or post meta.
|
272 |
+
* @param array $layout_data Reformatted panels_data that includes data about the render.
|
273 |
+
*
|
274 |
+
* @return string
|
275 |
+
*/
|
276 |
+
function render( $post_id = false, $enqueue_css = true, $panels_data = false, & $layout_data = array(), $is_preview = false ) {
|
277 |
+
|
278 |
+
if ( empty( $post_id ) ) {
|
279 |
+
$post_id = get_the_ID();
|
280 |
+
|
281 |
+
if ( class_exists( 'WooCommerce' ) && is_shop() ) {
|
282 |
+
$post_id = wc_get_page_id( 'shop' );
|
283 |
+
}
|
284 |
+
}
|
285 |
+
|
286 |
+
global $siteorigin_panels_current_post;
|
287 |
+
$old_current_post = $siteorigin_panels_current_post;
|
288 |
+
$siteorigin_panels_current_post = $post_id;
|
289 |
+
|
290 |
+
// Try get the cached panel from in memory cache.
|
291 |
+
global $siteorigin_panels_cache;
|
292 |
+
if ( ! empty( $siteorigin_panels_cache ) && ! empty( $siteorigin_panels_cache[ $post_id ] ) ) {
|
293 |
+
return $siteorigin_panels_cache[ $post_id ];
|
294 |
+
}
|
295 |
+
|
296 |
+
if ( empty( $panels_data ) ) {
|
297 |
+
$panels_data = $this->get_panels_data_for_post( $post_id );
|
298 |
+
if ( $panels_data === false ) {
|
299 |
+
return false;
|
300 |
+
}
|
301 |
+
}
|
302 |
+
|
303 |
+
$panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, $post_id );
|
304 |
+
if ( empty( $panels_data ) || empty( $panels_data['grids'] ) ) {
|
305 |
+
return '';
|
306 |
+
}
|
307 |
+
|
308 |
+
if ( $is_preview ) {
|
309 |
+
$GLOBALS[ 'SITEORIGIN_PANELS_PREVIEW_RENDER' ] = true;
|
310 |
+
}
|
311 |
+
|
312 |
+
$layout_data = $this->get_panels_layout_data( $panels_data );
|
313 |
+
$layout_data = apply_filters( 'siteorigin_panels_layout_data', $layout_data, $post_id );
|
314 |
+
|
315 |
+
ob_start();
|
316 |
+
|
317 |
+
// Add the panel layout wrapper
|
318 |
+
$layout_classes = apply_filters( 'siteorigin_panels_layout_classes', array( 'panel-layout' ), $post_id, $panels_data );
|
319 |
+
if ( is_rtl() ) {
|
320 |
+
$layout_classes[] = 'panel-is-rtl';
|
321 |
+
}
|
322 |
+
$layout_attributes = apply_filters( 'siteorigin_panels_layout_attributes', array(
|
323 |
+
'id' => 'pl-' . $post_id,
|
324 |
+
'class' => implode( ' ', $layout_classes ),
|
325 |
+
), $post_id, $panels_data );
|
326 |
+
|
327 |
+
$this->render_element( 'div', $layout_attributes );
|
328 |
+
|
329 |
+
echo apply_filters( 'siteorigin_panels_before_content', '', $panels_data, $post_id );
|
330 |
+
|
331 |
+
foreach ( $layout_data as $ri => & $row ) {
|
332 |
+
$this->render_row( $post_id, $ri, $row, $panels_data );
|
333 |
+
}
|
334 |
+
|
335 |
+
echo apply_filters( 'siteorigin_panels_after_content', '', $panels_data, $post_id );
|
336 |
+
|
337 |
+
echo '</div>';
|
338 |
+
|
339 |
+
do_action( 'siteorigin_panels_after_render', $panels_data, $post_id );
|
340 |
+
|
341 |
+
$html = ob_get_clean();
|
342 |
+
|
343 |
+
if ( $enqueue_css && ! isset( $this->inline_css[ $post_id ] ) ) {
|
344 |
+
wp_enqueue_style( 'siteorigin-panels-front' );
|
345 |
+
$this->add_inline_css( $post_id, $this->generate_css( $post_id, $panels_data, $layout_data ) );
|
346 |
+
}
|
347 |
+
|
348 |
+
// Reset the current post
|
349 |
+
$siteorigin_panels_current_post = $old_current_post;
|
350 |
+
|
351 |
+
$rendered_layout = apply_filters( 'siteorigin_panels_render', $html, $post_id, ! empty( $post ) ? $post : null );
|
352 |
+
|
353 |
+
if ( $is_preview ) {
|
354 |
+
$widget_css = '@import url(' . SiteOrigin_Panels::front_css_url() . '); ';
|
355 |
+
$widget_css .= SiteOrigin_Panels::renderer()->generate_css( $post_id, $panels_data, $layout_data );
|
356 |
+
$widget_css = preg_replace( '/\s+/', ' ', $widget_css );
|
357 |
+
$rendered_layout .= "\n\n" .
|
358 |
+
'<style type="text/css" class="panels-style" data-panels-style-for-post="' . esc_attr( $post_id ) . '">' .
|
359 |
+
$widget_css .
|
360 |
+
'</style>';
|
361 |
+
}
|
362 |
+
|
363 |
+
unset( $GLOBALS[ 'SITEORIGIN_PANELS_PREVIEW_RENDER' ] );
|
364 |
+
|
365 |
+
return $rendered_layout;
|
366 |
+
}
|
367 |
+
|
368 |
+
/**
|
369 |
+
* Echo the style wrapper and return if there was a wrapper
|
370 |
+
*
|
371 |
+
* @param string $name The name of the style wrapper
|
372 |
+
* @param array $style The style wrapper args. Used as an argument for siteorigin_panels_{$name}_style_attributes
|
373 |
+
* @param string|bool $for An identifier of what this style wrapper is for
|
374 |
+
*
|
375 |
+
* @return bool Is there a style wrapper
|
376 |
+
*/
|
377 |
+
private function start_style_wrapper( $name, $style = array(), $for = false ) {
|
378 |
+
$attributes = array();
|
379 |
+
|
380 |
+
if ( empty( $attributes['class'] ) ) {
|
381 |
+
$attributes['class'] = array();
|
382 |
+
}
|
383 |
+
if ( empty( $attributes['style'] ) ) {
|
384 |
+
$attributes['style'] = '';
|
385 |
+
}
|
386 |
+
|
387 |
+
// Get everything related to the style wrapper
|
388 |
+
$attributes = apply_filters( 'siteorigin_panels_' . $name . '_style_attributes', $attributes, $style );
|
389 |
+
$attributes = apply_filters( 'siteorigin_panels_general_style_attributes', $attributes, $style );
|
390 |
+
|
391 |
+
$standard_css = array();
|
392 |
+
$standard_css = apply_filters( 'siteorigin_panels_' . $name . '_style_css', $standard_css, $style );
|
393 |
+
$standard_css = apply_filters( 'siteorigin_panels_general_style_css', $standard_css, $style );
|
394 |
+
|
395 |
+
$mobile_css = array();
|
396 |
+
$mobile_css = apply_filters( 'siteorigin_panels_' . $name . '_style_mobile_css', $mobile_css, $style );
|
397 |
+
$mobile_css = apply_filters( 'siteorigin_panels_general_style_mobile_css', $mobile_css, $style );
|
398 |
+
|
399 |
+
// Remove anything we didn't actually use
|
400 |
+
if ( empty( $attributes['class'] ) ) {
|
401 |
+
unset( $attributes['class'] );
|
402 |
+
}
|
403 |
+
if ( empty( $attributes['style'] ) ) {
|
404 |
+
unset( $attributes['style'] );
|
405 |
+
}
|
406 |
+
|
407 |
+
$style_wrapper = '';
|
408 |
+
if ( ! empty( $attributes ) || ! empty( $standard_css ) || ! empty( $mobile_css ) ) {
|
409 |
+
if ( empty( $attributes['class'] ) ) {
|
410 |
+
$attributes['class'] = array();
|
411 |
+
}
|
412 |
+
$attributes['class'][] = 'panel-' . $name . '-style';
|
413 |
+
if ( ! empty( $for ) ) {
|
414 |
+
$attributes['class'][] = 'panel-' . $name . '-style-for-' . sanitize_html_class( $for );
|
415 |
+
}
|
416 |
+
$attributes['class'] = array_unique( $attributes['class'] );
|
417 |
+
|
418 |
+
// Filter and sanitize the classes
|
419 |
+
$attributes['class'] = apply_filters( 'siteorigin_panels_' . $name . '_style_classes', $attributes['class'], $attributes, $style );
|
420 |
+
$attributes['class'] = array_map( 'sanitize_html_class', $attributes['class'] );
|
421 |
+
|
422 |
+
$style_wrapper = '<div ';
|
423 |
+
foreach ( $attributes as $name => $value ) {
|
424 |
+
// Attributes start with _ are used for internal communication between filters, so are not added to the HTML
|
425 |
+
// We don't make use of this in our styling, so its left as a mechanism for other plugins.
|
426 |
+
if ( substr( $name, 0, 1 ) === '_' ) {
|
427 |
+
continue;
|
428 |
+
}
|
429 |
+
|
430 |
+
if ( is_array( $value ) ) {
|
431 |
+
$style_wrapper .= $name . '="' . esc_attr( implode( " ", array_unique( $value ) ) ) . '" ';
|
432 |
+
} else {
|
433 |
+
$style_wrapper .= $name . '="' . esc_attr( $value ) . '" ';
|
434 |
+
}
|
435 |
+
}
|
436 |
+
$style_wrapper .= '>';
|
437 |
+
|
438 |
+
return $style_wrapper;
|
439 |
+
}
|
440 |
+
|
441 |
+
return $style_wrapper;
|
442 |
+
}
|
443 |
+
|
444 |
+
/**
|
445 |
+
* Render the widget.
|
446 |
+
*
|
447 |
+
* @param array $widget_info The widget info.
|
448 |
+
* @param array $instance The widget instance
|
449 |
+
* @param int $grid_index The grid index.
|
450 |
+
* @param int $cell_index The cell index.
|
451 |
+
* @param int $widget_index The index of this widget.
|
452 |
+
* @param bool $is_first Is this the first widget in the cell.
|
453 |
+
* @param bool $is_last Is this the last widget in the cell.
|
454 |
+
* @param bool $post_id
|
455 |
+
* @param string $style_wrapper The start of the style wrapper
|
456 |
+
*/
|
457 |
+
function the_widget( $widget_info, $instance, $grid_index, $cell_index, $widget_index, $is_first, $is_last, $post_id = false, $style_wrapper = '' ) {
|
458 |
+
|
459 |
+
// Set widget class to $widget
|
460 |
+
$widget_class = $widget_info['class'];
|
461 |
+
$widget_class = apply_filters( 'siteorigin_panels_widget_class', $widget_class );
|
462 |
+
|
463 |
+
// Load the widget from the widget factory and give themes and plugins a chance to provide their own
|
464 |
+
$the_widget = SiteOrigin_Panels::get_widget_instance( $widget_class );
|
465 |
+
$the_widget = apply_filters( 'siteorigin_panels_widget_object', $the_widget, $widget_class, $instance );
|
466 |
+
|
467 |
+
if ( empty( $post_id ) ) {
|
468 |
+
$post_id = get_the_ID();
|
469 |
+
|
470 |
+
if ( class_exists( 'WooCommerce' ) && is_shop() ) {
|
471 |
+
$post_id = wc_get_page_id( 'shop' );
|
472 |
+
}
|
473 |
+
}
|
474 |
+
|
475 |
+
$classes = array( 'so-panel' );
|
476 |
+
if ( siteorigin_panels_setting( 'add-widget-class' ) ) {
|
477 |
+
$classes[] = 'widget';
|
478 |
+
}
|
479 |
+
if ( ! empty( $the_widget ) && ! empty( $the_widget->id_base ) ) {
|
480 |
+
$classes[] = 'widget_' . $the_widget->id_base;
|
481 |
+
}
|
482 |
+
if ( ! empty( $the_widget ) && is_array( $the_widget->widget_options ) && ! empty( $the_widget->widget_options['classname'] ) ) {
|
483 |
+
$classes[] = $the_widget->widget_options['classname'];
|
484 |
+
}
|
485 |
+
if ( $is_first ) {
|
486 |
+
$classes[] = 'panel-first-child';
|
487 |
+
}
|
488 |
+
if ( $is_last ) {
|
489 |
+
$classes[] = 'panel-last-child';
|
490 |
+
}
|
491 |
+
$id = 'panel-' . $post_id . '-' . $grid_index . '-' . $cell_index . '-' . $widget_index;
|
492 |
+
|
493 |
+
// Filter and sanitize the classes
|
494 |
+
$classes = apply_filters( 'siteorigin_panels_widget_classes', $classes, $widget_class, $instance, $widget_info );
|
495 |
+
$classes = explode( ' ', implode( ' ', $classes ) );
|
496 |
+
$classes = array_filter( $classes );
|
497 |
+
$classes = array_unique( $classes );
|
498 |
+
$classes = array_map( 'sanitize_html_class', $classes );
|
499 |
+
|
500 |
+
$title_html = siteorigin_panels_setting( 'title-html' );
|
501 |
+
if ( strpos( $title_html, '{{title}}' ) !== false ) {
|
502 |
+
list( $before_title, $after_title ) = explode( '{{title}}', $title_html, 2 );
|
503 |
+
} else {
|
504 |
+
$before_title = '<h3 class="widget-title">';
|
505 |
+
$after_title = '</h3>';
|
506 |
+
}
|
507 |
+
|
508 |
+
// Attributes of the widget wrapper
|
509 |
+
$attributes = apply_filters( 'siteorigin_panels_widget_attributes', array(
|
510 |
+
'id' => $id,
|
511 |
+
'class' => implode( ' ', $classes ),
|
512 |
+
'data-index' => $widget_info['widget_index'],
|
513 |
+
), $widget_info );
|
514 |
+
|
515 |
+
$before_widget = '<div ';
|
516 |
+
foreach ( $attributes as $k => $v ) {
|
517 |
+
$before_widget .= esc_attr( $k ) . '="' . esc_attr( $v ) . '" ';
|
518 |
+
}
|
519 |
+
$before_widget .= '>';
|
520 |
+
|
521 |
+
$args = array(
|
522 |
+
'before_widget' => $before_widget,
|
523 |
+
'after_widget' => '</div>',
|
524 |
+
'before_title' => $before_title,
|
525 |
+
'after_title' => $after_title,
|
526 |
+
'widget_id' => 'widget-' . $grid_index . '-' . $cell_index . '-' . $widget_index
|
527 |
+
);
|
528 |
+
|
529 |
+
// Let other themes and plugins change the arguments that go to the widget class.
|
530 |
+
$args = apply_filters( 'siteorigin_panels_widget_args', $args );
|
531 |
+
|
532 |
+
// If there is a style wrapper, add it.
|
533 |
+
if ( ! empty( $style_wrapper ) ) {
|
534 |
+
$args['before_widget'] = $args['before_widget'] . $style_wrapper;
|
535 |
+
$args['after_widget'] = '</div>' . $args['after_widget'];
|
536 |
+
}
|
537 |
+
|
538 |
+
// This gives other plugins the chance to take over rendering of widgets
|
539 |
+
$widget_html = apply_filters( 'siteorigin_panels_the_widget_html', '', $the_widget, $args, $instance );
|
540 |
+
|
541 |
+
if ( ! empty( $widget_html ) ) {
|
542 |
+
echo $args['before_widget'];
|
543 |
+
echo $widget_html;
|
544 |
+
echo $args['after_widget'];
|
545 |
+
} else if ( ! empty( $the_widget ) && is_a( $the_widget, 'WP_Widget' ) ) {
|
546 |
+
$the_widget->widget( $args, $instance );
|
547 |
+
} else {
|
548 |
+
// This gives themes a chance to display some sort of placeholder for missing widgets
|
549 |
+
echo apply_filters( 'siteorigin_panels_missing_widget', $args['before_widget'] . $args['after_widget'], $widget_class, $args, $instance );
|
550 |
+
}
|
551 |
+
}
|
552 |
+
|
553 |
+
/**
|
554 |
+
* Print inline CSS in the header and footer.
|
555 |
+
*/
|
556 |
+
function print_inline_css() {
|
557 |
+
if ( ! empty( $this->inline_css ) ) {
|
558 |
+
$the_css = '';
|
559 |
+
foreach ( $this->inline_css as $post_id => $css ) {
|
560 |
+
if ( empty( $css ) ) {
|
561 |
+
continue;
|
562 |
+
}
|
563 |
+
$the_css .= '/* Layout ' . esc_attr( $post_id ) . ' */ ';
|
564 |
+
$the_css .= $css;
|
565 |
+
}
|
566 |
+
|
567 |
+
// Reset the inline CSS
|
568 |
+
$this->inline_css = null;
|
569 |
+
|
570 |
+
switch ( current_filter() ) {
|
571 |
+
case 'wp_head' :
|
572 |
+
$css_id = 'head';
|
573 |
+
break;
|
574 |
+
|
575 |
+
case 'wp_footer' :
|
576 |
+
$css_id = 'footer';
|
577 |
+
break;
|
578 |
+
|
579 |
+
default :
|
580 |
+
$css_id = sanitize_html_class( current_filter() );
|
581 |
+
break;
|
582 |
+
}
|
583 |
+
|
584 |
+
// Allow third party developers to change the inline styles or remove them completely.
|
585 |
+
$the_css = apply_filters( 'siteorigin_panels_inline_styles', $the_css );
|
586 |
+
|
587 |
+
if ( ! empty( $the_css ) ) {
|
588 |
+
?>
|
589 |
+
<style type="text/css" media="all"
|
590 |
+
id="siteorigin-panels-layouts-<?php echo esc_attr( $css_id ) ?>"><?php echo $the_css ?></style><?php
|
591 |
+
}
|
592 |
+
}
|
593 |
+
}
|
594 |
+
|
595 |
+
/**
|
596 |
+
* Enqueue the required styles
|
597 |
+
*/
|
598 |
+
function enqueue_styles() {
|
599 |
+
// Register the style to support possible lazy loading
|
600 |
+
wp_register_style( 'siteorigin-panels-front', SiteOrigin_Panels::front_css_url(), array(), SITEORIGIN_PANELS_VERSION );
|
601 |
+
}
|
602 |
+
|
603 |
+
/**
|
604 |
+
* Retrieve panels data for a post or a prebuilt layout or the home page layout.
|
605 |
+
*
|
606 |
+
* @param string $post_id
|
607 |
+
*
|
608 |
+
* @return array
|
609 |
+
*/
|
610 |
+
private function get_panels_data_for_post( $post_id ) {
|
611 |
+
if ( SiteOrigin_Panels::is_live_editor() ) {
|
612 |
+
if (
|
613 |
+
current_user_can( 'edit_post', $post_id ) &&
|
614 |
+
! empty( $_POST['live_editor_panels_data'] ) &&
|
615 |
+
$_POST['live_editor_post_ID'] == $post_id
|
616 |
+
) {
|
617 |
+
$panels_data = json_decode( wp_unslash( $_POST['live_editor_panels_data'] ), true );
|
618 |
+
|
619 |
+
if ( ! empty( $panels_data['widgets'] ) ) {
|
620 |
+
$panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'] );
|
621 |
+
}
|
622 |
+
}
|
623 |
+
} else if ( strpos( $post_id, 'prebuilt:' ) === 0 ) {
|
624 |
+
list( $null, $prebuilt_id ) = explode( ':', $post_id, 2 );
|
625 |
+
$layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
|
626 |
+
$panels_data = ! empty( $layouts[ $prebuilt_id ] ) ? $layouts[ $prebuilt_id ] : array();
|
627 |
+
} else if ( $post_id == 'home' ) {
|
628 |
+
$page_id = get_option( 'page_on_front' );
|
629 |
+
if ( empty( $page_id ) ) {
|
630 |
+
$page_id = get_option( 'siteorigin_panels_home_page_id' );
|
631 |
+
}
|
632 |
+
|
633 |
+
$panels_data = ! empty( $page_id ) ? get_post_meta( $page_id, 'panels_data', true ) : null;
|
634 |
+
|
635 |
+
if ( is_null( $panels_data ) ) {
|
636 |
+
// Load the default layout
|
637 |
+
$layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
|
638 |
+
$prebuilt_id = siteorigin_panels_setting( 'home-page-default' ) ? siteorigin_panels_setting( 'home-page-default' ) : 'home';
|
639 |
+
|
640 |
+
$panels_data = ! empty( $layouts[ $prebuilt_id ] ) ? $layouts[ $prebuilt_id ] : current( $layouts );
|
641 |
+
}
|
642 |
+
} else {
|
643 |
+
if ( post_password_required( $post_id ) ) {
|
644 |
+
return false;
|
645 |
+
}
|
646 |
+
$panels_data = get_post_meta( $post_id, 'panels_data', true );
|
647 |
+
}
|
648 |
+
|
649 |
+
return $panels_data;
|
650 |
+
}
|
651 |
+
|
652 |
+
/**
|
653 |
+
* Transform flat panels data into a hierarchical structure.
|
654 |
+
*
|
655 |
+
* @param array $panels_data Flat panels data containing `grids`, `grid_cells`, and `widgets`.
|
656 |
+
*
|
657 |
+
* @return array Hierarchical structure of rows => cells => widgets.
|
658 |
+
*/
|
659 |
+
public function get_panels_layout_data( $panels_data ) {
|
660 |
+
$layout_data = array();
|
661 |
+
|
662 |
+
foreach ( $panels_data['grids'] as $grid ) {
|
663 |
+
$layout_data[] = array(
|
664 |
+
'style' => ! empty( $grid['style'] ) ? $grid['style'] : array(),
|
665 |
+
'ratio' => ! empty( $grid['ratio'] ) ? $grid['ratio'] : '',
|
666 |
+
'ratio_direction' => ! empty( $grid['ratio_direction'] ) ? $grid['ratio_direction'] : '',
|
667 |
+
'color_label' => ! empty( $grid['color_label'] ) ? $grid['color_label'] : '',
|
668 |
+
'label' => ! empty( $grid['label'] ) ? $grid['label'] : '',
|
669 |
+
'cells' => array()
|
670 |
+
);
|
671 |
+
}
|
672 |
+
|
673 |
+
foreach ( $panels_data['grid_cells'] as $cell ) {
|
674 |
+
$layout_data[ $cell['grid'] ]['cells'][] = array(
|
675 |
+
'widgets' => array(),
|
676 |
+
'style' => ! empty( $cell['style'] ) ? $cell['style'] : array(),
|
677 |
+
'weight' => floatval( $cell['weight'] ),
|
678 |
+
);
|
679 |
+
}
|
680 |
+
|
681 |
+
foreach ( $panels_data['widgets'] as $i => $widget ) {
|
682 |
+
$widget['panels_info']['widget_index'] = $i;
|
683 |
+
$row_index = intval( $widget['panels_info']['grid'] );
|
684 |
+
$cell_index = intval( $widget['panels_info']['cell'] );
|
685 |
+
$layout_data[ $row_index ]['cells'][ $cell_index ]['widgets'][] = $widget;
|
686 |
+
}
|
687 |
+
|
688 |
+
return $layout_data;
|
689 |
+
}
|
690 |
+
|
691 |
+
/**
|
692 |
+
* Outputs the given HTML tag with the given attributes.
|
693 |
+
*
|
694 |
+
* @param string $tag The HTML element to render.
|
695 |
+
* @param array $attributes The attributes for the HTML element.
|
696 |
+
*
|
697 |
+
*/
|
698 |
+
private function render_element( $tag, $attributes ) {
|
699 |
+
|
700 |
+
echo '<' . $tag;
|
701 |
+
foreach ( $attributes as $name => $value ) {
|
702 |
+
if ( $value ) {
|
703 |
+
echo ' ' . $name . '="' . esc_attr( $value ) . '" ';
|
704 |
+
}
|
705 |
+
}
|
706 |
+
echo '>';
|
707 |
+
|
708 |
+
}
|
709 |
+
|
710 |
+
/**
|
711 |
+
* Render everything for the given row, including:
|
712 |
+
* - filters before and after row,
|
713 |
+
* - row style wrapper,
|
714 |
+
* - row element wrapper with attributes,
|
715 |
+
* - child cells
|
716 |
+
*
|
717 |
+
* @param string $post_id The ID of the post containing this layout.
|
718 |
+
* @param int $ri The index of this row.
|
719 |
+
* @param array $row The model containing this row's data and child cells.
|
720 |
+
* @param array $panels_data A copy of panels_data for filters.
|
721 |
+
*
|
722 |
+
*/
|
723 |
+
private function render_row( $post_id, $ri, & $row, & $panels_data ) {
|
724 |
+
$row_style_wrapper = $this->start_style_wrapper( 'row', ! empty( $row['style'] ) ? $row['style'] : array(), $post_id . '-' . $ri );
|
725 |
+
|
726 |
+
$row_classes = array( 'panel-grid' );
|
727 |
+
$row_classes[] = ! empty( $row_style_wrapper ) ? 'panel-has-style' : 'panel-no-style';
|
728 |
+
$row_classes = apply_filters( 'siteorigin_panels_row_classes', $row_classes, $row );
|
729 |
+
|
730 |
+
$row_attributes = apply_filters( 'siteorigin_panels_row_attributes', array(
|
731 |
+
'id' => 'pg-' . $post_id . '-' . $ri,
|
732 |
+
'class' => implode( ' ', $row_classes ),
|
733 |
+
), $row );
|
734 |
+
|
735 |
+
// This allows other themes and plugins to add html before the row
|
736 |
+
echo apply_filters( 'siteorigin_panels_before_row', '', $row, $row_attributes );
|
737 |
+
|
738 |
+
$this->render_element( 'div', $row_attributes );
|
739 |
+
|
740 |
+
if ( ! empty( $row_style_wrapper ) ) {
|
741 |
+
echo $row_style_wrapper;
|
742 |
+
}
|
743 |
+
|
744 |
+
if( method_exists( $this, 'modify_row_cells' ) ) {
|
745 |
+
// This gives other renderers a chance to change the cell order
|
746 |
+
$row['cells'] = $cells = $this->modify_row_cells( $row['cells'], $row );
|
747 |
+
}
|
748 |
+
|
749 |
+
foreach ( $row['cells'] as $ci => & $cell ) {
|
750 |
+
$this->render_cell( $post_id, $ri, $ci, $cell, $row['cells'], $panels_data );
|
751 |
+
}
|
752 |
+
|
753 |
+
// Close the style wrapper
|
754 |
+
if ( ! empty( $row_style_wrapper ) ) {
|
755 |
+
echo '</div>';
|
756 |
+
}
|
757 |
+
|
758 |
+
echo '</div>';
|
759 |
+
|
760 |
+
// This allows other themes and plugins to add html after the row
|
761 |
+
echo apply_filters( 'siteorigin_panels_after_row', '', $row, $row_attributes );
|
762 |
+
|
763 |
+
}
|
764 |
+
|
765 |
+
/**
|
766 |
+
*
|
767 |
+
* Render everything for the given cell, including:
|
768 |
+
* - filters before and after cell,
|
769 |
+
* - cell element wrapper with attributes,
|
770 |
+
* - style wrapper,
|
771 |
+
* - child widgets
|
772 |
+
*
|
773 |
+
* @param string $post_id The ID of the post containing this layout.
|
774 |
+
* @param int $ri The index of this cell's parent row.
|
775 |
+
* @param int $ci The index of this cell.
|
776 |
+
* @param array $cell The model containing this cell's data and child widgets.
|
777 |
+
* @param array $cells The array of cells containing this cell.
|
778 |
+
* @param array $panels_data A copy of panels_data for filters
|
779 |
+
*/
|
780 |
+
private function render_cell( $post_id, $ri, $ci, & $cell, $cells, & $panels_data ) {
|
781 |
+
|
782 |
+
$cell_classes = array( 'panel-grid-cell' );
|
783 |
+
|
784 |
+
if ( empty( $cell['widgets'] ) ) {
|
785 |
+
$cell_classes[] = 'panel-grid-cell-empty';
|
786 |
+
}
|
787 |
+
|
788 |
+
if ( $ci == count( $cells ) - 2 && count( $cells[ $ci + 1 ]['widgets'] ) == 0 ) {
|
789 |
+
$cell_classes[] = 'panel-grid-cell-mobile-last';
|
790 |
+
}
|
791 |
+
|
792 |
+
// Themes can add their own styles to cells
|
793 |
+
$cell_classes = apply_filters( 'siteorigin_panels_cell_classes', $cell_classes, $cell );
|
794 |
+
|
795 |
+
// Legacy filter, use `siteorigin_panels_cell_classes` instead
|
796 |
+
$cell_classes = apply_filters( 'siteorigin_panels_row_cell_classes', $cell_classes, $panels_data, $cell );
|
797 |
+
|
798 |
+
$cell_attributes = apply_filters( 'siteorigin_panels_cell_attributes', array(
|
799 |
+
'id' => 'pgc-' . $post_id . '-' . $ri . '-' . $ci,
|
800 |
+
'class' => implode( ' ', $cell_classes ),
|
801 |
+
), $cell );
|
802 |
+
|
803 |
+
// Legacy filter, use `siteorigin_panels_cell_attributes` instead
|
804 |
+
$cell_attributes = apply_filters( 'siteorigin_panels_row_cell_attributes', $cell_attributes, $panels_data, $cell );
|
805 |
+
|
806 |
+
echo apply_filters( 'siteorigin_panels_before_cell', '', $cell, $cell_attributes );
|
807 |
+
|
808 |
+
$this->render_element( 'div', $cell_attributes );
|
809 |
+
|
810 |
+
$grid = $panels_data['grids'][ $ri ];
|
811 |
+
|
812 |
+
if ( empty( $cell['style']['class'] ) && ! empty( $grid['style']['cell_class'] ) ) {
|
813 |
+
$cell['style']['class'] = $grid['style']['cell_class'];
|
814 |
+
}
|
815 |
+
|
816 |
+
$cell_style = ! empty( $cell['style'] ) ? $cell['style'] : array();
|
817 |
+
$cell_style_wrapper = $this->start_style_wrapper( 'cell', $cell_style, $post_id . '-' . $ri . '-' . $ci );
|
818 |
+
if ( ! empty( $cell_style_wrapper ) ) {
|
819 |
+
echo $cell_style_wrapper;
|
820 |
+
}
|
821 |
+
|
822 |
+
foreach ( $cell['widgets'] as $wi => & $widget ) {
|
823 |
+
$is_last = ( $wi == count( $cell['widgets'] ) - 1 );
|
824 |
+
$this->render_widget( $post_id, $ri, $ci, $wi, $widget, $is_last );
|
825 |
+
}
|
826 |
+
|
827 |
+
if ( ! empty( $cell_style_wrapper ) ) {
|
828 |
+
echo '</div>';
|
829 |
+
}
|
830 |
+
echo '</div>';
|
831 |
+
|
832 |
+
echo apply_filters( 'siteorigin_panels_after_cell', '', $cell, $cell_attributes );
|
833 |
+
}
|
834 |
+
|
835 |
+
/**
|
836 |
+
*
|
837 |
+
* Gets the style wrapper for this widget and passes it through to `the_widget` along with other required parameters.
|
838 |
+
*
|
839 |
+
* @param string $post_id The ID of the post containing this layout.
|
840 |
+
* @param int $ri The index of this widget's ancestor row.
|
841 |
+
* @param int $ci The index of this widget's parent cell.
|
842 |
+
* @param int $wi The index of this widget.
|
843 |
+
* @param array $widget The model containing this widget's data.
|
844 |
+
* @param bool $is_last Whether this is the last widget in the parent cell.
|
845 |
+
*
|
846 |
+
*/
|
847 |
+
private function render_widget( $post_id, $ri, $ci, $wi, & $widget, $is_last ) {
|
848 |
+
|
849 |
+
$widget_style_wrapper = $this->start_style_wrapper(
|
850 |
+
'widget',
|
851 |
+
! empty( $widget['panels_info']['style'] ) ? $widget['panels_info']['style'] : array(),
|
852 |
+
$post_id . '-' . $ri . '-' . $ci . '-' . $wi
|
853 |
+
);
|
854 |
+
|
855 |
+
$this->the_widget(
|
856 |
+
$widget['panels_info'],
|
857 |
+
$widget,
|
858 |
+
$ri,
|
859 |
+
$ci,
|
860 |
+
$wi,
|
861 |
+
$wi == 0,
|
862 |
+
$is_last,
|
863 |
+
$post_id,
|
864 |
+
$widget_style_wrapper
|
865 |
+
);
|
866 |
+
|
867 |
+
}
|
868 |
+
|
869 |
+
public function front_css_url() {
|
870 |
+
return siteorigin_panels_url( 'css/front-flex' . SITEORIGIN_PANELS_CSS_SUFFIX . '.css' );
|
871 |
+
}
|
872 |
+
}
|
inc/revisions.php
CHANGED
@@ -1,107 +1,107 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Class SiteOrigin_Panels_Revisions
|
5 |
-
*
|
6 |
-
* Handles Page Builder revisions.
|
7 |
-
*/
|
8 |
-
class SiteOrigin_Panels_Revisions {
|
9 |
-
|
10 |
-
function __construct() {
|
11 |
-
add_action( 'save_post', array( $this, 'save_post' ), 11, 2 );
|
12 |
-
add_action( 'wp_restore_post_revision', array( $this, 'revisions_restore' ), 10, 2 );
|
13 |
-
|
14 |
-
add_filter( '_wp_post_revision_fields', array( $this, 'revisions_fields' ) );
|
15 |
-
add_filter( '_wp_post_revision_field_panels_data_field', array( $this, 'revisions_field' ), 10, 3 );
|
16 |
-
}
|
17 |
-
|
18 |
-
/**
|
19 |
-
* @return SiteOrigin_Panels_Admin
|
20 |
-
*/
|
21 |
-
public static function single() {
|
22 |
-
static $single;
|
23 |
-
return empty( $single ) ? $single = new self() : $single;
|
24 |
-
}
|
25 |
-
|
26 |
-
/**
|
27 |
-
* Store the Page Builder meta in the revision.
|
28 |
-
*
|
29 |
-
* @param $post_id
|
30 |
-
* @param $post
|
31 |
-
*/
|
32 |
-
function save_post( $post_id, $post ) {
|
33 |
-
if( is_preview() ) return;
|
34 |
-
|
35 |
-
$parent_id = wp_is_post_revision( $post_id );
|
36 |
-
if ( $parent_id ) {
|
37 |
-
// Check whether the panels data needs to be copied to the revision.
|
38 |
-
$panels_data = get_metadata( 'post', $post_id, 'panels_data', true );
|
39 |
-
if ( empty( $panels_data ) ) {
|
40 |
-
// If the panels data meta exists for the post parent, copy it into the revision.
|
41 |
-
$panels_data = get_post_meta( $parent_id, 'panels_data', true );
|
42 |
-
if ( ! empty( $panels_data ) ) {
|
43 |
-
add_metadata( 'post', $post_id, 'panels_data', $panels_data );
|
44 |
-
}
|
45 |
-
}
|
46 |
-
}
|
47 |
-
}
|
48 |
-
|
49 |
-
/**
|
50 |
-
* Restore a revision.
|
51 |
-
*
|
52 |
-
* @param $post_id
|
53 |
-
* @param $revision_id
|
54 |
-
*/
|
55 |
-
function revisions_restore( $post_id, $revision_id ) {
|
56 |
-
$panels_data = get_metadata( 'post', $revision_id, 'panels_data', true );
|
57 |
-
if ( ! empty( $panels_data ) ) {
|
58 |
-
update_post_meta( $post_id, 'panels_data', map_deep( $panels_data, array( 'SiteOrigin_Panels_Admin', 'double_slash_string' ) ) );
|
59 |
-
} else {
|
60 |
-
delete_post_meta( $post_id, 'panels_data' );
|
61 |
-
}
|
62 |
-
}
|
63 |
-
|
64 |
-
/**
|
65 |
-
* Add the Page Builder content revision field.
|
66 |
-
*
|
67 |
-
* @param $fields
|
68 |
-
*
|
69 |
-
* @return mixed
|
70 |
-
*/
|
71 |
-
function revisions_fields( $fields ) {
|
72 |
-
// Prevent the autosave message.
|
73 |
-
// TODO figure out how to include Page Builder data into the autosave.
|
74 |
-
if ( ! function_exists( 'get_current_screen' ) ) {
|
75 |
-
return $fields;
|
76 |
-
}
|
77 |
-
|
78 |
-
$screen = get_current_screen();
|
79 |
-
if ( ! empty( $screen ) && $screen->base == 'post' ) {
|
80 |
-
return $fields;
|
81 |
-
}
|
82 |
-
|
83 |
-
$fields['panels_data_field'] = __( 'Page Builder Content', 'siteorigin-panels' );
|
84 |
-
|
85 |
-
return $fields;
|
86 |
-
}
|
87 |
-
|
88 |
-
/**
|
89 |
-
* Display the Page Builder content for the revision.
|
90 |
-
*
|
91 |
-
* @param $value
|
92 |
-
* @param $field
|
93 |
-
* @param $revision
|
94 |
-
*
|
95 |
-
* @return string
|
96 |
-
*/
|
97 |
-
function revisions_field( $value, $field, $revision ) {
|
98 |
-
$parent_id = wp_is_post_revision( $revision->ID );
|
99 |
-
$panels_data = get_metadata( 'post', $revision->ID, 'panels_data', true );
|
100 |
-
|
101 |
-
if ( empty( $panels_data ) ) {
|
102 |
-
return '';
|
103 |
-
}
|
104 |
-
|
105 |
-
return siteorigin_panels_render( $parent_id, false, $panels_data );
|
106 |
-
}
|
107 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class SiteOrigin_Panels_Revisions
|
5 |
+
*
|
6 |
+
* Handles Page Builder revisions.
|
7 |
+
*/
|
8 |
+
class SiteOrigin_Panels_Revisions {
|
9 |
+
|
10 |
+
function __construct() {
|
11 |
+
add_action( 'save_post', array( $this, 'save_post' ), 11, 2 );
|
12 |
+
add_action( 'wp_restore_post_revision', array( $this, 'revisions_restore' ), 10, 2 );
|
13 |
+
|
14 |
+
add_filter( '_wp_post_revision_fields', array( $this, 'revisions_fields' ) );
|
15 |
+
add_filter( '_wp_post_revision_field_panels_data_field', array( $this, 'revisions_field' ), 10, 3 );
|
16 |
+
}
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @return SiteOrigin_Panels_Admin
|
20 |
+
*/
|
21 |
+
public static function single() {
|
22 |
+
static $single;
|
23 |
+
return empty( $single ) ? $single = new self() : $single;
|
24 |
+
}
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Store the Page Builder meta in the revision.
|
28 |
+
*
|
29 |
+
* @param $post_id
|
30 |
+
* @param $post
|
31 |
+
*/
|
32 |
+
function save_post( $post_id, $post ) {
|
33 |
+
if( is_preview() ) return;
|
34 |
+
|
35 |
+
$parent_id = wp_is_post_revision( $post_id );
|
36 |
+
if ( $parent_id ) {
|
37 |
+
// Check whether the panels data needs to be copied to the revision.
|
38 |
+
$panels_data = get_metadata( 'post', $post_id, 'panels_data', true );
|
39 |
+
if ( empty( $panels_data ) ) {
|
40 |
+
// If the panels data meta exists for the post parent, copy it into the revision.
|
41 |
+
$panels_data = get_post_meta( $parent_id, 'panels_data', true );
|
42 |
+
if ( ! empty( $panels_data ) ) {
|
43 |
+
add_metadata( 'post', $post_id, 'panels_data', $panels_data );
|
44 |
+
}
|
45 |
+
}
|
46 |
+
}
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Restore a revision.
|
51 |
+
*
|
52 |
+
* @param $post_id
|
53 |
+
* @param $revision_id
|
54 |
+
*/
|
55 |
+
function revisions_restore( $post_id, $revision_id ) {
|
56 |
+
$panels_data = get_metadata( 'post', $revision_id, 'panels_data', true );
|
57 |
+
if ( ! empty( $panels_data ) ) {
|
58 |
+
update_post_meta( $post_id, 'panels_data', map_deep( $panels_data, array( 'SiteOrigin_Panels_Admin', 'double_slash_string' ) ) );
|
59 |
+
} else {
|
60 |
+
delete_post_meta( $post_id, 'panels_data' );
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Add the Page Builder content revision field.
|
66 |
+
*
|
67 |
+
* @param $fields
|
68 |
+
*
|
69 |
+
* @return mixed
|
70 |
+
*/
|
71 |
+
function revisions_fields( $fields ) {
|
72 |
+
// Prevent the autosave message.
|
73 |
+
// TODO figure out how to include Page Builder data into the autosave.
|
74 |
+
if ( ! function_exists( 'get_current_screen' ) ) {
|
75 |
+
return $fields;
|
76 |
+
}
|
77 |
+
|
78 |
+
$screen = get_current_screen();
|
79 |
+
if ( ! empty( $screen ) && $screen->base == 'post' ) {
|
80 |
+
return $fields;
|
81 |
+
}
|
82 |
+
|
83 |
+
$fields['panels_data_field'] = __( 'Page Builder Content', 'siteorigin-panels' );
|
84 |
+
|
85 |
+
return $fields;
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Display the Page Builder content for the revision.
|
90 |
+
*
|
91 |
+
* @param $value
|
92 |
+
* @param $field
|
93 |
+
* @param $revision
|
94 |
+
*
|
95 |
+
* @return string
|
96 |
+
*/
|
97 |
+
function revisions_field( $value, $field, $revision ) {
|
98 |
+
$parent_id = wp_is_post_revision( $revision->ID );
|
99 |
+
$panels_data = get_metadata( 'post', $revision->ID, 'panels_data', true );
|
100 |
+
|
101 |
+
if ( empty( $panels_data ) ) {
|
102 |
+
return '';
|
103 |
+
}
|
104 |
+
|
105 |
+
return siteorigin_panels_render( $parent_id, false, $panels_data );
|
106 |
+
}
|
107 |
+
}
|
inc/settings.php
CHANGED
@@ -1,662 +1,668 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Class to handle Page Builder settings.
|
5 |
-
*
|
6 |
-
* Class SiteOrigin_Panels_Settings
|
7 |
-
*/
|
8 |
-
class SiteOrigin_Panels_Settings {
|
9 |
-
|
10 |
-
private $settings;
|
11 |
-
private $fields;
|
12 |
-
private $settings_saved;
|
13 |
-
|
14 |
-
function __construct() {
|
15 |
-
$this->settings = array();
|
16 |
-
$this->fields = array();
|
17 |
-
$this->settings_saved = false;
|
18 |
-
|
19 |
-
// Admin actions
|
20 |
-
add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
|
21 |
-
add_action( 'admin_menu', array( $this, 'add_settings_page' ) );
|
22 |
-
add_action( 'after_setup_theme', array( $this, 'clear_cache' ), 100 );
|
23 |
-
|
24 |
-
// Default filters for fields and defaults
|
25 |
-
add_filter( 'siteorigin_panels_settings_defaults', array( $this, 'settings_defaults' ) );
|
26 |
-
add_filter( 'siteorigin_panels_default_add_widget_class', array( $this, 'add_widget_class' ) );
|
27 |
-
add_filter( 'siteorigin_panels_settings_fields', array( $this, 'settings_fields' ) );
|
28 |
-
}
|
29 |
-
|
30 |
-
/**
|
31 |
-
* @return SiteOrigin_Panels_Settings
|
32 |
-
*/
|
33 |
-
static function single() {
|
34 |
-
static $single;
|
35 |
-
return empty( $single ) ? $single = new self() : $single;
|
36 |
-
}
|
37 |
-
|
38 |
-
function clear_cache() {
|
39 |
-
$this->settings = array();
|
40 |
-
}
|
41 |
-
|
42 |
-
/**
|
43 |
-
* Get a settings value
|
44 |
-
*
|
45 |
-
* @param string $key
|
46 |
-
*
|
47 |
-
* @return array|bool|mixed|null|void
|
48 |
-
*/
|
49 |
-
function get( $key = '' ) {
|
50 |
-
|
51 |
-
if ( empty( $this->settings ) ) {
|
52 |
-
|
53 |
-
// Get the settings, attempt to fetch new settings first.
|
54 |
-
$current_settings = get_option( 'siteorigin_panels_settings', false );
|
55 |
-
|
56 |
-
if ( $current_settings === false ) {
|
57 |
-
// We can't find the settings, so try access old settings
|
58 |
-
$current_settings = get_option( 'siteorigin_panels_display', array() );
|
59 |
-
$post_types = get_option( 'siteorigin_panels_post_types' );
|
60 |
-
if ( ! empty( $post_types ) ) {
|
61 |
-
$current_settings['post-types'] = $post_types;
|
62 |
-
}
|
63 |
-
|
64 |
-
// Store the old settings in the new field
|
65 |
-
update_option( 'siteorigin_panels_settings', $current_settings );
|
66 |
-
}
|
67 |
-
|
68 |
-
// Get the settings provided by the theme
|
69 |
-
$theme_settings = get_theme_support( 'siteorigin-panels' );
|
70 |
-
if ( ! empty( $theme_settings ) ) {
|
71 |
-
$theme_settings = $theme_settings[0];
|
72 |
-
} else {
|
73 |
-
$theme_settings = array();
|
74 |
-
}
|
75 |
-
|
76 |
-
$this->settings = wp_parse_args( $theme_settings, apply_filters( 'siteorigin_panels_settings_defaults', array() ) );
|
77 |
-
$this->settings = wp_parse_args( $current_settings, $this->settings );
|
78 |
-
|
79 |
-
// Filter these settings
|
80 |
-
$this->settings = apply_filters( 'siteorigin_panels_settings', $this->settings );
|
81 |
-
}
|
82 |
-
|
83 |
-
if ( ! empty( $key ) ) {
|
84 |
-
return isset( $this->settings[ $key ] ) ? $this->settings[ $key ] : null;
|
85 |
-
}
|
86 |
-
|
87 |
-
return $this->settings;
|
88 |
-
}
|
89 |
-
|
90 |
-
/**
|
91 |
-
* Set a settings value
|
92 |
-
*
|
93 |
-
* @param $key
|
94 |
-
* @param $value
|
95 |
-
*/
|
96 |
-
function set( $key, $value ) {
|
97 |
-
$current_settings = get_option( 'siteorigin_panels_settings', array() );
|
98 |
-
$current_settings[ $key ] = $value;
|
99 |
-
update_option( 'siteorigin_panels_settings', $current_settings );
|
100 |
-
}
|
101 |
-
|
102 |
-
/**
|
103 |
-
* Add default settings for the Page Builder settings.
|
104 |
-
*
|
105 |
-
* @param $defaults
|
106 |
-
*
|
107 |
-
* @return mixed
|
108 |
-
*/
|
109 |
-
function settings_defaults( $defaults ) {
|
110 |
-
$defaults['home-page'] = false;
|
111 |
-
$defaults['home-page-default'] = false;
|
112 |
-
$defaults['home-template'] = 'home-panels.php';
|
113 |
-
$defaults['affiliate-id'] = apply_filters( 'siteorigin_panels_affiliate_id', false );
|
114 |
-
$defaults['display-teaser'] = true;
|
115 |
-
$defaults['display-learn'] = true;
|
116 |
-
$defaults['load-on-attach'] = false;
|
117 |
-
$defaults['use-classic'] = true;
|
118 |
-
|
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;
|
126 |
-
$defaults['layout-block-default-mode'] = 'preview';
|
127 |
-
|
128 |
-
// Widgets fields
|
129 |
-
$defaults['title-html'] = '<h3 class="widget-title">{{title}}</h3>';
|
130 |
-
$defaults['add-widget-class'] = apply_filters( 'siteorigin_panels_default_add_widget_class', true );
|
131 |
-
$defaults['bundled-widgets'] = get_option( 'siteorigin_panels_is_using_bundled', false );
|
132 |
-
$defaults['recommended-widgets'] = true;
|
133 |
-
$defaults['instant-open-widgets'] = false;
|
134 |
-
|
135 |
-
// The layout fields
|
136 |
-
$defaults['responsive'] = true;
|
137 |
-
$defaults['tablet-layout'] = false;
|
138 |
-
$defaults['legacy-layout'] = 'auto';
|
139 |
-
$defaults['tablet-width'] = 1024;
|
140 |
-
$defaults['mobile-width'] = 780;
|
141 |
-
$defaults['margin-bottom'] = 30;
|
142 |
-
$defaults['margin-bottom-last-row'] = false;
|
143 |
-
$defaults['margin-sides'] = 30;
|
144 |
-
$defaults['full-width-container'] = 'body';
|
145 |
-
|
146 |
-
// Content fields
|
147 |
-
$defaults['copy-content'] = true;
|
148 |
-
$defaults['copy-styles'] = false;
|
149 |
-
|
150 |
-
return $defaults;
|
151 |
-
}
|
152 |
-
|
153 |
-
/**
|
154 |
-
* Set the option on whether to add widget classes for known themes
|
155 |
-
*
|
156 |
-
* @param $add_class
|
157 |
-
*
|
158 |
-
* @return bool
|
159 |
-
*/
|
160 |
-
function add_widget_class( $add_class ) {
|
161 |
-
|
162 |
-
switch ( get_option( 'stylesheet' ) ) {
|
163 |
-
case 'twentysixteen';
|
164 |
-
$add_class = false;
|
165 |
-
break;
|
166 |
-
}
|
167 |
-
|
168 |
-
|
169 |
-
return $add_class;
|
170 |
-
}
|
171 |
-
|
172 |
-
/**
|
173 |
-
* Enqueue admin scripts
|
174 |
-
*
|
175 |
-
* @param $prefix
|
176 |
-
*/
|
177 |
-
function admin_scripts( $prefix ) {
|
178 |
-
if ( $prefix != 'settings_page_siteorigin_panels' ) {
|
179 |
-
return;
|
180 |
-
}
|
181 |
-
wp_enqueue_style(
|
182 |
-
'siteorigin-panels-settings',
|
183 |
-
siteorigin_panels_url( 'settings/admin-settings.css' ),
|
184 |
-
array(),
|
185 |
-
SITEORIGIN_PANELS_VERSION
|
186 |
-
);
|
187 |
-
wp_enqueue_script(
|
188 |
-
'siteorigin-panels-settings',
|
189 |
-
siteorigin_panels_url( 'settings/admin-settings' . SITEORIGIN_PANELS_JS_SUFFIX . '.js' ),
|
190 |
-
array(),
|
191 |
-
SITEORIGIN_PANELS_VERSION
|
192 |
-
);
|
193 |
-
}
|
194 |
-
|
195 |
-
/**
|
196 |
-
* Add the Page Builder settings page
|
197 |
-
*/
|
198 |
-
function add_settings_page() {
|
199 |
-
$page = add_options_page( __( 'SiteOrigin Page Builder', 'siteorigin-panels' ), __( 'Page Builder', 'siteorigin-panels' ), 'manage_options', 'siteorigin_panels', array(
|
200 |
-
$this,
|
201 |
-
'display_settings_page'
|
202 |
-
) );
|
203 |
-
add_action( 'load-' . $page, array( $this, 'add_help_tab' ) );
|
204 |
-
add_action( 'load-' . $page, array( $this, 'save_settings' ) );
|
205 |
-
}
|
206 |
-
|
207 |
-
/**
|
208 |
-
* Display the Page Builder settings page
|
209 |
-
*/
|
210 |
-
function display_settings_page() {
|
211 |
-
$settings_fields = $this->fields = apply_filters( 'siteorigin_panels_settings_fields', array() );
|
212 |
-
include plugin_dir_path( __FILE__ ) . '../settings/tpl/settings.php';
|
213 |
-
}
|
214 |
-
|
215 |
-
/**
|
216 |
-
* Add a settings help tab
|
217 |
-
*/
|
218 |
-
function add_help_tab() {
|
219 |
-
$screen = get_current_screen();
|
220 |
-
ob_start();
|
221 |
-
include plugin_dir_path( __FILE__ ) . '../settings/tpl/help.php';
|
222 |
-
$content = ob_get_clean();
|
223 |
-
|
224 |
-
$screen->add_help_tab( array(
|
225 |
-
'id' => 'panels-help-tab',
|
226 |
-
'title' => __( 'Page Builder Settings', 'siteorigin-panels' ),
|
227 |
-
'content' => $content
|
228 |
-
) );
|
229 |
-
}
|
230 |
-
|
231 |
-
/**
|
232 |
-
* Add the default Page Builder settings.
|
233 |
-
*
|
234 |
-
* @param $fields
|
235 |
-
*
|
236 |
-
* @return mixed
|
237 |
-
*/
|
238 |
-
function settings_fields( $fields ) {
|
239 |
-
// The post types fields
|
240 |
-
|
241 |
-
$fields['general'] = array(
|
242 |
-
'title' => __( 'General', 'siteorigin-panels' ),
|
243 |
-
'fields' => array(),
|
244 |
-
);
|
245 |
-
|
246 |
-
$fields['general']['fields']['post-types'] = array(
|
247 |
-
'type' => 'select_multi',
|
248 |
-
'label' => __( 'Post Types', 'siteorigin-panels' ),
|
249 |
-
'options' => $this->get_post_types(),
|
250 |
-
'description' => __( 'The post types on which to use Page Builder.', 'siteorigin-panels' ),
|
251 |
-
);
|
252 |
-
|
253 |
-
$fields['general']['fields']['use-classic'] = array(
|
254 |
-
'type' => 'checkbox',
|
255 |
-
'label' => __( 'Use Classic Editor for new posts', 'siteorigin-panels' ),
|
256 |
-
'description' => __( 'New posts of the above Post Types will be created using the Classic Editor.', 'siteorigin-panels' )
|
257 |
-
);
|
258 |
-
|
259 |
-
$fields['general']['fields']['live-editor-quick-link'] = array(
|
260 |
-
'type' => 'checkbox',
|
261 |
-
'label' => __( 'Live Editor Quick Link', 'siteorigin-panels' ),
|
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' ),
|
278 |
-
'description' => __( "Display a widget count in the admin lists of posts/pages where you're using Page Builder.", 'siteorigin-panels' ),
|
279 |
-
);
|
280 |
-
|
281 |
-
$fields['general']['fields']['parallax-motion'] = array(
|
282 |
-
'type' => 'float',
|
283 |
-
'label' => __( 'Limit Parallax Motion', 'siteorigin-panels' ),
|
284 |
-
'description' => __( 'How many pixels of scrolling result in a single pixel of parallax motion. 0 means automatic. Lower values give more noticeable effect.', 'siteorigin-panels' ),
|
285 |
-
);
|
286 |
-
|
287 |
-
$fields['general']['fields']['sidebars-emulator'] = array(
|
288 |
-
'type' => 'checkbox',
|
289 |
-
'label' => __( 'Sidebars Emulator', 'siteorigin-panels' ),
|
290 |
-
'description' => __( 'Page Builder will create an emulated sidebar, that contains all widgets in the page.', 'siteorigin-panels' ),
|
291 |
-
);
|
292 |
-
|
293 |
-
$fields['general']['fields']['display-teaser'] = array(
|
294 |
-
'type' => 'checkbox',
|
295 |
-
'label' => __('Upgrade Teaser', 'siteorigin-panels'),
|
296 |
-
'description' => sprintf(
|
297 |
-
__('Display the %sSiteOrigin Premium%s upgrade teaser in the Page Builder toolbar.', 'siteorigin-panels'),
|
298 |
-
'<a href="siteorigin.com/downloads/premium/" target="_blank" rel="noopener noreferrer">',
|
299 |
-
'</a>'
|
300 |
-
)
|
301 |
-
);
|
302 |
-
|
303 |
-
$fields['general']['fields']['load-on-attach'] = array(
|
304 |
-
'type' => 'checkbox',
|
305 |
-
'label' => __( 'Default To Page Builder Interface', 'siteorigin-panels' ),
|
306 |
-
'description' => sprintf(
|
307 |
-
__( '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.', 'siteorigin-panels' ),
|
308 |
-
'<strong>',
|
309 |
-
'</strong>'
|
310 |
-
)
|
311 |
-
);
|
312 |
-
|
313 |
-
$fields['general']['fields']['layout-block-default-mode'] = array(
|
314 |
-
'label' => __( 'Layout Block Default Mode', 'siteorigin-panels' ),
|
315 |
-
'type' => 'select',
|
316 |
-
'options' => array(
|
317 |
-
'edit' => __( 'Edit', 'siteorigin-panels' ),
|
318 |
-
'preview' => __( 'Preview', 'siteorigin-panels' ),
|
319 |
-
),
|
320 |
-
'description' => __( 'Whether to display layout blocks in edit mode or preview mode in the block editor.', 'siteorigin-panels' ),
|
321 |
-
);
|
322 |
-
|
323 |
-
// The widgets fields
|
324 |
-
|
325 |
-
$fields['widgets'] = array(
|
326 |
-
'title' => __( 'Widgets', 'siteorigin-panels' ),
|
327 |
-
'fields' => array(),
|
328 |
-
);
|
329 |
-
|
330 |
-
$fields['widgets']['fields']['title-html'] = array(
|
331 |
-
'type' => 'html',
|
332 |
-
'label' => __( 'Widget Title HTML', 'siteorigin-panels' ),
|
333 |
-
'description' => __( 'The HTML used for widget titles. {{title}} is replaced with the widget title.', 'siteorigin-panels' ),
|
334 |
-
);
|
335 |
-
|
336 |
-
$fields['widgets']['fields']['add-widget-class'] = array(
|
337 |
-
'type' => 'checkbox',
|
338 |
-
'label' => __( 'Add Widget Class', 'siteorigin-panels' ),
|
339 |
-
'description' => __( "Add the widget class to Page Builder widgets. Disable this if you're experiencing conflicts.", 'siteorigin-panels' ),
|
340 |
-
);
|
341 |
-
|
342 |
-
$fields['widgets']['fields']['bundled-widgets'] = array(
|
343 |
-
'type' => 'checkbox',
|
344 |
-
'label' => __( 'Legacy Bundled Widgets', 'siteorigin-panels' ),
|
345 |
-
'description' => __( 'Load legacy widgets from Page Builder 1.', 'siteorigin-panels' ),
|
346 |
-
);
|
347 |
-
|
348 |
-
$fields['widgets']['fields']['recommended-widgets'] = array(
|
349 |
-
'type' => 'checkbox',
|
350 |
-
'label' => __( 'Recommended Widgets', 'siteorigin-panels' ),
|
351 |
-
'description' => __( 'Display recommend widgets in Page Builder add widget dialog.', 'siteorigin-panels' ),
|
352 |
-
);
|
353 |
-
|
354 |
-
$fields['widgets']['fields']['instant-open-widgets'] = array(
|
355 |
-
'type' => 'checkbox',
|
356 |
-
'label' => __( 'Instant Open Widgets', 'siteorigin-panels' ),
|
357 |
-
'description' => __( 'Open a widget form as soon as its added to a page.', 'siteorigin-panels' ),
|
358 |
-
);
|
359 |
-
|
360 |
-
// The layout fields
|
361 |
-
|
362 |
-
$fields['layout'] = array(
|
363 |
-
'title' => __( 'Layout', 'siteorigin-panels' ),
|
364 |
-
'fields' => array(),
|
365 |
-
);
|
366 |
-
|
367 |
-
// The layout fields
|
368 |
-
|
369 |
-
$fields['layout']['fields']['responsive'] = array(
|
370 |
-
'type' => 'checkbox',
|
371 |
-
'label' => __( 'Responsive Layout', 'siteorigin-panels' ),
|
372 |
-
'description' => __( 'Collapse widgets, rows and columns on mobile devices.', 'siteorigin-panels' ),
|
373 |
-
);
|
374 |
-
|
375 |
-
$fields['layout']['fields']['tablet-layout'] = array(
|
376 |
-
'type' => 'checkbox',
|
377 |
-
'label' => __( 'Use Tablet Layout', 'siteorigin-panels' ),
|
378 |
-
'description' => __( 'Collapses columns differently on tablet devices.', 'siteorigin-panels' ),
|
379 |
-
);
|
380 |
-
|
381 |
-
$fields['layout']['fields']['legacy-layout'] = array(
|
382 |
-
'type' => 'select',
|
383 |
-
'options' => array(
|
384 |
-
'auto' => __( 'Detect older browsers', 'siteorigin-panels' ),
|
385 |
-
'never' => __( 'Never', 'siteorigin-panels' ),
|
386 |
-
'always' => __( 'Always', 'siteorigin-panels' ),
|
387 |
-
),
|
388 |
-
'label' => __( 'Use Legacy Layout Engine', 'siteorigin-panels' ),
|
389 |
-
'description' => __( 'The CSS and HTML uses floats instead of flexbox for compatibility with very old browsers.', 'siteorigin-panels' ),
|
390 |
-
);
|
391 |
-
|
392 |
-
$fields['layout']['fields']['tablet-width'] = array(
|
393 |
-
'type' => 'number',
|
394 |
-
'unit' => 'px',
|
395 |
-
'label' => __( 'Tablet Width', 'siteorigin-panels' ),
|
396 |
-
'description' => __( 'Device width, in pixels, to collapse into a tablet view .', 'siteorigin-panels' ),
|
397 |
-
);
|
398 |
-
|
399 |
-
$fields['layout']['fields']['mobile-width'] = array(
|
400 |
-
'type' => 'number',
|
401 |
-
'unit' => 'px',
|
402 |
-
'label' => __( 'Mobile Width', 'siteorigin-panels' ),
|
403 |
-
'description' => __( 'Device width, in pixels, to collapse into a mobile view .', 'siteorigin-panels' ),
|
404 |
-
);
|
405 |
-
|
406 |
-
$fields['layout']['fields']['margin-bottom'] = array(
|
407 |
-
'type' => 'number',
|
408 |
-
'unit' => 'px',
|
409 |
-
'label' => __( 'Row/Widget Bottom Margin', 'siteorigin-panels' ),
|
410 |
-
'description' => __( 'Default margin below rows and widgets.', 'siteorigin-panels' ),
|
411 |
-
);
|
412 |
-
|
413 |
-
$fields['layout']['fields']['margin-bottom-last-row'] = array(
|
414 |
-
'type' => 'checkbox',
|
415 |
-
'label' => __( 'Last Row With Margin', 'siteorigin-panels' ),
|
416 |
-
'description' => __( 'Allow margin in last row.', 'siteorigin-panels' ),
|
417 |
-
);
|
418 |
-
|
419 |
-
$fields['layout']['fields']['margin-sides'] = array(
|
420 |
-
'type' => 'number',
|
421 |
-
'unit' => 'px',
|
422 |
-
'label' => __( 'Row Gutter', 'siteorigin-panels' ),
|
423 |
-
'description' => __( 'Default spacing between columns in each row.', 'siteorigin-panels' ),
|
424 |
-
'keywords' => 'margin',
|
425 |
-
);
|
426 |
-
|
427 |
-
$fields['layout']['fields']['full-width-container'] = array(
|
428 |
-
'type' => 'text',
|
429 |
-
'label' => __( 'Full Width Container', 'siteorigin-panels' ),
|
430 |
-
'description' => __( 'The container used for the full width layout.', 'siteorigin-panels' ),
|
431 |
-
'keywords' => 'full width, container, stretch',
|
432 |
-
);
|
433 |
-
|
434 |
-
// The content fields
|
435 |
-
|
436 |
-
$fields['content'] = array(
|
437 |
-
'title' => __( 'Content', 'siteorigin-panels' ),
|
438 |
-
'fields' => array(),
|
439 |
-
);
|
440 |
-
|
441 |
-
$fields['content']['fields']['copy-content'] = array(
|
442 |
-
'type' => 'checkbox',
|
443 |
-
'label' => __( 'Copy Content', 'siteorigin-panels' ),
|
444 |
-
'description' => __( 'Copy content from Page Builder to post content.', 'siteorigin-panels' ),
|
445 |
-
);
|
446 |
-
|
447 |
-
$fields['content']['fields']['copy-styles'] = array(
|
448 |
-
'type' => 'checkbox',
|
449 |
-
'label' => __( 'Copy Styles', 'siteorigin-panels' ),
|
450 |
-
'description' => __( 'Include styles into your Post Content. This keeps page layouts, even when Page Builder is deactivated.', 'siteorigin-panels' ),
|
451 |
-
);
|
452 |
-
|
453 |
-
return $fields;
|
454 |
-
}
|
455 |
-
|
456 |
-
/**
|
457 |
-
* Display a settings field
|
458 |
-
*
|
459 |
-
* @param $field_id
|
460 |
-
* @param $field
|
461 |
-
*/
|
462 |
-
function display_field( $field_id, $field ) {
|
463 |
-
$value = siteorigin_panels_setting( $field_id );
|
464 |
-
|
465 |
-
$field_name = 'panels_setting[' . $field_id . ']';
|
466 |
-
|
467 |
-
switch ( $field['type'] ) {
|
468 |
-
case 'text':
|
469 |
-
case 'float':
|
470 |
-
?><input name="<?php echo esc_attr( $field_name ) ?>"
|
471 |
-
class="panels-setting-<?php echo esc_attr( $field['type'] ) ?>" type="text"
|
472 |
-
value="<?php echo esc_attr( $value ) ?>" /> <?php
|
473 |
-
break;
|
474 |
-
|
475 |
-
case '
|
476 |
-
?>
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
break;
|
491 |
-
|
492 |
-
case '
|
493 |
-
?>
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
<?php
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
if (
|
544 |
-
return;
|
545 |
-
}
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
$values[ $field_id ] =
|
578 |
-
}
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
break;
|
588 |
-
|
589 |
-
case '
|
590 |
-
$values[ $field_id ] = ! empty( $post[ $field_id ] );
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
$values[ $field_id ]
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
$
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class to handle Page Builder settings.
|
5 |
+
*
|
6 |
+
* Class SiteOrigin_Panels_Settings
|
7 |
+
*/
|
8 |
+
class SiteOrigin_Panels_Settings {
|
9 |
+
|
10 |
+
private $settings;
|
11 |
+
private $fields;
|
12 |
+
private $settings_saved;
|
13 |
+
|
14 |
+
function __construct() {
|
15 |
+
$this->settings = array();
|
16 |
+
$this->fields = array();
|
17 |
+
$this->settings_saved = false;
|
18 |
+
|
19 |
+
// Admin actions
|
20 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
|
21 |
+
add_action( 'admin_menu', array( $this, 'add_settings_page' ) );
|
22 |
+
add_action( 'after_setup_theme', array( $this, 'clear_cache' ), 100 );
|
23 |
+
|
24 |
+
// Default filters for fields and defaults
|
25 |
+
add_filter( 'siteorigin_panels_settings_defaults', array( $this, 'settings_defaults' ) );
|
26 |
+
add_filter( 'siteorigin_panels_default_add_widget_class', array( $this, 'add_widget_class' ) );
|
27 |
+
add_filter( 'siteorigin_panels_settings_fields', array( $this, 'settings_fields' ) );
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @return SiteOrigin_Panels_Settings
|
32 |
+
*/
|
33 |
+
static function single() {
|
34 |
+
static $single;
|
35 |
+
return empty( $single ) ? $single = new self() : $single;
|
36 |
+
}
|
37 |
+
|
38 |
+
function clear_cache() {
|
39 |
+
$this->settings = array();
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Get a settings value
|
44 |
+
*
|
45 |
+
* @param string $key
|
46 |
+
*
|
47 |
+
* @return array|bool|mixed|null|void
|
48 |
+
*/
|
49 |
+
function get( $key = '' ) {
|
50 |
+
|
51 |
+
if ( empty( $this->settings ) ) {
|
52 |
+
|
53 |
+
// Get the settings, attempt to fetch new settings first.
|
54 |
+
$current_settings = get_option( 'siteorigin_panels_settings', false );
|
55 |
+
|
56 |
+
if ( $current_settings === false ) {
|
57 |
+
// We can't find the settings, so try access old settings
|
58 |
+
$current_settings = get_option( 'siteorigin_panels_display', array() );
|
59 |
+
$post_types = get_option( 'siteorigin_panels_post_types' );
|
60 |
+
if ( ! empty( $post_types ) ) {
|
61 |
+
$current_settings['post-types'] = $post_types;
|
62 |
+
}
|
63 |
+
|
64 |
+
// Store the old settings in the new field
|
65 |
+
update_option( 'siteorigin_panels_settings', $current_settings );
|
66 |
+
}
|
67 |
+
|
68 |
+
// Get the settings provided by the theme
|
69 |
+
$theme_settings = get_theme_support( 'siteorigin-panels' );
|
70 |
+
if ( ! empty( $theme_settings ) ) {
|
71 |
+
$theme_settings = $theme_settings[0];
|
72 |
+
} else {
|
73 |
+
$theme_settings = array();
|
74 |
+
}
|
75 |
+
|
76 |
+
$this->settings = wp_parse_args( $theme_settings, apply_filters( 'siteorigin_panels_settings_defaults', array() ) );
|
77 |
+
$this->settings = wp_parse_args( $current_settings, $this->settings );
|
78 |
+
|
79 |
+
// Filter these settings
|
80 |
+
$this->settings = apply_filters( 'siteorigin_panels_settings', $this->settings );
|
81 |
+
}
|
82 |
+
|
83 |
+
if ( ! empty( $key ) ) {
|
84 |
+
return isset( $this->settings[ $key ] ) ? $this->settings[ $key ] : null;
|
85 |
+
}
|
86 |
+
|
87 |
+
return $this->settings;
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Set a settings value
|
92 |
+
*
|
93 |
+
* @param $key
|
94 |
+
* @param $value
|
95 |
+
*/
|
96 |
+
function set( $key, $value ) {
|
97 |
+
$current_settings = get_option( 'siteorigin_panels_settings', array() );
|
98 |
+
$current_settings[ $key ] = $value;
|
99 |
+
update_option( 'siteorigin_panels_settings', $current_settings );
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Add default settings for the Page Builder settings.
|
104 |
+
*
|
105 |
+
* @param $defaults
|
106 |
+
*
|
107 |
+
* @return mixed
|
108 |
+
*/
|
109 |
+
function settings_defaults( $defaults ) {
|
110 |
+
$defaults['home-page'] = false;
|
111 |
+
$defaults['home-page-default'] = false;
|
112 |
+
$defaults['home-template'] = 'home-panels.php';
|
113 |
+
$defaults['affiliate-id'] = apply_filters( 'siteorigin_panels_affiliate_id', false );
|
114 |
+
$defaults['display-teaser'] = true;
|
115 |
+
$defaults['display-learn'] = true;
|
116 |
+
$defaults['load-on-attach'] = false;
|
117 |
+
$defaults['use-classic'] = true;
|
118 |
+
|
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;
|
126 |
+
$defaults['layout-block-default-mode'] = 'preview';
|
127 |
+
|
128 |
+
// Widgets fields
|
129 |
+
$defaults['title-html'] = '<h3 class="widget-title">{{title}}</h3>';
|
130 |
+
$defaults['add-widget-class'] = apply_filters( 'siteorigin_panels_default_add_widget_class', true );
|
131 |
+
$defaults['bundled-widgets'] = get_option( 'siteorigin_panels_is_using_bundled', false );
|
132 |
+
$defaults['recommended-widgets'] = true;
|
133 |
+
$defaults['instant-open-widgets'] = false;
|
134 |
+
|
135 |
+
// The layout fields
|
136 |
+
$defaults['responsive'] = true;
|
137 |
+
$defaults['tablet-layout'] = false;
|
138 |
+
$defaults['legacy-layout'] = 'auto';
|
139 |
+
$defaults['tablet-width'] = 1024;
|
140 |
+
$defaults['mobile-width'] = 780;
|
141 |
+
$defaults['margin-bottom'] = 30;
|
142 |
+
$defaults['margin-bottom-last-row'] = false;
|
143 |
+
$defaults['margin-sides'] = 30;
|
144 |
+
$defaults['full-width-container'] = 'body';
|
145 |
+
|
146 |
+
// Content fields
|
147 |
+
$defaults['copy-content'] = true;
|
148 |
+
$defaults['copy-styles'] = false;
|
149 |
+
|
150 |
+
return $defaults;
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Set the option on whether to add widget classes for known themes
|
155 |
+
*
|
156 |
+
* @param $add_class
|
157 |
+
*
|
158 |
+
* @return bool
|
159 |
+
*/
|
160 |
+
function add_widget_class( $add_class ) {
|
161 |
+
|
162 |
+
switch ( get_option( 'stylesheet' ) ) {
|
163 |
+
case 'twentysixteen';
|
164 |
+
$add_class = false;
|
165 |
+
break;
|
166 |
+
}
|
167 |
+
|
168 |
+
|
169 |
+
return $add_class;
|
170 |
+
}
|
171 |
+
|
172 |
+
/**
|
173 |
+
* Enqueue admin scripts
|
174 |
+
*
|
175 |
+
* @param $prefix
|
176 |
+
*/
|
177 |
+
function admin_scripts( $prefix ) {
|
178 |
+
if ( $prefix != 'settings_page_siteorigin_panels' ) {
|
179 |
+
return;
|
180 |
+
}
|
181 |
+
wp_enqueue_style(
|
182 |
+
'siteorigin-panels-settings',
|
183 |
+
siteorigin_panels_url( 'settings/admin-settings.css' ),
|
184 |
+
array(),
|
185 |
+
SITEORIGIN_PANELS_VERSION
|
186 |
+
);
|
187 |
+
wp_enqueue_script(
|
188 |
+
'siteorigin-panels-settings',
|
189 |
+
siteorigin_panels_url( 'settings/admin-settings' . SITEORIGIN_PANELS_JS_SUFFIX . '.js' ),
|
190 |
+
array(),
|
191 |
+
SITEORIGIN_PANELS_VERSION
|
192 |
+
);
|
193 |
+
}
|
194 |
+
|
195 |
+
/**
|
196 |
+
* Add the Page Builder settings page
|
197 |
+
*/
|
198 |
+
function add_settings_page() {
|
199 |
+
$page = add_options_page( __( 'SiteOrigin Page Builder', 'siteorigin-panels' ), __( 'Page Builder', 'siteorigin-panels' ), 'manage_options', 'siteorigin_panels', array(
|
200 |
+
$this,
|
201 |
+
'display_settings_page'
|
202 |
+
) );
|
203 |
+
add_action( 'load-' . $page, array( $this, 'add_help_tab' ) );
|
204 |
+
add_action( 'load-' . $page, array( $this, 'save_settings' ) );
|
205 |
+
}
|
206 |
+
|
207 |
+
/**
|
208 |
+
* Display the Page Builder settings page
|
209 |
+
*/
|
210 |
+
function display_settings_page() {
|
211 |
+
$settings_fields = $this->fields = apply_filters( 'siteorigin_panels_settings_fields', array() );
|
212 |
+
include plugin_dir_path( __FILE__ ) . '../settings/tpl/settings.php';
|
213 |
+
}
|
214 |
+
|
215 |
+
/**
|
216 |
+
* Add a settings help tab
|
217 |
+
*/
|
218 |
+
function add_help_tab() {
|
219 |
+
$screen = get_current_screen();
|
220 |
+
ob_start();
|
221 |
+
include plugin_dir_path( __FILE__ ) . '../settings/tpl/help.php';
|
222 |
+
$content = ob_get_clean();
|
223 |
+
|
224 |
+
$screen->add_help_tab( array(
|
225 |
+
'id' => 'panels-help-tab',
|
226 |
+
'title' => __( 'Page Builder Settings', 'siteorigin-panels' ),
|
227 |
+
'content' => $content
|
228 |
+
) );
|
229 |
+
}
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Add the default Page Builder settings.
|
233 |
+
*
|
234 |
+
* @param $fields
|
235 |
+
*
|
236 |
+
* @return mixed
|
237 |
+
*/
|
238 |
+
function settings_fields( $fields ) {
|
239 |
+
// The post types fields
|
240 |
+
|
241 |
+
$fields['general'] = array(
|
242 |
+
'title' => __( 'General', 'siteorigin-panels' ),
|
243 |
+
'fields' => array(),
|
244 |
+
);
|
245 |
+
|
246 |
+
$fields['general']['fields']['post-types'] = array(
|
247 |
+
'type' => 'select_multi',
|
248 |
+
'label' => __( 'Post Types', 'siteorigin-panels' ),
|
249 |
+
'options' => $this->get_post_types(),
|
250 |
+
'description' => __( 'The post types on which to use Page Builder.', 'siteorigin-panels' ),
|
251 |
+
);
|
252 |
+
|
253 |
+
$fields['general']['fields']['use-classic'] = array(
|
254 |
+
'type' => 'checkbox',
|
255 |
+
'label' => __( 'Use Classic Editor for new posts', 'siteorigin-panels' ),
|
256 |
+
'description' => __( 'New posts of the above Post Types will be created using the Classic Editor.', 'siteorigin-panels' )
|
257 |
+
);
|
258 |
+
|
259 |
+
$fields['general']['fields']['live-editor-quick-link'] = array(
|
260 |
+
'type' => 'checkbox',
|
261 |
+
'label' => __( 'Live Editor Quick Link', 'siteorigin-panels' ),
|
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' ),
|
278 |
+
'description' => __( "Display a widget count in the admin lists of posts/pages where you're using Page Builder.", 'siteorigin-panels' ),
|
279 |
+
);
|
280 |
+
|
281 |
+
$fields['general']['fields']['parallax-motion'] = array(
|
282 |
+
'type' => 'float',
|
283 |
+
'label' => __( 'Limit Parallax Motion', 'siteorigin-panels' ),
|
284 |
+
'description' => __( 'How many pixels of scrolling result in a single pixel of parallax motion. 0 means automatic. Lower values give more noticeable effect.', 'siteorigin-panels' ),
|
285 |
+
);
|
286 |
+
|
287 |
+
$fields['general']['fields']['sidebars-emulator'] = array(
|
288 |
+
'type' => 'checkbox',
|
289 |
+
'label' => __( 'Sidebars Emulator', 'siteorigin-panels' ),
|
290 |
+
'description' => __( 'Page Builder will create an emulated sidebar, that contains all widgets in the page.', 'siteorigin-panels' ),
|
291 |
+
);
|
292 |
+
|
293 |
+
$fields['general']['fields']['display-teaser'] = array(
|
294 |
+
'type' => 'checkbox',
|
295 |
+
'label' => __('Upgrade Teaser', 'siteorigin-panels'),
|
296 |
+
'description' => sprintf(
|
297 |
+
__('Display the %sSiteOrigin Premium%s upgrade teaser in the Page Builder toolbar.', 'siteorigin-panels'),
|
298 |
+
'<a href="https://siteorigin.com/downloads/premium/" target="_blank" rel="noopener noreferrer">',
|
299 |
+
'</a>'
|
300 |
+
)
|
301 |
+
);
|
302 |
+
|
303 |
+
$fields['general']['fields']['load-on-attach'] = array(
|
304 |
+
'type' => 'checkbox',
|
305 |
+
'label' => __( 'Default To Page Builder Interface', 'siteorigin-panels' ),
|
306 |
+
'description' => sprintf(
|
307 |
+
__( '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.', 'siteorigin-panels' ),
|
308 |
+
'<strong>',
|
309 |
+
'</strong>'
|
310 |
+
)
|
311 |
+
);
|
312 |
+
|
313 |
+
$fields['general']['fields']['layout-block-default-mode'] = array(
|
314 |
+
'label' => __( 'Layout Block Default Mode', 'siteorigin-panels' ),
|
315 |
+
'type' => 'select',
|
316 |
+
'options' => array(
|
317 |
+
'edit' => __( 'Edit', 'siteorigin-panels' ),
|
318 |
+
'preview' => __( 'Preview', 'siteorigin-panels' ),
|
319 |
+
),
|
320 |
+
'description' => __( 'Whether to display layout blocks in edit mode or preview mode in the block editor.', 'siteorigin-panels' ),
|
321 |
+
);
|
322 |
+
|
323 |
+
// The widgets fields
|
324 |
+
|
325 |
+
$fields['widgets'] = array(
|
326 |
+
'title' => __( 'Widgets', 'siteorigin-panels' ),
|
327 |
+
'fields' => array(),
|
328 |
+
);
|
329 |
+
|
330 |
+
$fields['widgets']['fields']['title-html'] = array(
|
331 |
+
'type' => 'html',
|
332 |
+
'label' => __( 'Widget Title HTML', 'siteorigin-panels' ),
|
333 |
+
'description' => __( 'The HTML used for widget titles. {{title}} is replaced with the widget title.', 'siteorigin-panels' ),
|
334 |
+
);
|
335 |
+
|
336 |
+
$fields['widgets']['fields']['add-widget-class'] = array(
|
337 |
+
'type' => 'checkbox',
|
338 |
+
'label' => __( 'Add Widget Class', 'siteorigin-panels' ),
|
339 |
+
'description' => __( "Add the widget class to Page Builder widgets. Disable this if you're experiencing conflicts.", 'siteorigin-panels' ),
|
340 |
+
);
|
341 |
+
|
342 |
+
$fields['widgets']['fields']['bundled-widgets'] = array(
|
343 |
+
'type' => 'checkbox',
|
344 |
+
'label' => __( 'Legacy Bundled Widgets', 'siteorigin-panels' ),
|
345 |
+
'description' => __( 'Load legacy widgets from Page Builder 1.', 'siteorigin-panels' ),
|
346 |
+
);
|
347 |
+
|
348 |
+
$fields['widgets']['fields']['recommended-widgets'] = array(
|
349 |
+
'type' => 'checkbox',
|
350 |
+
'label' => __( 'Recommended Widgets', 'siteorigin-panels' ),
|
351 |
+
'description' => __( 'Display recommend widgets in Page Builder add widget dialog.', 'siteorigin-panels' ),
|
352 |
+
);
|
353 |
+
|
354 |
+
$fields['widgets']['fields']['instant-open-widgets'] = array(
|
355 |
+
'type' => 'checkbox',
|
356 |
+
'label' => __( 'Instant Open Widgets', 'siteorigin-panels' ),
|
357 |
+
'description' => __( 'Open a widget form as soon as its added to a page.', 'siteorigin-panels' ),
|
358 |
+
);
|
359 |
+
|
360 |
+
// The layout fields
|
361 |
+
|
362 |
+
$fields['layout'] = array(
|
363 |
+
'title' => __( 'Layout', 'siteorigin-panels' ),
|
364 |
+
'fields' => array(),
|
365 |
+
);
|
366 |
+
|
367 |
+
// The layout fields
|
368 |
+
|
369 |
+
$fields['layout']['fields']['responsive'] = array(
|
370 |
+
'type' => 'checkbox',
|
371 |
+
'label' => __( 'Responsive Layout', 'siteorigin-panels' ),
|
372 |
+
'description' => __( 'Collapse widgets, rows and columns on mobile devices.', 'siteorigin-panels' ),
|
373 |
+
);
|
374 |
+
|
375 |
+
$fields['layout']['fields']['tablet-layout'] = array(
|
376 |
+
'type' => 'checkbox',
|
377 |
+
'label' => __( 'Use Tablet Layout', 'siteorigin-panels' ),
|
378 |
+
'description' => __( 'Collapses columns differently on tablet devices.', 'siteorigin-panels' ),
|
379 |
+
);
|
380 |
+
|
381 |
+
$fields['layout']['fields']['legacy-layout'] = array(
|
382 |
+
'type' => 'select',
|
383 |
+
'options' => array(
|
384 |
+
'auto' => __( 'Detect older browsers', 'siteorigin-panels' ),
|
385 |
+
'never' => __( 'Never', 'siteorigin-panels' ),
|
386 |
+
'always' => __( 'Always', 'siteorigin-panels' ),
|
387 |
+
),
|
388 |
+
'label' => __( 'Use Legacy Layout Engine', 'siteorigin-panels' ),
|
389 |
+
'description' => __( 'The CSS and HTML uses floats instead of flexbox for compatibility with very old browsers.', 'siteorigin-panels' ),
|
390 |
+
);
|
391 |
+
|
392 |
+
$fields['layout']['fields']['tablet-width'] = array(
|
393 |
+
'type' => 'number',
|
394 |
+
'unit' => 'px',
|
395 |
+
'label' => __( 'Tablet Width', 'siteorigin-panels' ),
|
396 |
+
'description' => __( 'Device width, in pixels, to collapse into a tablet view .', 'siteorigin-panels' ),
|
397 |
+
);
|
398 |
+
|
399 |
+
$fields['layout']['fields']['mobile-width'] = array(
|
400 |
+
'type' => 'number',
|
401 |
+
'unit' => 'px',
|
402 |
+
'label' => __( 'Mobile Width', 'siteorigin-panels' ),
|
403 |
+
'description' => __( 'Device width, in pixels, to collapse into a mobile view .', 'siteorigin-panels' ),
|
404 |
+
);
|
405 |
+
|
406 |
+
$fields['layout']['fields']['margin-bottom'] = array(
|
407 |
+
'type' => 'number',
|
408 |
+
'unit' => 'px',
|
409 |
+
'label' => __( 'Row/Widget Bottom Margin', 'siteorigin-panels' ),
|
410 |
+
'description' => __( 'Default margin below rows and widgets.', 'siteorigin-panels' ),
|
411 |
+
);
|
412 |
+
|
413 |
+
$fields['layout']['fields']['margin-bottom-last-row'] = array(
|
414 |
+
'type' => 'checkbox',
|
415 |
+
'label' => __( 'Last Row With Margin', 'siteorigin-panels' ),
|
416 |
+
'description' => __( 'Allow margin in last row.', 'siteorigin-panels' ),
|
417 |
+
);
|
418 |
+
|
419 |
+
$fields['layout']['fields']['margin-sides'] = array(
|
420 |
+
'type' => 'number',
|
421 |
+
'unit' => 'px',
|
422 |
+
'label' => __( 'Row Gutter', 'siteorigin-panels' ),
|
423 |
+
'description' => __( 'Default spacing between columns in each row.', 'siteorigin-panels' ),
|
424 |
+
'keywords' => 'margin',
|
425 |
+
);
|
426 |
+
|
427 |
+
$fields['layout']['fields']['full-width-container'] = array(
|
428 |
+
'type' => 'text',
|
429 |
+
'label' => __( 'Full Width Container', 'siteorigin-panels' ),
|
430 |
+
'description' => __( 'The container used for the full width layout.', 'siteorigin-panels' ),
|
431 |
+
'keywords' => 'full width, container, stretch',
|
432 |
+
);
|
433 |
+
|
434 |
+
// The content fields
|
435 |
+
|
436 |
+
$fields['content'] = array(
|
437 |
+
'title' => __( 'Content', 'siteorigin-panels' ),
|
438 |
+
'fields' => array(),
|
439 |
+
);
|
440 |
+
|
441 |
+
$fields['content']['fields']['copy-content'] = array(
|
442 |
+
'type' => 'checkbox',
|
443 |
+
'label' => __( 'Copy Content', 'siteorigin-panels' ),
|
444 |
+
'description' => __( 'Copy content from Page Builder to post content.', 'siteorigin-panels' ),
|
445 |
+
);
|
446 |
+
|
447 |
+
$fields['content']['fields']['copy-styles'] = array(
|
448 |
+
'type' => 'checkbox',
|
449 |
+
'label' => __( 'Copy Styles', 'siteorigin-panels' ),
|
450 |
+
'description' => __( 'Include styles into your Post Content. This keeps page layouts, even when Page Builder is deactivated.', 'siteorigin-panels' ),
|
451 |
+
);
|
452 |
+
|
453 |
+
return $fields;
|
454 |
+
}
|
455 |
+
|
456 |
+
/**
|
457 |
+
* Display a settings field
|
458 |
+
*
|
459 |
+
* @param $field_id
|
460 |
+
* @param $field
|
461 |
+
*/
|
462 |
+
function display_field( $field_id, $field ) {
|
463 |
+
$value = siteorigin_panels_setting( $field_id );
|
464 |
+
|
465 |
+
$field_name = 'panels_setting[' . $field_id . ']';
|
466 |
+
|
467 |
+
switch ( $field['type'] ) {
|
468 |
+
case 'text':
|
469 |
+
case 'float':
|
470 |
+
?><input name="<?php echo esc_attr( $field_name ) ?>"
|
471 |
+
class="panels-setting-<?php echo esc_attr( $field['type'] ) ?>" type="text"
|
472 |
+
value="<?php echo esc_attr( $value ) ?>" /> <?php
|
473 |
+
break;
|
474 |
+
|
475 |
+
case 'password':
|
476 |
+
?><input name="<?php echo esc_attr( $field_name ) ?>"
|
477 |
+
class="panels-setting-<?php echo esc_attr( $field['type'] ) ?>" type="password"
|
478 |
+
value="<?php echo esc_attr( $value ) ?>" /> <?php
|
479 |
+
break;
|
480 |
+
|
481 |
+
case 'number':
|
482 |
+
?>
|
483 |
+
<input name="<?php echo esc_attr( $field_name ) ?>" type="number"
|
484 |
+
class="panels-setting-<?php echo esc_attr( $field['type'] ) ?>"
|
485 |
+
value="<?php echo esc_attr( $value ) ?>"/>
|
486 |
+
<?php
|
487 |
+
if ( ! empty( $field['unit'] ) ) {
|
488 |
+
echo esc_html( $field['unit'] );
|
489 |
+
}
|
490 |
+
break;
|
491 |
+
|
492 |
+
case 'html':
|
493 |
+
?><textarea name="<?php echo esc_attr( $field_name ) ?>"
|
494 |
+
class="panels-setting-<?php echo esc_attr( $field['type'] ) ?> widefat"
|
495 |
+
rows="<?php echo ! empty( $field['rows'] ) ? intval( $field['rows'] ) : 2 ?>"><?php echo esc_textarea( $value ) ?></textarea> <?php
|
496 |
+
break;
|
497 |
+
|
498 |
+
case 'checkbox':
|
499 |
+
?>
|
500 |
+
<label class="widefat">
|
501 |
+
<input name="<?php echo esc_attr( $field_name ) ?>"
|
502 |
+
type="checkbox" <?php checked( ! empty( $value ) ) ?> />
|
503 |
+
<?php echo ! empty( $field['checkbox_text'] ) ? esc_html( $field['checkbox_text'] ) : __( 'Enabled', 'siteorigin-panels' ) ?>
|
504 |
+
</label>
|
505 |
+
<?php
|
506 |
+
break;
|
507 |
+
|
508 |
+
case 'select':
|
509 |
+
?>
|
510 |
+
<select name="<?php echo esc_attr( $field_name ) ?>">
|
511 |
+
<?php foreach ( $field['options'] as $option_id => $option ) : ?>
|
512 |
+
<option
|
513 |
+
value="<?php echo esc_attr( $option_id ) ?>" <?php selected( $option_id, $value ) ?>><?php echo esc_html( $option ) ?></option>
|
514 |
+
<?php endforeach; ?>
|
515 |
+
</select>
|
516 |
+
<?php
|
517 |
+
break;
|
518 |
+
|
519 |
+
case 'select_multi':
|
520 |
+
foreach ( $field['options'] as $option_id => $option ) {
|
521 |
+
?>
|
522 |
+
<label class="widefat">
|
523 |
+
<input name="<?php echo esc_attr( $field_name ) ?>[<?php echo esc_attr( $option_id ) ?>]"
|
524 |
+
type="checkbox" <?php checked( in_array( $option_id, $value ) ) ?> />
|
525 |
+
<?php echo esc_html( $option ) ?>
|
526 |
+
</label>
|
527 |
+
<?php
|
528 |
+
}
|
529 |
+
|
530 |
+
break;
|
531 |
+
}
|
532 |
+
}
|
533 |
+
|
534 |
+
/**
|
535 |
+
* Save the Page Builder settings.
|
536 |
+
*/
|
537 |
+
function save_settings() {
|
538 |
+
$screen = get_current_screen();
|
539 |
+
if ( $screen->base != 'settings_page_siteorigin_panels' ) {
|
540 |
+
return;
|
541 |
+
}
|
542 |
+
|
543 |
+
if ( ! current_user_can( 'manage_options' ) ) {
|
544 |
+
return;
|
545 |
+
}
|
546 |
+
if ( empty( $_POST['_wpnonce'] ) || ! wp_verify_nonce( $_POST['_wpnonce'], 'panels-settings' ) ) {
|
547 |
+
return;
|
548 |
+
}
|
549 |
+
if ( empty( $_POST['panels_setting'] ) ) {
|
550 |
+
return;
|
551 |
+
}
|
552 |
+
|
553 |
+
$values = array();
|
554 |
+
$post = stripslashes_deep( $_POST['panels_setting'] );
|
555 |
+
$settings_fields = $this->fields = apply_filters( 'siteorigin_panels_settings_fields', array() );
|
556 |
+
|
557 |
+
if ( empty( $settings_fields ) ) {
|
558 |
+
return;
|
559 |
+
}
|
560 |
+
|
561 |
+
foreach ( $settings_fields as $section_id => $section ) {
|
562 |
+
if ( empty( $section['fields'] ) ) {
|
563 |
+
continue;
|
564 |
+
}
|
565 |
+
|
566 |
+
foreach ( $section['fields'] as $field_id => $field ) {
|
567 |
+
// Sanitize the fields
|
568 |
+
switch ( $field['type'] ) {
|
569 |
+
case 'text' :
|
570 |
+
$values[ $field_id ] = ! empty( $post[ $field_id ] ) ? sanitize_text_field( $post[ $field_id ] ) : '';
|
571 |
+
break;
|
572 |
+
|
573 |
+
case 'number':
|
574 |
+
if ( $post[ $field_id ] != '' ) {
|
575 |
+
$values[ $field_id ] = ! empty( $post[ $field_id ] ) ? intval( $post[ $field_id ] ) : 0;
|
576 |
+
} else {
|
577 |
+
$values[ $field_id ] = '';
|
578 |
+
}
|
579 |
+
break;
|
580 |
+
|
581 |
+
case 'float':
|
582 |
+
if ( $post[ $field_id ] != '' ) {
|
583 |
+
$values[ $field_id ] = ! empty( $post[ $field_id ] ) ? floatval( $post[ $field_id ] ) : 0;
|
584 |
+
} else {
|
585 |
+
$values[ $field_id ] = '';
|
586 |
+
}
|
587 |
+
break;
|
588 |
+
|
589 |
+
case 'html':
|
590 |
+
$values[ $field_id ] = ! empty( $post[ $field_id ] ) ? $post[ $field_id ] : '';
|
591 |
+
$values[ $field_id ] = wp_kses_post( $values[ $field_id ] );
|
592 |
+
$values[ $field_id ] = force_balance_tags( $values[ $field_id ] );
|
593 |
+
break;
|
594 |
+
|
595 |
+
case 'checkbox':
|
596 |
+
$values[ $field_id ] = ! empty( $post[ $field_id ] );
|
597 |
+
break;
|
598 |
+
|
599 |
+
case 'select':
|
600 |
+
$values[ $field_id ] = ! empty( $post[ $field_id ] ) ? $post[ $field_id ] : '';
|
601 |
+
if ( ! in_array( $values[ $field_id ], array_keys( $field['options'] ) ) ) {
|
602 |
+
unset( $values[ $field_id ] );
|
603 |
+
}
|
604 |
+
break;
|
605 |
+
|
606 |
+
case 'select_multi':
|
607 |
+
$values[ $field_id ] = array();
|
608 |
+
$multi_values = array();
|
609 |
+
foreach ( $field['options'] as $option_id => $option ) {
|
610 |
+
$multi_values[ $option_id ] = ! empty( $post[ $field_id ][ $option_id ] );
|
611 |
+
}
|
612 |
+
foreach ( $multi_values as $k => $v ) {
|
613 |
+
if ( $v ) {
|
614 |
+
$values[ $field_id ][] = $k;
|
615 |
+
}
|
616 |
+
}
|
617 |
+
|
618 |
+
break;
|
619 |
+
}
|
620 |
+
}
|
621 |
+
}
|
622 |
+
|
623 |
+
// Don't let mobile width go below 320
|
624 |
+
$values[ 'mobile-width' ] = max( $values[ 'mobile-width' ], 320 );
|
625 |
+
|
626 |
+
// Save the values to the database
|
627 |
+
update_option( 'siteorigin_panels_settings', $values );
|
628 |
+
do_action( 'siteorigin_panels_save_settings', $values );
|
629 |
+
$this->settings = wp_parse_args( $values, $this->settings );
|
630 |
+
$this->settings_saved = true;
|
631 |
+
}
|
632 |
+
|
633 |
+
/**
|
634 |
+
* Get a post type array
|
635 |
+
*
|
636 |
+
* @return array
|
637 |
+
*/
|
638 |
+
function get_post_types() {
|
639 |
+
$post_types = get_post_types( array( '_builtin' => false ) );
|
640 |
+
|
641 |
+
$types = array(
|
642 |
+
'page' => 'page',
|
643 |
+
'post' => 'post'
|
644 |
+
);
|
645 |
+
|
646 |
+
// Don't use `array_merge` here as it will break things if a post type has a numeric slug.
|
647 |
+
foreach ( $post_types as $key => $value ) {
|
648 |
+
$types[ $key ] = $value;
|
649 |
+
}
|
650 |
+
|
651 |
+
// These are post types we know we don't want to show Page Builder on
|
652 |
+
unset( $types['ml-slider'] );
|
653 |
+
|
654 |
+
foreach ( $types as $type_id => $type ) {
|
655 |
+
$type_object = get_post_type_object( $type_id );
|
656 |
+
|
657 |
+
if ( ! $type_object->show_ui ) {
|
658 |
+
unset( $types[ $type_id ] );
|
659 |
+
continue;
|
660 |
+
}
|
661 |
+
|
662 |
+
$types[ $type_id ] = $type_object->label;
|
663 |
+
}
|
664 |
+
|
665 |
+
return apply_filters( 'siteorigin_panels_settings_enabled_post_types', $types );
|
666 |
+
}
|
667 |
+
|
668 |
+
}
|
inc/sidebars-emulator.php
CHANGED
@@ -1,224 +1,224 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class SiteOrigin_Panels_Sidebars_Emulator {
|
4 |
-
|
5 |
-
private $all_posts_widgets;
|
6 |
-
|
7 |
-
function __construct() {
|
8 |
-
$this->all_posts_widgets = array();
|
9 |
-
add_action( 'widgets_init', array( $this, 'register_widgets' ) );
|
10 |
-
add_filter( 'sidebars_widgets', array( $this, 'add_widgets_to_sidebars' ) );
|
11 |
-
}
|
12 |
-
|
13 |
-
/**
|
14 |
-
* Get the single instance.
|
15 |
-
*
|
16 |
-
* @return SiteOrigin_Panels_Sidebars_Emulator
|
17 |
-
*/
|
18 |
-
static function single() {
|
19 |
-
static $single;
|
20 |
-
return empty( $single ) ? $single = new self() : $single;
|
21 |
-
}
|
22 |
-
|
23 |
-
/**
|
24 |
-
* @param string $name The name of the function
|
25 |
-
* @param array $args
|
26 |
-
*
|
27 |
-
* @return mixed
|
28 |
-
*/
|
29 |
-
function __call( $name, $args ) {
|
30 |
-
|
31 |
-
// Check if this is a filter option call
|
32 |
-
preg_match( '/filter_option_widget_(.+)/', $name, $opt_matches );
|
33 |
-
if ( ! empty( $opt_matches ) && count( $opt_matches ) > 1 ) {
|
34 |
-
$opt_name = $opt_matches[1];
|
35 |
-
global $wp_widget_factory;
|
36 |
-
foreach ( $wp_widget_factory->widgets as $widget ) {
|
37 |
-
$widget_class = get_class( $widget );
|
38 |
-
if ( $widget->id_base != $opt_name ) {
|
39 |
-
continue;
|
40 |
-
}
|
41 |
-
|
42 |
-
foreach ( $this->all_posts_widgets as $post_widgets ) {
|
43 |
-
foreach ( $post_widgets as $widget_instance ) {
|
44 |
-
if ( empty( $widget_instance['panels_info']['class'] ) ) {
|
45 |
-
continue;
|
46 |
-
}
|
47 |
-
|
48 |
-
$instance_class = $widget_instance['panels_info']['class'];
|
49 |
-
$sidebar_id = $this->get_sidebar_id( $widget_instance );
|
50 |
-
if ( $instance_class == $widget_class && ! empty( $sidebar_id ) ) {
|
51 |
-
//The option value uses only the widget id number as keys
|
52 |
-
preg_match( '/-([0-9]+$)/', $sidebar_id, $num_match );
|
53 |
-
$args[0][ $num_match[1] ] = $widget_instance;
|
54 |
-
}
|
55 |
-
}
|
56 |
-
}
|
57 |
-
}
|
58 |
-
|
59 |
-
return $args[0];
|
60 |
-
}
|
61 |
-
|
62 |
-
}
|
63 |
-
|
64 |
-
/**
|
65 |
-
* Register all the current widgets so we can filter the get_option('widget_...') values to add instances
|
66 |
-
*/
|
67 |
-
function register_widgets() {
|
68 |
-
$current_url = add_query_arg( false, false );
|
69 |
-
$cache_key = md5( $current_url );
|
70 |
-
|
71 |
-
// Get the ID of the current post
|
72 |
-
$post_id = wp_cache_get( $cache_key, 'siteorigin_url_to_postid' );
|
73 |
-
if ( false === $post_id ) {
|
74 |
-
$post_id = url_to_postid( $current_url );
|
75 |
-
wp_cache_set( $cache_key, $post_id, 'siteorigin_url_to_postid', 3 * HOUR_IN_SECONDS );
|
76 |
-
}
|
77 |
-
|
78 |
-
if ( empty( $post_id ) ) {
|
79 |
-
// Maybe this is the home page
|
80 |
-
$current_url_path = parse_url( $current_url, PHP_URL_PATH );
|
81 |
-
$home_url_path = parse_url( trailingslashit( home_url() ), PHP_URL_PATH );
|
82 |
-
|
83 |
-
if ( $current_url_path === $home_url_path && get_option( 'page_on_front' ) != 0 ) {
|
84 |
-
$post_id = absint( get_option( 'page_on_front' ) );
|
85 |
-
}
|
86 |
-
}
|
87 |
-
|
88 |
-
if ( empty( $post_id ) ) {
|
89 |
-
return;
|
90 |
-
}
|
91 |
-
|
92 |
-
$panels_data = get_post_meta( $post_id, 'panels_data', true );
|
93 |
-
$widget_option_names = $this->get_widget_option_names( $post_id, $panels_data );
|
94 |
-
$widget_option_names = array_unique( $widget_option_names );
|
95 |
-
|
96 |
-
foreach ( $widget_option_names as $widget_option_name ) {
|
97 |
-
add_filter( 'option_' . $widget_option_name, array( $this, 'filter_option_' . $widget_option_name ) );
|
98 |
-
}
|
99 |
-
}
|
100 |
-
|
101 |
-
/**
|
102 |
-
* Recursively get all widget option names from $panels_data and store widget instances in $this->all_posts_widgets.
|
103 |
-
*
|
104 |
-
* @param int|string $post_id
|
105 |
-
* @param array $panels_data
|
106 |
-
*
|
107 |
-
* @return array A list of widget option names from the post and its Layout Builder widgets.
|
108 |
-
*/
|
109 |
-
private function get_widget_option_names( $post_id, $panels_data ) {
|
110 |
-
if( empty( $panels_data ) || empty( $panels_data[ 'widgets' ] ) ) {
|
111 |
-
return array();
|
112 |
-
}
|
113 |
-
|
114 |
-
if( empty( $this->all_posts_widgets[ $post_id ] ) ) {
|
115 |
-
$this->all_posts_widgets[ $post_id ] = array();
|
116 |
-
}
|
117 |
-
|
118 |
-
$widget_option_names = array();
|
119 |
-
$widgets = $panels_data['widgets'];
|
120 |
-
foreach ( $widgets as $i => $widget_instance ) {
|
121 |
-
if ( empty( $widget_instance['panels_info']['class'] ) ) {
|
122 |
-
continue;
|
123 |
-
}
|
124 |
-
|
125 |
-
if( $widget_instance['panels_info']['class'] === 'SiteOrigin_Panels_Widgets_Layout' ) {
|
126 |
-
// Add the widget option names from the layout widget
|
127 |
-
$widget_option_names = array_merge( $widget_option_names, $this->get_widget_option_names( $post_id, $widget_instance[ 'panels_data' ] ) );
|
128 |
-
}
|
129 |
-
$sidebar_id = $this->get_sidebar_id( $widget_instance );
|
130 |
-
if ( ! empty( $sidebar_id ) ) {
|
131 |
-
$widget_option_names[] = $widget_instance['option_name'];
|
132 |
-
}
|
133 |
-
$this->all_posts_widgets[ $post_id ][] = $widget_instance;
|
134 |
-
}
|
135 |
-
|
136 |
-
return $widget_option_names;
|
137 |
-
}
|
138 |
-
|
139 |
-
/**
|
140 |
-
* This should be called when a post is saved to set ids required for `is_active_widget` checks. It's necessary to
|
141 |
-
* do this separately for widgets that call `is_active_widget` in their constructors, e.g. some of Jetpack's widgets
|
142 |
-
* like Twitter Timeline, Milestone etc.
|
143 |
-
*
|
144 |
-
* @param $widgets array The widgets in the layout from $panels_data for which to generate ids.
|
145 |
-
* @param $post_id int The post id which is used to derive ids.
|
146 |
-
* @param int $start This keeps track of recursive depth.
|
147 |
-
*
|
148 |
-
* @return array The widgets array containing updated widgets.
|
149 |
-
*/
|
150 |
-
public function generate_sidebar_widget_ids( $widgets, $post_id, $start = 1 ) {
|
151 |
-
foreach ( $widgets as $i => &$widget_instance ) {
|
152 |
-
$id_val = $post_id . strval( ( 10000 * $start ) + intval( $i ) );
|
153 |
-
$widget_class = $widget_instance['panels_info']['class'];
|
154 |
-
|
155 |
-
|
156 |
-
if( $widget_instance['panels_info']['class'] === 'SiteOrigin_Panels_Widgets_Layout' ) {
|
157 |
-
if ( ! empty( $widget_instance['panels_data']['widgets'] ) ) {
|
158 |
-
// Recursively set widget ids in layout widgets.
|
159 |
-
$widget_instance[ 'panels_data' ]['widgets'] = $this->generate_sidebar_widget_ids( $widget_instance[ 'panels_data' ]['widgets'], $post_id, ++$start );
|
160 |
-
}
|
161 |
-
}
|
162 |
-
|
163 |
-
/** @var WP_Widget $widget */
|
164 |
-
$widget = SiteOrigin_Panels::get_widget_instance( $widget_class );
|
165 |
-
if ( ! empty( $widget ) ) {
|
166 |
-
$widget_instance['so_sidebar_emulator_id'] = $widget->id_base . '-' . $id_val;
|
167 |
-
$widget_instance['option_name'] = $widget->option_name;
|
168 |
-
}
|
169 |
-
}
|
170 |
-
|
171 |
-
return $widgets;
|
172 |
-
}
|
173 |
-
|
174 |
-
/**
|
175 |
-
* Add a sidebar for SiteOrigin Panels widgets so they are correctly detected by is_active_widget
|
176 |
-
*
|
177 |
-
* @param $sidebars_widgets
|
178 |
-
*
|
179 |
-
* @return array
|
180 |
-
*/
|
181 |
-
function add_widgets_to_sidebars( $sidebars_widgets ) {
|
182 |
-
if ( empty( $this->all_posts_widgets ) ) {
|
183 |
-
return $sidebars_widgets;
|
184 |
-
}
|
185 |
-
|
186 |
-
foreach ( array_keys( $this->all_posts_widgets ) as $post_id ) {
|
187 |
-
$post_widgets = $this->all_posts_widgets[ $post_id ];
|
188 |
-
foreach ( $post_widgets as $widget_instance ) {
|
189 |
-
$sidebar_id = $this->get_sidebar_id( $widget_instance );
|
190 |
-
if ( empty( $sidebar_id ) ) {
|
191 |
-
continue;
|
192 |
-
}
|
193 |
-
//Sidebars widgets and the global $wp_registered widgets use full widget ids as keys
|
194 |
-
$siteorigin_panels_widget_ids[] = $sidebar_id;
|
195 |
-
}
|
196 |
-
if ( ! empty( $siteorigin_panels_widget_ids ) ) {
|
197 |
-
$sidebars_widgets[ 'sidebar-siteorigin_panels-post-' . $post_id ] = $siteorigin_panels_widget_ids;
|
198 |
-
}
|
199 |
-
}
|
200 |
-
|
201 |
-
return $sidebars_widgets;
|
202 |
-
}
|
203 |
-
|
204 |
-
/**
|
205 |
-
* The 'id' key was changed to 'so_sidebar_emulator_id' to try avoid conflicts with widgets that already had
|
206 |
-
* an 'id' key.
|
207 |
-
*
|
208 |
-
* @param $instance
|
209 |
-
*
|
210 |
-
* @return null
|
211 |
-
*/
|
212 |
-
private function get_sidebar_id( $instance ) {
|
213 |
-
$sidebar_id = null;
|
214 |
-
if ( ! empty( $instance['id'] ) ) {
|
215 |
-
$sidebar_id = $instance['id'];
|
216 |
-
} else if ( ! empty( $instance['so_sidebar_emulator_id'] ) ) {
|
217 |
-
$sidebar_id = $instance['so_sidebar_emulator_id'];
|
218 |
-
}
|
219 |
-
|
220 |
-
return $sidebar_id;
|
221 |
-
}
|
222 |
-
}
|
223 |
-
|
224 |
-
SiteOrigin_Panels_Sidebars_Emulator::single();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class SiteOrigin_Panels_Sidebars_Emulator {
|
4 |
+
|
5 |
+
private $all_posts_widgets;
|
6 |
+
|
7 |
+
function __construct() {
|
8 |
+
$this->all_posts_widgets = array();
|
9 |
+
add_action( 'widgets_init', array( $this, 'register_widgets' ) );
|
10 |
+
add_filter( 'sidebars_widgets', array( $this, 'add_widgets_to_sidebars' ) );
|
11 |
+
}
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Get the single instance.
|
15 |
+
*
|
16 |
+
* @return SiteOrigin_Panels_Sidebars_Emulator
|
17 |
+
*/
|
18 |
+
static function single() {
|
19 |
+
static $single;
|
20 |
+
return empty( $single ) ? $single = new self() : $single;
|
21 |
+
}
|
22 |
+
|
23 |
+
/**
|
24 |
+
* @param string $name The name of the function
|
25 |
+
* @param array $args
|
26 |
+
*
|
27 |
+
* @return mixed
|
28 |
+
*/
|
29 |
+
function __call( $name, $args ) {
|
30 |
+
|
31 |
+
// Check if this is a filter option call
|
32 |
+
preg_match( '/filter_option_widget_(.+)/', $name, $opt_matches );
|
33 |
+
if ( ! empty( $opt_matches ) && count( $opt_matches ) > 1 ) {
|
34 |
+
$opt_name = $opt_matches[1];
|
35 |
+
global $wp_widget_factory;
|
36 |
+
foreach ( $wp_widget_factory->widgets as $widget ) {
|
37 |
+
$widget_class = get_class( $widget );
|
38 |
+
if ( $widget->id_base != $opt_name ) {
|
39 |
+
continue;
|
40 |
+
}
|
41 |
+
|
42 |
+
foreach ( $this->all_posts_widgets as $post_widgets ) {
|
43 |
+
foreach ( $post_widgets as $widget_instance ) {
|
44 |
+
if ( empty( $widget_instance['panels_info']['class'] ) ) {
|
45 |
+
continue;
|
46 |
+
}
|
47 |
+
|
48 |
+
$instance_class = $widget_instance['panels_info']['class'];
|
49 |
+
$sidebar_id = $this->get_sidebar_id( $widget_instance );
|
50 |
+
if ( $instance_class == $widget_class && ! empty( $sidebar_id ) ) {
|
51 |
+
//The option value uses only the widget id number as keys
|
52 |
+
preg_match( '/-([0-9]+$)/', $sidebar_id, $num_match );
|
53 |
+
$args[0][ $num_match[1] ] = $widget_instance;
|
54 |
+
}
|
55 |
+
}
|
56 |
+
}
|
57 |
+
}
|
58 |
+
|
59 |
+
return $args[0];
|
60 |
+
}
|
61 |
+
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Register all the current widgets so we can filter the get_option('widget_...') values to add instances
|
66 |
+
*/
|
67 |
+
function register_widgets() {
|
68 |
+
$current_url = add_query_arg( false, false );
|
69 |
+
$cache_key = md5( $current_url );
|
70 |
+
|
71 |
+
// Get the ID of the current post
|
72 |
+
$post_id = wp_cache_get( $cache_key, 'siteorigin_url_to_postid' );
|
73 |
+
if ( false === $post_id ) {
|
74 |
+
$post_id = url_to_postid( $current_url );
|
75 |
+
wp_cache_set( $cache_key, $post_id, 'siteorigin_url_to_postid', 3 * HOUR_IN_SECONDS );
|
76 |
+
}
|
77 |
+
|
78 |
+
if ( empty( $post_id ) ) {
|
79 |
+
// Maybe this is the home page
|
80 |
+
$current_url_path = parse_url( $current_url, PHP_URL_PATH );
|
81 |
+
$home_url_path = parse_url( trailingslashit( home_url() ), PHP_URL_PATH );
|
82 |
+
|
83 |
+
if ( $current_url_path === $home_url_path && get_option( 'page_on_front' ) != 0 ) {
|
84 |
+
$post_id = absint( get_option( 'page_on_front' ) );
|
85 |
+
}
|
86 |
+
}
|
87 |
+
|
88 |
+
if ( empty( $post_id ) ) {
|
89 |
+
return;
|
90 |
+
}
|
91 |
+
|
92 |
+
$panels_data = get_post_meta( $post_id, 'panels_data', true );
|
93 |
+
$widget_option_names = $this->get_widget_option_names( $post_id, $panels_data );
|
94 |
+
$widget_option_names = array_unique( $widget_option_names );
|
95 |
+
|
96 |
+
foreach ( $widget_option_names as $widget_option_name ) {
|
97 |
+
add_filter( 'option_' . $widget_option_name, array( $this, 'filter_option_' . $widget_option_name ) );
|
98 |
+
}
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Recursively get all widget option names from $panels_data and store widget instances in $this->all_posts_widgets.
|
103 |
+
*
|
104 |
+
* @param int|string $post_id
|
105 |
+
* @param array $panels_data
|
106 |
+
*
|
107 |
+
* @return array A list of widget option names from the post and its Layout Builder widgets.
|
108 |
+
*/
|
109 |
+
private function get_widget_option_names( $post_id, $panels_data ) {
|
110 |
+
if( empty( $panels_data ) || empty( $panels_data[ 'widgets' ] ) ) {
|
111 |
+
return array();
|
112 |
+
}
|
113 |
+
|
114 |
+
if( empty( $this->all_posts_widgets[ $post_id ] ) ) {
|
115 |
+
$this->all_posts_widgets[ $post_id ] = array();
|
116 |
+
}
|
117 |
+
|
118 |
+
$widget_option_names = array();
|
119 |
+
$widgets = $panels_data['widgets'];
|
120 |
+
foreach ( $widgets as $i => $widget_instance ) {
|
121 |
+
if ( empty( $widget_instance['panels_info']['class'] ) ) {
|
122 |
+
continue;
|
123 |
+
}
|
124 |
+
|
125 |
+
if( $widget_instance['panels_info']['class'] === 'SiteOrigin_Panels_Widgets_Layout' ) {
|
126 |
+
// Add the widget option names from the layout widget
|
127 |
+
$widget_option_names = array_merge( $widget_option_names, $this->get_widget_option_names( $post_id, $widget_instance[ 'panels_data' ] ) );
|
128 |
+
}
|
129 |
+
$sidebar_id = $this->get_sidebar_id( $widget_instance );
|
130 |
+
if ( ! empty( $sidebar_id ) ) {
|
131 |
+
$widget_option_names[] = $widget_instance['option_name'];
|
132 |
+
}
|
133 |
+
$this->all_posts_widgets[ $post_id ][] = $widget_instance;
|
134 |
+
}
|
135 |
+
|
136 |
+
return $widget_option_names;
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* This should be called when a post is saved to set ids required for `is_active_widget` checks. It's necessary to
|
141 |
+
* do this separately for widgets that call `is_active_widget` in their constructors, e.g. some of Jetpack's widgets
|
142 |
+
* like Twitter Timeline, Milestone etc.
|
143 |
+
*
|
144 |
+
* @param $widgets array The widgets in the layout from $panels_data for which to generate ids.
|
145 |
+
* @param $post_id int The post id which is used to derive ids.
|
146 |
+
* @param int $start This keeps track of recursive depth.
|
147 |
+
*
|
148 |
+
* @return array The widgets array containing updated widgets.
|
149 |
+
*/
|
150 |
+
public function generate_sidebar_widget_ids( $widgets, $post_id, $start = 1 ) {
|
151 |
+
foreach ( $widgets as $i => &$widget_instance ) {
|
152 |
+
$id_val = $post_id . strval( ( 10000 * $start ) + intval( $i ) );
|
153 |
+
$widget_class = $widget_instance['panels_info']['class'];
|
154 |
+
|
155 |
+
|
156 |
+
if( $widget_instance['panels_info']['class'] === 'SiteOrigin_Panels_Widgets_Layout' ) {
|
157 |
+
if ( ! empty( $widget_instance['panels_data']['widgets'] ) ) {
|
158 |
+
// Recursively set widget ids in layout widgets.
|
159 |
+
$widget_instance[ 'panels_data' ]['widgets'] = $this->generate_sidebar_widget_ids( $widget_instance[ 'panels_data' ]['widgets'], $post_id, ++$start );
|
160 |
+
}
|
161 |
+
}
|
162 |
+
|
163 |
+
/** @var WP_Widget $widget */
|
164 |
+
$widget = SiteOrigin_Panels::get_widget_instance( $widget_class );
|
165 |
+
if ( ! empty( $widget ) ) {
|
166 |
+
$widget_instance['so_sidebar_emulator_id'] = $widget->id_base . '-' . $id_val;
|
167 |
+
$widget_instance['option_name'] = $widget->option_name;
|
168 |
+
}
|
169 |
+
}
|
170 |
+
|
171 |
+
return $widgets;
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Add a sidebar for SiteOrigin Panels widgets so they are correctly detected by is_active_widget
|
176 |
+
*
|
177 |
+
* @param $sidebars_widgets
|
178 |
+
*
|
179 |
+
* @return array
|
180 |
+
*/
|
181 |
+
function add_widgets_to_sidebars( $sidebars_widgets ) {
|
182 |
+
if ( empty( $this->all_posts_widgets ) ) {
|
183 |
+
return $sidebars_widgets;
|
184 |
+
}
|
185 |
+
|
186 |
+
foreach ( array_keys( $this->all_posts_widgets ) as $post_id ) {
|
187 |
+
$post_widgets = $this->all_posts_widgets[ $post_id ];
|
188 |
+
foreach ( $post_widgets as $widget_instance ) {
|
189 |
+
$sidebar_id = $this->get_sidebar_id( $widget_instance );
|
190 |
+
if ( empty( $sidebar_id ) ) {
|
191 |
+
continue;
|
192 |
+
}
|
193 |
+
//Sidebars widgets and the global $wp_registered widgets use full widget ids as keys
|
194 |
+
$siteorigin_panels_widget_ids[] = $sidebar_id;
|
195 |
+
}
|
196 |
+
if ( ! empty( $siteorigin_panels_widget_ids ) ) {
|
197 |
+
$sidebars_widgets[ 'sidebar-siteorigin_panels-post-' . $post_id ] = $siteorigin_panels_widget_ids;
|
198 |
+
}
|
199 |
+
}
|
200 |
+
|
201 |
+
return $sidebars_widgets;
|
202 |
+
}
|
203 |
+
|
204 |
+
/**
|
205 |
+
* The 'id' key was changed to 'so_sidebar_emulator_id' to try avoid conflicts with widgets that already had
|
206 |
+
* an 'id' key.
|
207 |
+
*
|
208 |
+
* @param $instance
|
209 |
+
*
|
210 |
+
* @return null
|
211 |
+
*/
|
212 |
+
private function get_sidebar_id( $instance ) {
|
213 |
+
$sidebar_id = null;
|
214 |
+
if ( ! empty( $instance['id'] ) ) {
|
215 |
+
$sidebar_id = $instance['id'];
|
216 |
+
} else if ( ! empty( $instance['so_sidebar_emulator_id'] ) ) {
|
217 |
+
$sidebar_id = $instance['so_sidebar_emulator_id'];
|
218 |
+
}
|
219 |
+
|
220 |
+
return $sidebar_id;
|
221 |
+
}
|
222 |
+
}
|
223 |
+
|
224 |
+
SiteOrigin_Panels_Sidebars_Emulator::single();
|
inc/styles-admin.php
CHANGED
@@ -1,513 +1,517 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class SiteOrigin_Panels_Styles_Admin {
|
4 |
-
|
5 |
-
function __construct() {
|
6 |
-
add_action( 'wp_ajax_so_panels_style_form', array( $this, 'action_style_form' ) );
|
7 |
-
|
8 |
-
add_filter( 'siteorigin_panels_data', array( $this, 'convert_data' ) );
|
9 |
-
add_filter( 'siteorigin_panels_prebuilt_layout', array( $this, 'convert_data' ) );
|
10 |
-
}
|
11 |
-
|
12 |
-
public static function single() {
|
13 |
-
static $single;
|
14 |
-
return empty( $single ) ? $single = new self() : $single;
|
15 |
-
}
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Admin action for handling fetching the style fields
|
19 |
-
*/
|
20 |
-
function action_style_form() {
|
21 |
-
if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
|
22 |
-
wp_die(
|
23 |
-
__( 'The supplied nonce is invalid.', 'siteorigin-panels' ),
|
24 |
-
__( 'Invalid nonce.', 'siteorigin-panels' ),
|
25 |
-
403
|
26 |
-
);
|
27 |
-
}
|
28 |
-
|
29 |
-
$type = $_REQUEST['type'];
|
30 |
-
|
31 |
-
if ( ! in_array( $type, array( 'row', 'cell', 'widget' ) ) ) {
|
32 |
-
wp_die(
|
33 |
-
__( 'Please specify the type of style form to be rendered.', 'siteorigin-panels' ),
|
34 |
-
__( 'Missing style form type.', 'siteorigin-panels' ),
|
35 |
-
400
|
36 |
-
);
|
37 |
-
}
|
38 |
-
|
39 |
-
$current = isset( $_REQUEST['style'] ) ? $_REQUEST['style'] : array();
|
40 |
-
$post_id = empty( $_REQUEST['postId'] ) ? 0 : $_REQUEST['postId'];
|
41 |
-
|
42 |
-
$args = ! empty( $_POST['args'] ) ? json_decode( stripslashes( $_POST['args'] ), true ) : array();
|
43 |
-
|
44 |
-
switch ( $type ) {
|
45 |
-
case 'row':
|
46 |
-
$this->render_styles_fields( 'row', '<h3>' . __( 'Row Styles', 'siteorigin-panels' ) . '</h3>', '', $current, $post_id, $args );
|
47 |
-
break;
|
48 |
-
|
49 |
-
case 'cell':
|
50 |
-
$cell_number = isset( $args['index'] ) ? ' ' . ( intval( $args['index'] ) + 1 ) : '';
|
51 |
-
$this->render_styles_fields( 'cell', '<h3>' . sprintf( __( 'Cell%s Styles', 'siteorigin-panels' ), $cell_number ) . '</h3>', '', $current, $post_id, $args );
|
52 |
-
break;
|
53 |
-
|
54 |
-
case 'widget':
|
55 |
-
$this->render_styles_fields( 'widget', '<h3>' . __( 'Widget Styles', 'siteorigin-panels' ) . '</h3>', '', $current, $post_id, $args );
|
56 |
-
break;
|
57 |
-
}
|
58 |
-
|
59 |
-
wp_die();
|
60 |
-
}
|
61 |
-
|
62 |
-
/**
|
63 |
-
* Render all the style fields
|
64 |
-
*
|
65 |
-
* @param $section
|
66 |
-
* @param string $before
|
67 |
-
* @param string $after
|
68 |
-
* @param array $current
|
69 |
-
* @param int $post_id
|
70 |
-
* @param array $args Arguments passed by the builder
|
71 |
-
*
|
72 |
-
* @return bool
|
73 |
-
*/
|
74 |
-
function render_styles_fields( $section, $before = '', $after = '', $current = array(), $post_id = 0, $args = array() ) {
|
75 |
-
$fields = array();
|
76 |
-
$fields = apply_filters( 'siteorigin_panels_' . $section . '_style_fields', $fields, $post_id, $args );
|
77 |
-
$fields = apply_filters( 'siteorigin_panels_general_style_fields', $fields, $post_id, $args );
|
78 |
-
if ( empty( $fields ) ) {
|
79 |
-
return false;
|
80 |
-
}
|
81 |
-
|
82 |
-
$groups = array(
|
83 |
-
'attributes' => array(
|
84 |
-
'name' => __( 'Attributes', 'siteorigin-panels' ),
|
85 |
-
'priority' => 5
|
86 |
-
),
|
87 |
-
'layout' => array(
|
88 |
-
'name' => __( 'Layout', 'siteorigin-panels' ),
|
89 |
-
'priority' => 10
|
90 |
-
),
|
91 |
-
'
|
92 |
-
'name' => __( '
|
93 |
-
'priority' =>
|
94 |
-
),
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
$
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
*
|
173 |
-
*
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
<div class="measurement-wrapper">
|
190 |
-
<input type="text" class="measurement-value measurement-
|
191 |
-
placeholder="<?php _e( '
|
192 |
-
</div>
|
193 |
-
<div class="measurement-wrapper">
|
194 |
-
<input type="text" class="measurement-value measurement-
|
195 |
-
placeholder="<?php _e( '
|
196 |
-
</div>
|
197 |
-
<div class="measurement-wrapper">
|
198 |
-
<input type="text" class="measurement-value measurement-
|
199 |
-
placeholder="<?php _e( '
|
200 |
-
</div>
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
</div>
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
<?php
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
*
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
*
|
361 |
-
*
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
}
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
$
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
$return[ $k ] =
|
427 |
-
}
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
break;
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
*
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
if (
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
'
|
488 |
-
'
|
489 |
-
'
|
490 |
-
'
|
491 |
-
'
|
492 |
-
'
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
*
|
505 |
-
*
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class SiteOrigin_Panels_Styles_Admin {
|
4 |
+
|
5 |
+
function __construct() {
|
6 |
+
add_action( 'wp_ajax_so_panels_style_form', array( $this, 'action_style_form' ) );
|
7 |
+
|
8 |
+
add_filter( 'siteorigin_panels_data', array( $this, 'convert_data' ) );
|
9 |
+
add_filter( 'siteorigin_panels_prebuilt_layout', array( $this, 'convert_data' ) );
|
10 |
+
}
|
11 |
+
|
12 |
+
public static function single() {
|
13 |
+
static $single;
|
14 |
+
return empty( $single ) ? $single = new self() : $single;
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Admin action for handling fetching the style fields
|
19 |
+
*/
|
20 |
+
function action_style_form() {
|
21 |
+
if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
|
22 |
+
wp_die(
|
23 |
+
__( 'The supplied nonce is invalid.', 'siteorigin-panels' ),
|
24 |
+
__( 'Invalid nonce.', 'siteorigin-panels' ),
|
25 |
+
403
|
26 |
+
);
|
27 |
+
}
|
28 |
+
|
29 |
+
$type = $_REQUEST['type'];
|
30 |
+
|
31 |
+
if ( ! in_array( $type, array( 'row', 'cell', 'widget' ) ) ) {
|
32 |
+
wp_die(
|
33 |
+
__( 'Please specify the type of style form to be rendered.', 'siteorigin-panels' ),
|
34 |
+
__( 'Missing style form type.', 'siteorigin-panels' ),
|
35 |
+
400
|
36 |
+
);
|
37 |
+
}
|
38 |
+
|
39 |
+
$current = isset( $_REQUEST['style'] ) ? $_REQUEST['style'] : array();
|
40 |
+
$post_id = empty( $_REQUEST['postId'] ) ? 0 : $_REQUEST['postId'];
|
41 |
+
|
42 |
+
$args = ! empty( $_POST['args'] ) ? json_decode( stripslashes( $_POST['args'] ), true ) : array();
|
43 |
+
|
44 |
+
switch ( $type ) {
|
45 |
+
case 'row':
|
46 |
+
$this->render_styles_fields( 'row', '<h3>' . __( 'Row Styles', 'siteorigin-panels' ) . '</h3>', '', $current, $post_id, $args );
|
47 |
+
break;
|
48 |
+
|
49 |
+
case 'cell':
|
50 |
+
$cell_number = isset( $args['index'] ) ? ' ' . ( intval( $args['index'] ) + 1 ) : '';
|
51 |
+
$this->render_styles_fields( 'cell', '<h3>' . sprintf( __( 'Cell%s Styles', 'siteorigin-panels' ), $cell_number ) . '</h3>', '', $current, $post_id, $args );
|
52 |
+
break;
|
53 |
+
|
54 |
+
case 'widget':
|
55 |
+
$this->render_styles_fields( 'widget', '<h3>' . __( 'Widget Styles', 'siteorigin-panels' ) . '</h3>', '', $current, $post_id, $args );
|
56 |
+
break;
|
57 |
+
}
|
58 |
+
|
59 |
+
wp_die();
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Render all the style fields
|
64 |
+
*
|
65 |
+
* @param $section
|
66 |
+
* @param string $before
|
67 |
+
* @param string $after
|
68 |
+
* @param array $current
|
69 |
+
* @param int $post_id
|
70 |
+
* @param array $args Arguments passed by the builder
|
71 |
+
*
|
72 |
+
* @return bool
|
73 |
+
*/
|
74 |
+
function render_styles_fields( $section, $before = '', $after = '', $current = array(), $post_id = 0, $args = array() ) {
|
75 |
+
$fields = array();
|
76 |
+
$fields = apply_filters( 'siteorigin_panels_' . $section . '_style_fields', $fields, $post_id, $args );
|
77 |
+
$fields = apply_filters( 'siteorigin_panels_general_style_fields', $fields, $post_id, $args );
|
78 |
+
if ( empty( $fields ) ) {
|
79 |
+
return false;
|
80 |
+
}
|
81 |
+
|
82 |
+
$groups = array(
|
83 |
+
'attributes' => array(
|
84 |
+
'name' => __( 'Attributes', 'siteorigin-panels' ),
|
85 |
+
'priority' => 5
|
86 |
+
),
|
87 |
+
'layout' => array(
|
88 |
+
'name' => __( 'Layout', 'siteorigin-panels' ),
|
89 |
+
'priority' => 10
|
90 |
+
),
|
91 |
+
'mobile_layout' => array(
|
92 |
+
'name' => __( 'Mobile Layout', 'siteorigin-panels' ),
|
93 |
+
'priority' => 11
|
94 |
+
),
|
95 |
+
'design' => array(
|
96 |
+
'name' => __( 'Design', 'siteorigin-panels' ),
|
97 |
+
'priority' => 15
|
98 |
+
),
|
99 |
+
);
|
100 |
+
|
101 |
+
// Check if we need a default group
|
102 |
+
foreach ( $fields as $field_id => $field ) {
|
103 |
+
if ( empty( $field['group'] ) || $field['group'] == 'theme' ) {
|
104 |
+
if ( empty( $groups['theme'] ) ) {
|
105 |
+
$groups['theme'] = array(
|
106 |
+
'name' => __( 'Theme', 'siteorigin-panels' ),
|
107 |
+
'priority' => 10
|
108 |
+
);
|
109 |
+
}
|
110 |
+
$fields[ $field_id ]['group'] = 'theme';
|
111 |
+
}
|
112 |
+
}
|
113 |
+
$groups = apply_filters( 'siteorigin_panels_' . $section . '_style_groups', $groups, $post_id, $args );
|
114 |
+
$groups = apply_filters( 'siteorigin_panels_general_style_groups', $groups, $post_id, $args );
|
115 |
+
|
116 |
+
// Sort the style fields and groups by priority
|
117 |
+
uasort( $fields, array( $this, 'sort_fields' ) );
|
118 |
+
uasort( $groups, array( $this, 'sort_fields' ) );
|
119 |
+
|
120 |
+
echo $before;
|
121 |
+
|
122 |
+
$group_counts = array();
|
123 |
+
foreach ( $fields as $field_id => $field ) {
|
124 |
+
if ( empty( $group_counts[ $field['group'] ] ) ) {
|
125 |
+
$group_counts[ $field['group'] ] = 0;
|
126 |
+
}
|
127 |
+
$group_counts[ $field['group'] ] ++;
|
128 |
+
}
|
129 |
+
|
130 |
+
foreach ( $groups as $group_id => $group ) {
|
131 |
+
|
132 |
+
if ( empty( $group_counts[ $group_id ] ) ) {
|
133 |
+
continue;
|
134 |
+
}
|
135 |
+
|
136 |
+
?>
|
137 |
+
<div class="style-section-wrapper">
|
138 |
+
<div class="style-section-head">
|
139 |
+
<h4><?php echo esc_html( $group['name'] ) ?></h4>
|
140 |
+
</div>
|
141 |
+
<div class="style-section-fields" style="display: none">
|
142 |
+
<?php
|
143 |
+
foreach ( $fields as $field_id => $field ) {
|
144 |
+
$default = isset( $field[ 'default' ] ) ? $field[ 'default' ] : false;
|
145 |
+
|
146 |
+
if ( $field['group'] == $group_id ) {
|
147 |
+
?>
|
148 |
+
<div class="style-field-wrapper">
|
149 |
+
<?php if ( ! empty( $field['name'] ) ) : ?>
|
150 |
+
<label><?php echo $field['name'] ?></label>
|
151 |
+
<?php endif; ?>
|
152 |
+
<div
|
153 |
+
class="style-field style-field-<?php echo sanitize_html_class( $field['type'] ) ?>">
|
154 |
+
<?php $this->render_style_field( $field, isset( $current[ $field_id ] ) ? $current[ $field_id ] : $default, $field_id, $current ) ?>
|
155 |
+
</div>
|
156 |
+
</div>
|
157 |
+
<?php
|
158 |
+
|
159 |
+
}
|
160 |
+
|
161 |
+
}
|
162 |
+
?>
|
163 |
+
</div>
|
164 |
+
</div>
|
165 |
+
<?php
|
166 |
+
}
|
167 |
+
|
168 |
+
echo $after;
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* Generate the style field
|
173 |
+
*
|
174 |
+
* @param array $field Everything needed to display the field
|
175 |
+
* @param $current
|
176 |
+
* @param $field_id
|
177 |
+
* @param $current_styles
|
178 |
+
*/
|
179 |
+
function render_style_field( $field, $current, $field_id, $current_styles ) {
|
180 |
+
$field_name = 'style[' . $field_id . ']';
|
181 |
+
|
182 |
+
echo '<div class="style-input-wrapper">';
|
183 |
+
switch ( $field['type'] ) {
|
184 |
+
case 'measurement' :
|
185 |
+
|
186 |
+
if ( ! empty( $field['multiple'] ) ) {
|
187 |
+
?>
|
188 |
+
<div class="measurement-inputs">
|
189 |
+
<div class="measurement-wrapper">
|
190 |
+
<input type="text" class="measurement-value measurement-top"
|
191 |
+
placeholder="<?php _e( 'Top', 'siteorigin-panels' ) ?>"/>
|
192 |
+
</div>
|
193 |
+
<div class="measurement-wrapper">
|
194 |
+
<input type="text" class="measurement-value measurement-right"
|
195 |
+
placeholder="<?php _e( 'Right', 'siteorigin-panels' ) ?>"/>
|
196 |
+
</div>
|
197 |
+
<div class="measurement-wrapper">
|
198 |
+
<input type="text" class="measurement-value measurement-bottom"
|
199 |
+
placeholder="<?php _e( 'Bottom', 'siteorigin-panels' ) ?>"/>
|
200 |
+
</div>
|
201 |
+
<div class="measurement-wrapper">
|
202 |
+
<input type="text" class="measurement-value measurement-left"
|
203 |
+
placeholder="<?php _e( 'Left', 'siteorigin-panels' ) ?>"/>
|
204 |
+
</div>
|
205 |
+
</div>
|
206 |
+
<?php
|
207 |
+
} else {
|
208 |
+
?><input type="text" class="measurement-value measurement-value-single"/><?php
|
209 |
+
}
|
210 |
+
|
211 |
+
?>
|
212 |
+
<select
|
213 |
+
class="measurement-unit measurement-unit-<?php echo ! empty( $field['multiple'] ) ? 'multiple' : 'single' ?>">
|
214 |
+
<?php foreach ( $this->measurements_list() as $measurement ): ?>
|
215 |
+
<option
|
216 |
+
value="<?php echo esc_html( $measurement ) ?>"><?php echo esc_html( $measurement ) ?></option>
|
217 |
+
<?php endforeach ?>
|
218 |
+
</select>
|
219 |
+
<input type="hidden" name="<?php echo esc_attr( $field_name ) ?>"
|
220 |
+
value="<?php echo esc_attr( $current ) ?>"/>
|
221 |
+
<?php
|
222 |
+
break;
|
223 |
+
|
224 |
+
case 'color' :
|
225 |
+
?>
|
226 |
+
<input type="text" name="<?php echo esc_attr( $field_name ) ?>"
|
227 |
+
value="<?php echo esc_attr( $current ) ?>" class="so-wp-color-field"/>
|
228 |
+
<?php
|
229 |
+
break;
|
230 |
+
|
231 |
+
case 'image' :
|
232 |
+
$image = false;
|
233 |
+
if ( ! empty( $current ) ) {
|
234 |
+
$image = SiteOrigin_Panels_Styles::get_attachment_image_src( $current, 'thumbnail' );
|
235 |
+
}
|
236 |
+
|
237 |
+
$fallback_url = ( ! empty( $current_styles[ $field_id . '_fallback' ] ) && $current_styles[ $field_id . '_fallback' ] !== 'false' ? $current_styles[ $field_id . '_fallback' ] : '' );
|
238 |
+
$fallback_field_name = 'style[' . $field_id . '_fallback]';
|
239 |
+
|
240 |
+
?>
|
241 |
+
<div class="so-image-selector">
|
242 |
+
<div class="current-image" <?php if ( ! empty( $image ) ) {
|
243 |
+
echo 'style="background-image: url(' . esc_url( $image[0] ) . ');"';
|
244 |
+
} ?>>
|
245 |
+
</div>
|
246 |
+
|
247 |
+
<div class="select-image">
|
248 |
+
<?php _e( 'Select Image', 'siteorigin-panels' ) ?>
|
249 |
+
</div>
|
250 |
+
<input type="hidden" name="<?php echo esc_attr( $field_name ) ?>"
|
251 |
+
value="<?php echo intval( $current ) ?>"/>
|
252 |
+
</div>
|
253 |
+
<a href="#" class="remove-image<?php if ( empty( $current ) ) echo ' hidden' ?>"><?php _e( 'Remove', 'siteorigin-panels' ) ?></a>
|
254 |
+
|
255 |
+
<input type="text" value="<?php echo esc_url( $fallback_url ) ?>"
|
256 |
+
placeholder="<?php esc_attr_e( 'External URL', 'siteorigin-panels' ) ?>"
|
257 |
+
name="<?php echo esc_attr( $fallback_field_name ) ?>"
|
258 |
+
class="image-fallback widefat" />
|
259 |
+
<?php
|
260 |
+
break;
|
261 |
+
|
262 |
+
case 'url' :
|
263 |
+
case 'text' :
|
264 |
+
?><input type="text" name="<?php echo esc_attr( $field_name ) ?>"
|
265 |
+
value="<?php echo esc_attr( $current ) ?>" class="widefat" /><?php
|
266 |
+
break;
|
267 |
+
|
268 |
+
case 'checkbox' :
|
269 |
+
$current = (bool) $current;
|
270 |
+
?>
|
271 |
+
<label class="so-checkbox-label">
|
272 |
+
<input type="checkbox" name="<?php echo esc_attr( $field_name ) ?>" <?php checked( $current ) ?> />
|
273 |
+
<?php echo esc_html( isset( $field['label'] ) ? $field['label'] : __( 'Enabled', 'siteorigin-panels' ) ) ?>
|
274 |
+
</label>
|
275 |
+
<?php
|
276 |
+
break;
|
277 |
+
|
278 |
+
case 'select' :
|
279 |
+
?>
|
280 |
+
<select name="<?php echo esc_attr( $field_name ) ?>">
|
281 |
+
<?php foreach ( $field['options'] as $k => $v ) : ?>
|
282 |
+
<option
|
283 |
+
value="<?php echo esc_attr( $k ) ?>" <?php selected( $current, $k ) ?>><?php echo esc_html( $v ) ?></option>
|
284 |
+
<?php endforeach; ?>
|
285 |
+
</select>
|
286 |
+
<?php
|
287 |
+
break;
|
288 |
+
|
289 |
+
case 'radio' :
|
290 |
+
$radio_id = $field_name . '-' . uniqid();
|
291 |
+
foreach ( $field['options'] as $k => $v ) :
|
292 |
+
?>
|
293 |
+
<label for="<?php echo esc_attr( $radio_id . '-' . $k ) ?>">
|
294 |
+
<input type="radio" name="<?php echo esc_attr( $radio_id ) ?>"
|
295 |
+
id="<?php echo esc_attr( $radio_id . '-' . $k ) ?>"
|
296 |
+
value="<?php echo esc_attr( $k ) ?>" <?php checked( $k, $current ) ?>> <?php echo esc_html( $v ) ?>
|
297 |
+
</label>
|
298 |
+
<?php
|
299 |
+
endforeach;
|
300 |
+
break;
|
301 |
+
|
302 |
+
case 'textarea' :
|
303 |
+
case 'code' :
|
304 |
+
?><textarea type="text" name="<?php echo esc_attr( $field_name ) ?>"
|
305 |
+
class="widefat <?php if ( $field['type'] == 'code' ) {
|
306 |
+
echo 'so-field-code';
|
307 |
+
} ?>" rows="4"><?php echo esc_textarea( $current ) ?></textarea><?php
|
308 |
+
break;
|
309 |
+
}
|
310 |
+
|
311 |
+
echo '</div>';
|
312 |
+
|
313 |
+
if ( ! empty( $field['description'] ) ) {
|
314 |
+
?><p class="so-description"><?php echo wp_kses_post( $field['description'] ) ?></p><?php
|
315 |
+
}
|
316 |
+
}
|
317 |
+
|
318 |
+
/**
|
319 |
+
* Sanitize the style fields in panels_data
|
320 |
+
*
|
321 |
+
* @param $panels_data
|
322 |
+
*
|
323 |
+
* @return mixed
|
324 |
+
*/
|
325 |
+
function sanitize_all( $panels_data ) {
|
326 |
+
if ( ! empty( $panels_data['widgets'] ) ) {
|
327 |
+
// Sanitize the widgets
|
328 |
+
for ( $i = 0; $i < count( $panels_data['widgets'] ); $i ++ ) {
|
329 |
+
if ( empty( $panels_data['widgets'][ $i ]['panels_info']['style'] ) ) {
|
330 |
+
continue;
|
331 |
+
}
|
332 |
+
$panels_data['widgets'][ $i ]['panels_info']['style'] = $this->sanitize_style_fields( 'widget', $panels_data['widgets'][ $i ]['panels_info']['style'] );
|
333 |
+
}
|
334 |
+
}
|
335 |
+
|
336 |
+
if ( ! empty( $panels_data['grids'] ) ) {
|
337 |
+
// The rows
|
338 |
+
for ( $i = 0; $i < count( $panels_data['grids'] ); $i ++ ) {
|
339 |
+
if ( empty( $panels_data['grids'][ $i ]['style'] ) ) {
|
340 |
+
continue;
|
341 |
+
}
|
342 |
+
$panels_data['grids'][ $i ]['style'] = $this->sanitize_style_fields( 'row', $panels_data['grids'][ $i ]['style'] );
|
343 |
+
}
|
344 |
+
}
|
345 |
+
|
346 |
+
if ( ! empty( $panels_data['grid_cells'] ) ) {
|
347 |
+
// And finally, the cells
|
348 |
+
for ( $i = 0; $i < count( $panels_data['grid_cells'] ); $i ++ ) {
|
349 |
+
if ( empty( $panels_data['grid_cells'][ $i ]['style'] ) ) {
|
350 |
+
continue;
|
351 |
+
}
|
352 |
+
$panels_data['grid_cells'][ $i ]['style'] = $this->sanitize_style_fields( 'cell', $panels_data['grid_cells'][ $i ]['style'] );
|
353 |
+
}
|
354 |
+
}
|
355 |
+
|
356 |
+
return $panels_data;
|
357 |
+
}
|
358 |
+
|
359 |
+
/**
|
360 |
+
* Sanitize style fields.
|
361 |
+
*
|
362 |
+
* @param $section
|
363 |
+
* @param $styles
|
364 |
+
*
|
365 |
+
* @return array Sanitized styles
|
366 |
+
*/
|
367 |
+
function sanitize_style_fields( $section, $styles ) {
|
368 |
+
// Use the filter to get the fields for this section.
|
369 |
+
if ( empty( $fields_cache[ $section ] ) ) {
|
370 |
+
// This filter doesn't pass in the arguments $post_id and $args
|
371 |
+
// Plugins looking to extend fields, should always add their fields if these are empty
|
372 |
+
$fields_cache[ $section ] = array();
|
373 |
+
$fields_cache[ $section ] = apply_filters( 'siteorigin_panels_' . $section . '_style_fields', $fields_cache[ $section ], false, false );
|
374 |
+
$fields_cache[ $section ] = apply_filters( 'siteorigin_panels_general_style_fields', $fields_cache[ $section ], false, false );
|
375 |
+
}
|
376 |
+
$fields = $fields_cache[ $section ];
|
377 |
+
|
378 |
+
if ( empty( $fields ) ) {
|
379 |
+
return array();
|
380 |
+
}
|
381 |
+
|
382 |
+
$return = array();
|
383 |
+
foreach ( $fields as $k => $field ) {
|
384 |
+
// Skip this if no field type is set
|
385 |
+
if ( empty( $field['type'] ) ) {
|
386 |
+
continue;
|
387 |
+
}
|
388 |
+
|
389 |
+
// Handle the special case of a checkbox
|
390 |
+
if ( $field['type'] == 'checkbox' ) {
|
391 |
+
$return[ $k ] = ! empty( $styles[ $k ] ) ? true : '';
|
392 |
+
continue;
|
393 |
+
}
|
394 |
+
|
395 |
+
// Ignore this if we don't even have a value for the style, unless 'image' field which might have a fallback.
|
396 |
+
if ( ! isset( $styles[ $k ] ) || ( $field['type'] != 'image' && $styles[ $k ] == '' ) ) {
|
397 |
+
continue;
|
398 |
+
}
|
399 |
+
|
400 |
+
switch ( $field['type'] ) {
|
401 |
+
case 'color' :
|
402 |
+
$color = $styles[ $k ];
|
403 |
+
if ( preg_match( '|^#([A-Fa-f0-9]{3,8})$|', $color ) ) {
|
404 |
+
$return[ $k ] = $color;
|
405 |
+
} else {
|
406 |
+
$return[ $k ] = '';
|
407 |
+
}
|
408 |
+
break;
|
409 |
+
case 'image' :
|
410 |
+
$return[ $k ] = ! empty( $styles[ $k ] ) ? sanitize_text_field( $styles[ $k ] ) : false;
|
411 |
+
$fallback_name = $k . '_fallback';
|
412 |
+
if ( empty( $styles[ $k ] ) && empty( $styles[ $fallback_name ] ) ) {
|
413 |
+
break;
|
414 |
+
}
|
415 |
+
$return[ $fallback_name ] = ! empty( $styles[ $fallback_name ] ) ? esc_url_raw( $styles[ $fallback_name ] ) : false;
|
416 |
+
break;
|
417 |
+
case 'url' :
|
418 |
+
$return[ $k ] = esc_url_raw( $styles[ $k ] );
|
419 |
+
break;
|
420 |
+
case 'measurement' :
|
421 |
+
$measurements = array_map( 'preg_quote', $this->measurements_list() );
|
422 |
+
if ( ! empty( $field['multiple'] ) ) {
|
423 |
+
if ( preg_match_all( '/(?:(-?[0-9\.,]+).*?(' . implode( '|', $measurements ) . ')+)/', $styles[ $k ], $match ) ) {
|
424 |
+
$return[ $k ] = $styles[ $k ];
|
425 |
+
} else {
|
426 |
+
$return[ $k ] = '';
|
427 |
+
}
|
428 |
+
} else {
|
429 |
+
if ( preg_match( '/([-?0-9\.,]+).*?(' . implode( '|', $measurements ) . ')/', $styles[ $k ], $match ) ) {
|
430 |
+
$return[ $k ] = $match[1] . $match[2];
|
431 |
+
} else {
|
432 |
+
$return[ $k ] = '';
|
433 |
+
}
|
434 |
+
}
|
435 |
+
break;
|
436 |
+
case 'select' :
|
437 |
+
case 'radio' :
|
438 |
+
if ( ! empty( $styles[ $k ] ) && in_array( $styles[ $k ], array_keys( $field['options'] ) ) ) {
|
439 |
+
$return[ $k ] = $styles[ $k ];
|
440 |
+
}
|
441 |
+
break;
|
442 |
+
default:
|
443 |
+
// Just pass the value through.
|
444 |
+
$return[ $k ] = $styles[ $k ];
|
445 |
+
break;
|
446 |
+
|
447 |
+
}
|
448 |
+
}
|
449 |
+
|
450 |
+
return $return;
|
451 |
+
}
|
452 |
+
|
453 |
+
/**
|
454 |
+
* Convert the single string attribute of the grid style into an array.
|
455 |
+
*
|
456 |
+
* @param $panels_data
|
457 |
+
*
|
458 |
+
* @return mixed
|
459 |
+
*/
|
460 |
+
function convert_data( $panels_data ) {
|
461 |
+
if ( empty( $panels_data ) || empty( $panels_data['grids'] ) || ! is_array( $panels_data['grids'] ) ) {
|
462 |
+
return $panels_data;
|
463 |
+
}
|
464 |
+
|
465 |
+
foreach( $panels_data['grids'] as & $grid ) {
|
466 |
+
if ( ! is_array( $grid ) || empty( $grid ) || empty( $grid['style'] ) ) {
|
467 |
+
continue;
|
468 |
+
}
|
469 |
+
|
470 |
+
if ( is_string( $grid['style'] ) ) {
|
471 |
+
$grid['style'] = array(
|
472 |
+
$grid['style']
|
473 |
+
);
|
474 |
+
}
|
475 |
+
}
|
476 |
+
|
477 |
+
return $panels_data;
|
478 |
+
}
|
479 |
+
|
480 |
+
/**
|
481 |
+
* Get list of supported mesurements
|
482 |
+
*
|
483 |
+
* @return array
|
484 |
+
*/
|
485 |
+
function measurements_list() {
|
486 |
+
$measurements = array(
|
487 |
+
'px',
|
488 |
+
'%',
|
489 |
+
'in',
|
490 |
+
'cm',
|
491 |
+
'mm',
|
492 |
+
'em',
|
493 |
+
'ex',
|
494 |
+
'pt',
|
495 |
+
'pc',
|
496 |
+
'rem'
|
497 |
+
);
|
498 |
+
|
499 |
+
// Allow themes and plugins to trim or enhance the list.
|
500 |
+
return apply_filters( 'siteorigin_panels_style_get_measurements_list', $measurements );
|
501 |
+
}
|
502 |
+
|
503 |
+
/**
|
504 |
+
* User sort function to sort by the priority key value.
|
505 |
+
*
|
506 |
+
* @param $a
|
507 |
+
* @param $b
|
508 |
+
*
|
509 |
+
* @return int
|
510 |
+
*/
|
511 |
+
static function sort_fields( $a, $b ) {
|
512 |
+
return ( ( isset( $a['priority'] ) ? $a['priority'] : 10 ) > ( isset( $b['priority'] ) ? $b['priority'] : 10 ) ) ? 1 : - 1;
|
513 |
+
}
|
514 |
+
}
|
515 |
+
|
516 |
+
// Initialise all the default styling
|
517 |
+
SiteOrigin_Panels_Styles::single();
|
inc/styles.php
CHANGED
@@ -1,713 +1,750 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Class for handling all the default styling.
|
5 |
-
*
|
6 |
-
* Class SiteOrigin_Panels_Default_Styles
|
7 |
-
*/
|
8 |
-
class SiteOrigin_Panels_Styles {
|
9 |
-
|
10 |
-
public function __construct() {
|
11 |
-
add_action( 'wp_enqueue_scripts', array( $this, 'register_scripts' ), 5 );
|
12 |
-
|
13 |
-
// Adding all the fields
|
14 |
-
add_filter( 'siteorigin_panels_row_style_fields', array( $this, 'row_style_fields' ) );
|
15 |
-
add_filter( 'siteorigin_panels_cell_style_fields', array( $this, 'cell_style_fields' ) );
|
16 |
-
add_filter( 'siteorigin_panels_widget_style_fields', array( $this, 'widget_style_fields' ) );
|
17 |
-
|
18 |
-
// Style wrapper attributes
|
19 |
-
add_filter( 'siteorigin_panels_row_style_attributes', array( $this, 'general_style_attributes' ), 10, 2 );
|
20 |
-
add_filter( 'siteorigin_panels_row_style_attributes', array( $this, 'row_style_attributes' ), 10, 2 );
|
21 |
-
add_filter( 'siteorigin_panels_row_style_attributes', array( $this, 'vantage_row_style_attributes' ), 11, 2 );
|
22 |
-
add_filter( 'siteorigin_panels_cell_style_attributes', array( $this, 'general_style_attributes' ), 10, 2 );
|
23 |
-
add_filter( 'siteorigin_panels_widget_style_attributes', array( $this, 'general_style_attributes' ), 10, 2 );
|
24 |
-
|
25 |
-
// Style wrapper CSS
|
26 |
-
add_filter( 'siteorigin_panels_row_style_css', array( $this, 'general_style_css' ), 10, 2 );
|
27 |
-
add_filter( 'siteorigin_panels_cell_style_css', array( $this, 'general_style_css' ), 10, 2 );
|
28 |
-
add_filter( 'siteorigin_panels_widget_style_css', array( $this, 'general_style_css' ), 10, 2 );
|
29 |
-
|
30 |
-
add_filter( 'siteorigin_panels_row_style_mobile_css', array( $this, 'general_style_mobile_css' ), 10, 2 );
|
31 |
-
add_filter( 'siteorigin_panels_cell_style_mobile_css', array( $this, 'general_style_mobile_css' ), 10, 2 );
|
32 |
-
add_filter( 'siteorigin_panels_widget_style_mobile_css', array( $this, 'general_style_mobile_css' ), 10, 2 );
|
33 |
-
|
34 |
-
// Main filter to add any custom CSS.
|
35 |
-
add_filter( 'siteorigin_panels_css_object', array( $this, 'filter_css_object' ), 10, 4 );
|
36 |
-
|
37 |
-
// Filtering specific attributes
|
38 |
-
add_filter( 'siteorigin_panels_css_row_margin_bottom', array( $this, 'filter_row_bottom_margin' ), 10, 2 );
|
39 |
-
add_filter( '
|
40 |
-
add_filter( '
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
*
|
69 |
-
*
|
70 |
-
*
|
71 |
-
*
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
'
|
81 |
-
'
|
82 |
-
'
|
83 |
-
'
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
'
|
89 |
-
'
|
90 |
-
'
|
91 |
-
'
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
'
|
97 |
-
'
|
98 |
-
'
|
99 |
-
'
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
'
|
105 |
-
'
|
106 |
-
'
|
107 |
-
'
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
'
|
115 |
-
'
|
116 |
-
'
|
117 |
-
'
|
118 |
-
'
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
'
|
126 |
-
'
|
127 |
-
'
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
'
|
137 |
-
'
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
'
|
145 |
-
'
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
'
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
'
|
157 |
-
'
|
158 |
-
'
|
159 |
-
'
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
'
|
170 |
-
'
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
*
|
181 |
-
*
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
'
|
192 |
-
'
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
'
|
202 |
-
'
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
'
|
210 |
-
'
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
'
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
'
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
'
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
'
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
'
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
'
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
'
|
294 |
-
'
|
295 |
-
'
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
'
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
$fields
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
$fields
|
333 |
-
|
334 |
-
|
335 |
-
'
|
336 |
-
'
|
337 |
-
'
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
$css[ 'background-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
$css[ 'background-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
if
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
);
|
580 |
-
}
|
581 |
-
|
582 |
-
//
|
583 |
-
if( empty( $row[
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
$
|
607 |
-
$
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
$
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
if( empty( $cell[ '
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
$
|
649 |
-
$
|
650 |
-
|
651 |
-
$
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
*
|
686 |
-
*
|
687 |
-
* @
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
}
|
712 |
-
|
713 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class for handling all the default styling.
|
5 |
+
*
|
6 |
+
* Class SiteOrigin_Panels_Default_Styles
|
7 |
+
*/
|
8 |
+
class SiteOrigin_Panels_Styles {
|
9 |
+
|
10 |
+
public function __construct() {
|
11 |
+
add_action( 'wp_enqueue_scripts', array( $this, 'register_scripts' ), 5 );
|
12 |
+
|
13 |
+
// Adding all the fields
|
14 |
+
add_filter( 'siteorigin_panels_row_style_fields', array( $this, 'row_style_fields' ) );
|
15 |
+
add_filter( 'siteorigin_panels_cell_style_fields', array( $this, 'cell_style_fields' ) );
|
16 |
+
add_filter( 'siteorigin_panels_widget_style_fields', array( $this, 'widget_style_fields' ) );
|
17 |
+
|
18 |
+
// Style wrapper attributes
|
19 |
+
add_filter( 'siteorigin_panels_row_style_attributes', array( $this, 'general_style_attributes' ), 10, 2 );
|
20 |
+
add_filter( 'siteorigin_panels_row_style_attributes', array( $this, 'row_style_attributes' ), 10, 2 );
|
21 |
+
add_filter( 'siteorigin_panels_row_style_attributes', array( $this, 'vantage_row_style_attributes' ), 11, 2 );
|
22 |
+
add_filter( 'siteorigin_panels_cell_style_attributes', array( $this, 'general_style_attributes' ), 10, 2 );
|
23 |
+
add_filter( 'siteorigin_panels_widget_style_attributes', array( $this, 'general_style_attributes' ), 10, 2 );
|
24 |
+
|
25 |
+
// Style wrapper CSS
|
26 |
+
add_filter( 'siteorigin_panels_row_style_css', array( $this, 'general_style_css' ), 10, 2 );
|
27 |
+
add_filter( 'siteorigin_panels_cell_style_css', array( $this, 'general_style_css' ), 10, 2 );
|
28 |
+
add_filter( 'siteorigin_panels_widget_style_css', array( $this, 'general_style_css' ), 10, 2 );
|
29 |
+
|
30 |
+
add_filter( 'siteorigin_panels_row_style_mobile_css', array( $this, 'general_style_mobile_css' ), 10, 2 );
|
31 |
+
add_filter( 'siteorigin_panels_cell_style_mobile_css', array( $this, 'general_style_mobile_css' ), 10, 2 );
|
32 |
+
add_filter( 'siteorigin_panels_widget_style_mobile_css', array( $this, 'general_style_mobile_css' ), 10, 2 );
|
33 |
+
|
34 |
+
// Main filter to add any custom CSS.
|
35 |
+
add_filter( 'siteorigin_panels_css_object', array( $this, 'filter_css_object' ), 10, 4 );
|
36 |
+
|
37 |
+
// Filtering specific attributes
|
38 |
+
add_filter( 'siteorigin_panels_css_row_margin_bottom', array( $this, 'filter_row_bottom_margin' ), 10, 2 );
|
39 |
+
add_filter( 'siteorigin_panels_css_row_mobile_margin_bottom', array( $this, 'filter_row_mobile_bottom_margin' ), 10, 2 );
|
40 |
+
add_filter( 'siteorigin_panels_css_row_gutter', array( $this, 'filter_row_gutter' ), 10, 2 );
|
41 |
+
add_filter( 'siteorigin_panels_css_widget_css', array( $this, 'filter_widget_style_css' ), 10, 2 );
|
42 |
+
}
|
43 |
+
|
44 |
+
public static function single() {
|
45 |
+
static $single;
|
46 |
+
return empty( $single ) ? $single = new self() : $single;
|
47 |
+
}
|
48 |
+
|
49 |
+
static function register_scripts() {
|
50 |
+
wp_register_script(
|
51 |
+
'siteorigin-panels-front-styles',
|
52 |
+
siteorigin_panels_url( 'js/styling' . SITEORIGIN_PANELS_VERSION_SUFFIX . SITEORIGIN_PANELS_JS_SUFFIX . '.js' ),
|
53 |
+
array( 'jquery' ),
|
54 |
+
SITEORIGIN_PANELS_VERSION
|
55 |
+
);
|
56 |
+
wp_register_script(
|
57 |
+
'siteorigin-parallax',
|
58 |
+
siteorigin_panels_url( 'js/siteorigin-parallax' . SITEORIGIN_PANELS_JS_SUFFIX . '.js' ),
|
59 |
+
array( 'jquery' ),
|
60 |
+
SITEORIGIN_PANELS_VERSION
|
61 |
+
);
|
62 |
+
wp_localize_script( 'siteorigin-panels-front-styles', 'panelsStyles', array(
|
63 |
+
'fullContainer' => apply_filters( 'siteorigin_panels_full_width_container', siteorigin_panels_setting( 'full-width-container' ) )
|
64 |
+
) );
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* These are general styles that apply to all elements
|
69 |
+
*
|
70 |
+
* @param $label
|
71 |
+
*
|
72 |
+
* @return array
|
73 |
+
*/
|
74 |
+
static function get_general_style_fields( $id, $label ) {
|
75 |
+
$fields = array();
|
76 |
+
|
77 |
+
// All the attribute fields
|
78 |
+
|
79 |
+
$fields['id'] = array(
|
80 |
+
'name' => sprintf( __( '%s ID', 'siteorigin-panels' ), $label ),
|
81 |
+
'type' => 'text',
|
82 |
+
'group' => 'attributes',
|
83 |
+
'description' => sprintf( __( 'A custom ID used for this %s.', 'siteorigin-panels' ), strtolower( $label ) ),
|
84 |
+
'priority' => 4,
|
85 |
+
);
|
86 |
+
|
87 |
+
$fields['class'] = array(
|
88 |
+
'name' => sprintf( __( '%s Class', 'siteorigin-panels' ), $label ),
|
89 |
+
'type' => 'text',
|
90 |
+
'group' => 'attributes',
|
91 |
+
'description' => __( 'A CSS class', 'siteorigin-panels' ),
|
92 |
+
'priority' => 5,
|
93 |
+
);
|
94 |
+
|
95 |
+
$fields[ $id . '_css' ] = array(
|
96 |
+
'name' => __( 'CSS Styles', 'siteorigin-panels' ),
|
97 |
+
'type' => 'code',
|
98 |
+
'group' => 'attributes',
|
99 |
+
'description' => __( 'One style attribute per line.', 'siteorigin-panels' ),
|
100 |
+
'priority' => 10,
|
101 |
+
);
|
102 |
+
|
103 |
+
$fields[ 'mobile_css' ] = array(
|
104 |
+
'name' => __( 'Mobile CSS Styles', 'siteorigin-panels' ),
|
105 |
+
'type' => 'code',
|
106 |
+
'group' => 'attributes',
|
107 |
+
'description' => __( 'CSS applied when in mobile view.', 'siteorigin-panels' ),
|
108 |
+
'priority' => 11,
|
109 |
+
);
|
110 |
+
|
111 |
+
// The layout fields
|
112 |
+
|
113 |
+
$fields['padding'] = array(
|
114 |
+
'name' => __( 'Padding', 'siteorigin-panels' ),
|
115 |
+
'type' => 'measurement',
|
116 |
+
'group' => 'layout',
|
117 |
+
'description' => sprintf( __( 'Padding around the entire %s.', 'siteorigin-panels' ), strtolower( $label ) ),
|
118 |
+
'priority' => 7,
|
119 |
+
'multiple' => true
|
120 |
+
);
|
121 |
+
|
122 |
+
// Mobile layout fields
|
123 |
+
|
124 |
+
$fields['mobile_padding'] = array(
|
125 |
+
'name' => __( 'Mobile Padding', 'siteorigin-panels' ),
|
126 |
+
'type' => 'measurement',
|
127 |
+
'group' => 'mobile_layout',
|
128 |
+
'description' => __( 'Padding when on mobile devices.', 'siteorigin-panels' ),
|
129 |
+
'priority' => 8,
|
130 |
+
'multiple' => true
|
131 |
+
);
|
132 |
+
|
133 |
+
// The general design fields
|
134 |
+
|
135 |
+
$fields['background'] = array(
|
136 |
+
'name' => __( 'Background Color', 'siteorigin-panels' ),
|
137 |
+
'type' => 'color',
|
138 |
+
'group' => 'design',
|
139 |
+
'description' => sprintf( __( 'Background color of the %s.', 'siteorigin-panels' ), strtolower( $label ) ),
|
140 |
+
'priority' => 5,
|
141 |
+
);
|
142 |
+
|
143 |
+
$fields['background_image_attachment'] = array(
|
144 |
+
'name' => __( 'Background Image', 'siteorigin-panels' ),
|
145 |
+
'type' => 'image',
|
146 |
+
'group' => 'design',
|
147 |
+
'description' => sprintf( __( 'Background image of the %s.', 'siteorigin-panels' ), strtolower( $label ) ),
|
148 |
+
'priority' => 6,
|
149 |
+
);
|
150 |
+
|
151 |
+
$fields['background_display'] = array(
|
152 |
+
'name' => __( 'Background Image Display', 'siteorigin-panels' ),
|
153 |
+
'type' => 'select',
|
154 |
+
'group' => 'design',
|
155 |
+
'options' => array(
|
156 |
+
'tile' => __( 'Tiled Image', 'siteorigin-panels' ),
|
157 |
+
'cover' => __( 'Cover', 'siteorigin-panels' ),
|
158 |
+
'center' => __( 'Centered, with original size', 'siteorigin-panels' ),
|
159 |
+
'contain' => __( 'Contain', 'siteorigin-panels' ),
|
160 |
+
'fixed' => __( 'Fixed', 'siteorigin-panels' ),
|
161 |
+
'parallax' => __( 'Parallax', 'siteorigin-panels' ),
|
162 |
+
'parallax-original' => __( 'Parallax (Original Size)', 'siteorigin-panels' ),
|
163 |
+
),
|
164 |
+
'description' => __( 'How the background image is displayed.', 'siteorigin-panels' ),
|
165 |
+
'priority' => 7,
|
166 |
+
);
|
167 |
+
|
168 |
+
$fields['border_color'] = array(
|
169 |
+
'name' => __( 'Border Color', 'siteorigin-panels' ),
|
170 |
+
'type' => 'color',
|
171 |
+
'group' => 'design',
|
172 |
+
'description' => sprintf( __( 'Border color of the %s.', 'siteorigin-panels' ), strtolower( $label ) ),
|
173 |
+
'priority' => 10,
|
174 |
+
);
|
175 |
+
|
176 |
+
return $fields;
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* All the row styling fields
|
181 |
+
*
|
182 |
+
* @param $fields
|
183 |
+
*
|
184 |
+
* @return array
|
185 |
+
*/
|
186 |
+
static function row_style_fields( $fields ) {
|
187 |
+
// Add the general fields
|
188 |
+
$fields = wp_parse_args( $fields, self::get_general_style_fields( 'row', __( 'Row', 'siteorigin-panels' ) ) );
|
189 |
+
|
190 |
+
$fields['cell_class'] = array(
|
191 |
+
'name' => __( 'Cell Class', 'siteorigin-panels' ),
|
192 |
+
'type' => 'text',
|
193 |
+
'group' => 'attributes',
|
194 |
+
'description' => __( 'Class added to all cells in this row.', 'siteorigin-panels' ),
|
195 |
+
'priority' => 6,
|
196 |
+
);
|
197 |
+
|
198 |
+
// Add the layout fields
|
199 |
+
|
200 |
+
$fields['bottom_margin'] = array(
|
201 |
+
'name' => __( 'Bottom Margin', 'siteorigin-panels' ),
|
202 |
+
'type' => 'measurement',
|
203 |
+
'group' => 'layout',
|
204 |
+
'description' => sprintf( __( 'Space below the row. Default is %spx.', 'siteorigin-panels' ), siteorigin_panels_setting( 'margin-bottom' ) ),
|
205 |
+
'priority' => 5,
|
206 |
+
);
|
207 |
+
|
208 |
+
$fields['gutter'] = array(
|
209 |
+
'name' => __( 'Gutter', 'siteorigin-panels' ),
|
210 |
+
'type' => 'measurement',
|
211 |
+
'group' => 'layout',
|
212 |
+
'description' => sprintf( __( 'Amount of space between cells. Default is %spx.', 'siteorigin-panels' ), siteorigin_panels_setting( 'margin-sides' ) ),
|
213 |
+
'priority' => 6,
|
214 |
+
);
|
215 |
+
|
216 |
+
$fields['row_stretch'] = array(
|
217 |
+
'name' => __( 'Row Layout', 'siteorigin-panels' ),
|
218 |
+
'type' => 'select',
|
219 |
+
'group' => 'layout',
|
220 |
+
'options' => array(
|
221 |
+
'' => __( 'Standard', 'siteorigin-panels' ),
|
222 |
+
'full' => __( 'Full Width', 'siteorigin-panels' ),
|
223 |
+
'full-stretched' => __( 'Full Width Stretched', 'siteorigin-panels' ),
|
224 |
+
'full-stretched-padded' => __( 'Full Width Stretched Padded', 'siteorigin-panels' ),
|
225 |
+
),
|
226 |
+
'priority' => 10,
|
227 |
+
);
|
228 |
+
|
229 |
+
$fields['collapse_behaviour'] = array(
|
230 |
+
'name' => __( 'Collapse Behaviour', 'siteorigin-panels' ),
|
231 |
+
'type' => 'select',
|
232 |
+
'group' => 'layout',
|
233 |
+
'options' => array(
|
234 |
+
'' => __( 'Standard', 'siteorigin-panels' ),
|
235 |
+
'no_collapse' => __( 'No Collapse', 'siteorigin-panels' ),
|
236 |
+
),
|
237 |
+
'priority' => 15,
|
238 |
+
);
|
239 |
+
|
240 |
+
$fields['collapse_order'] = array(
|
241 |
+
'name' => __( 'Collapse Order', 'siteorigin-panels' ),
|
242 |
+
'type' => 'select',
|
243 |
+
'group' => 'layout',
|
244 |
+
'options' => array(
|
245 |
+
'' => __( 'Default', 'siteorigin-panels' ),
|
246 |
+
'left-top' => __( 'Left on Top', 'siteorigin-panels' ),
|
247 |
+
'right-top' => __( 'Right on Top', 'siteorigin-panels' ),
|
248 |
+
),
|
249 |
+
'priority' => 16,
|
250 |
+
);
|
251 |
+
|
252 |
+
if ( siteorigin_panels_setting( 'legacy-layout' ) != 'always' ) {
|
253 |
+
$fields['cell_alignment'] = array(
|
254 |
+
'name' => __( 'Cell Vertical Alignment', 'siteorigin-panels' ),
|
255 |
+
'type' => 'select',
|
256 |
+
'group' => 'layout',
|
257 |
+
'options' => array(
|
258 |
+
'flex-start' => __( 'Top', 'siteorigin-panels' ),
|
259 |
+
'center' => __( 'Center', 'siteorigin-panels' ),
|
260 |
+
'flex-end' => __( 'Bottom', 'siteorigin-panels' ),
|
261 |
+
'stretch' => __( 'Stretch', 'siteorigin-panels' ),
|
262 |
+
),
|
263 |
+
'priority' => 17,
|
264 |
+
);
|
265 |
+
}
|
266 |
+
|
267 |
+
// Add the mobile layout fields
|
268 |
+
|
269 |
+
$fields['mobile_bottom_margin'] = array(
|
270 |
+
'name' => __( 'Mobile Bottom Margin', 'siteorigin-panels' ),
|
271 |
+
'type' => 'measurement',
|
272 |
+
'group' => 'mobile_layout',
|
273 |
+
'description' => sprintf( __( 'Space below the row on mobile devices. Default is %spx.', 'siteorigin-panels' ), siteorigin_panels_setting( 'margin-bottom' ) ),
|
274 |
+
'priority' => 5,
|
275 |
+
);
|
276 |
+
|
277 |
+
return $fields;
|
278 |
+
}
|
279 |
+
|
280 |
+
/**
|
281 |
+
* All the cell styling fields
|
282 |
+
*
|
283 |
+
* @param $fields
|
284 |
+
*
|
285 |
+
* @return array
|
286 |
+
*/
|
287 |
+
static function cell_style_fields( $fields ) {
|
288 |
+
// Add the general fields
|
289 |
+
$fields = wp_parse_args( $fields, self::get_general_style_fields( 'cell', __( 'Cell', 'siteorigin-panels' ) ) );
|
290 |
+
|
291 |
+
$fields['vertical_alignment'] = array(
|
292 |
+
'name' => __( 'Vertical Alignment', 'siteorigin-panels' ),
|
293 |
+
'type' => 'select',
|
294 |
+
'group' => 'layout',
|
295 |
+
'options' => array(
|
296 |
+
'auto' => __( 'Use row setting', 'siteorigin-panels' ),
|
297 |
+
'flex-start' => __( 'Top', 'siteorigin-panels' ),
|
298 |
+
'center' => __( 'Center', 'siteorigin-panels' ),
|
299 |
+
'flex-end' => __( 'Bottom', 'siteorigin-panels' ),
|
300 |
+
'stretch' => __( 'Stretch', 'siteorigin-panels' ),
|
301 |
+
),
|
302 |
+
'priority' => 16,
|
303 |
+
);
|
304 |
+
|
305 |
+
$fields['font_color'] = array(
|
306 |
+
'name' => __( 'Font Color', 'siteorigin-panels' ),
|
307 |
+
'type' => 'color',
|
308 |
+
'group' => 'design',
|
309 |
+
'description' => __( 'Color of text inside this cell.', 'siteorigin-panels' ),
|
310 |
+
'priority' => 15,
|
311 |
+
);
|
312 |
+
|
313 |
+
$fields['link_color'] = array(
|
314 |
+
'name' => __( 'Links Color', 'siteorigin-panels' ),
|
315 |
+
'type' => 'color',
|
316 |
+
'group' => 'design',
|
317 |
+
'description' => __( 'Color of links inside this cell.', 'siteorigin-panels' ),
|
318 |
+
'priority' => 16,
|
319 |
+
);
|
320 |
+
|
321 |
+
return $fields;
|
322 |
+
}
|
323 |
+
|
324 |
+
/**
|
325 |
+
* @param $fields
|
326 |
+
*
|
327 |
+
* @return array
|
328 |
+
*/
|
329 |
+
static function widget_style_fields( $fields ) {
|
330 |
+
|
331 |
+
// Add the general fields
|
332 |
+
$fields = wp_parse_args( $fields, self::get_general_style_fields( 'widget', __( 'Widget', 'siteorigin-panels' ) ) );
|
333 |
+
|
334 |
+
$fields['margin'] = array(
|
335 |
+
'name' => __( 'Margin', 'siteorigin-panels' ),
|
336 |
+
'type' => 'measurement',
|
337 |
+
'group' => 'layout',
|
338 |
+
'description' => __( 'Margins around the widget.', 'siteorigin-panels' ),
|
339 |
+
'priority' => 6,
|
340 |
+
'multiple' => true
|
341 |
+
);
|
342 |
+
|
343 |
+
// How lets add the design fields
|
344 |
+
|
345 |
+
$fields['font_color'] = array(
|
346 |
+
'name' => __( 'Font Color', 'siteorigin-panels' ),
|
347 |
+
'type' => 'color',
|
348 |
+
'group' => 'design',
|
349 |
+
'description' => __( 'Color of text inside this widget.', 'siteorigin-panels' ),
|
350 |
+
'priority' => 15,
|
351 |
+
);
|
352 |
+
|
353 |
+
$fields['link_color'] = array(
|
354 |
+
'name' => __( 'Links Color', 'siteorigin-panels' ),
|
355 |
+
'type' => 'color',
|
356 |
+
'group' => 'design',
|
357 |
+
'description' => __( 'Color of links inside this widget.', 'siteorigin-panels' ),
|
358 |
+
'priority' => 16,
|
359 |
+
);
|
360 |
+
|
361 |
+
return $fields;
|
362 |
+
}
|
363 |
+
|
364 |
+
/**
|
365 |
+
* Style attributes that apply to rows, cells and widgets
|
366 |
+
*
|
367 |
+
* @param $attributes
|
368 |
+
* @param $style
|
369 |
+
*
|
370 |
+
* @return array $attributes
|
371 |
+
*/
|
372 |
+
static function general_style_attributes( $attributes, $style ){
|
373 |
+
if ( ! empty( $style['class'] ) ) {
|
374 |
+
if( ! is_array( $style['class'] ) ) {
|
375 |
+
$style['class'] = explode( ' ', $style[ 'class' ] );
|
376 |
+
}
|
377 |
+
$attributes['class'] = array_merge( $attributes['class'], $style['class'] );
|
378 |
+
}
|
379 |
+
|
380 |
+
if ( ! empty( $style['background_display'] ) &&
|
381 |
+
! empty( $style['background_image_attachment'] )
|
382 |
+
) {
|
383 |
+
|
384 |
+
$url = self::get_attachment_image_src( $style['background_image_attachment'], 'full' );
|
385 |
+
|
386 |
+
if (
|
387 |
+
! empty( $url ) &&
|
388 |
+
( $style['background_display'] == 'parallax' || $style['background_display'] == 'parallax-original' )
|
389 |
+
) {
|
390 |
+
wp_enqueue_script( 'siteorigin-parallax' );
|
391 |
+
$parallax_args = array(
|
392 |
+
'backgroundUrl' => $url[0],
|
393 |
+
'backgroundSize' => array( $url[1], $url[2] ),
|
394 |
+
'backgroundSizing' => $style['background_display'] == 'parallax-original' ? 'original' : 'scaled',
|
395 |
+
'limitMotion' => siteorigin_panels_setting( 'parallax-motion' ) ? floatval( siteorigin_panels_setting( 'parallax-motion' ) ) : 'auto',
|
396 |
+
);
|
397 |
+
$attributes['data-siteorigin-parallax'] = json_encode( $parallax_args );
|
398 |
+
}
|
399 |
+
}
|
400 |
+
|
401 |
+
if ( ! empty( $style['id'] ) ) {
|
402 |
+
$attributes['id'] = sanitize_html_class( $style['id'] );
|
403 |
+
}
|
404 |
+
|
405 |
+
return $attributes;
|
406 |
+
}
|
407 |
+
|
408 |
+
static function row_style_attributes( $attributes, $style ) {
|
409 |
+
if ( ! empty( $style['row_stretch'] ) ) {
|
410 |
+
$attributes['class'][] = 'siteorigin-panels-stretch';
|
411 |
+
$attributes['data-stretch-type'] = $style['row_stretch'];
|
412 |
+
wp_enqueue_script( 'siteorigin-panels-front-styles' );
|
413 |
+
}
|
414 |
+
|
415 |
+
return $attributes;
|
416 |
+
}
|
417 |
+
|
418 |
+
static function vantage_row_style_attributes( $attributes, $style ) {
|
419 |
+
if ( isset( $style['class'] ) && $style['class'] == 'wide-grey' && ! empty( $attributes['style'] ) ) {
|
420 |
+
$attributes['style'] = preg_replace( '/padding-left: 1000px; padding-right: 1000px;/', '', $attributes['style'] );
|
421 |
+
}
|
422 |
+
|
423 |
+
return $attributes;
|
424 |
+
}
|
425 |
+
|
426 |
+
/**
|
427 |
+
* Get the CSS styles that apply to all rows, cells and widgets
|
428 |
+
*
|
429 |
+
* @param $css
|
430 |
+
* @param $style
|
431 |
+
*
|
432 |
+
* @return mixed
|
433 |
+
*/
|
434 |
+
static function general_style_css( $css, $style ){
|
435 |
+
|
436 |
+
if ( ! empty( $style['background'] ) ) {
|
437 |
+
$css[ 'background-color' ] = $style['background'];
|
438 |
+
}
|
439 |
+
|
440 |
+
if ( ! empty( $style['background_display'] ) &&
|
441 |
+
! ( empty( $style['background_image_attachment'] ) && empty( $style['background_image_attachment_fallback'] ) )
|
442 |
+
) {
|
443 |
+
$url = self::get_attachment_image_src( $style['background_image_attachment'], 'full' );
|
444 |
+
|
445 |
+
if ( empty( $url ) && ! empty( $style['background_image_attachment_fallback'] ) ) {
|
446 |
+
$url = $style['background_image_attachment_fallback'];
|
447 |
+
}
|
448 |
+
|
449 |
+
if ( ! empty( $url ) ) {
|
450 |
+
$css['background-image'] = 'url(' .( is_array( $url ) ? $url[0] : $url ) . ')';
|
451 |
+
|
452 |
+
switch ( $style['background_display'] ) {
|
453 |
+
case 'parallax':
|
454 |
+
case 'parallax-original':
|
455 |
+
$css[ 'background-position' ] = 'center center';
|
456 |
+
$css[ 'background-repeat' ] = 'no-repeat';
|
457 |
+
break;
|
458 |
+
case 'tile':
|
459 |
+
$css[ 'background-repeat' ] = 'repeat';
|
460 |
+
break;
|
461 |
+
case 'cover':
|
462 |
+
$css[ 'background-position' ] = 'center center';
|
463 |
+
$css[ 'background-size' ] = 'cover';
|
464 |
+
break;
|
465 |
+
case 'contain':
|
466 |
+
$css[ 'background-size' ] = 'contain';
|
467 |
+
break;
|
468 |
+
case 'center':
|
469 |
+
$css[ 'background-position' ] = 'center center';
|
470 |
+
$css[ 'background-repeat' ] = 'no-repeat';
|
471 |
+
break;
|
472 |
+
case 'fixed':
|
473 |
+
$css[ 'background-attachment' ] = 'fixed';
|
474 |
+
$css[ 'background-position' ] = 'center center';
|
475 |
+
$css[ 'background-size' ] = 'cover';
|
476 |
+
break;
|
477 |
+
}
|
478 |
+
}
|
479 |
+
}
|
480 |
+
|
481 |
+
if ( ! empty( $style[ 'border_color' ] ) ) {
|
482 |
+
$css[ 'border' ] = '1px solid ' . $style['border_color'];
|
483 |
+
}
|
484 |
+
|
485 |
+
if ( ! empty( $style[ 'font_color' ] ) ) {
|
486 |
+
$css[ 'color' ] = $style['font_color'];
|
487 |
+
}
|
488 |
+
|
489 |
+
if( ! empty( $style[ 'padding' ] ) ) {
|
490 |
+
$css['padding'] = $style[ 'padding' ];
|
491 |
+
}
|
492 |
+
|
493 |
+
// Find which key the CSS is stored in
|
494 |
+
foreach( array( 'row_css', 'cell_css', 'widget_css', '' ) as $css_key ) {
|
495 |
+
if( empty( $css_key ) || ! empty( $style[ $css_key ] ) ) {
|
496 |
+
break;
|
497 |
+
}
|
498 |
+
}
|
499 |
+
if ( ! empty( $css_key ) && ! empty( $style[ $css_key ] ) ) {
|
500 |
+
preg_match_all( '/^([A-Za-z0-9\-]+?):(.+?);?$/m', $style[ $css_key ], $matches );
|
501 |
+
|
502 |
+
if ( ! empty( $matches[0] ) ) {
|
503 |
+
for ( $i = 0; $i < count( $matches[0] ); $i ++ ) {
|
504 |
+
$css[ $matches[1][ $i ] ] = $matches[2][ $i ];
|
505 |
+
}
|
506 |
+
}
|
507 |
+
}
|
508 |
+
|
509 |
+
return $css;
|
510 |
+
}
|
511 |
+
|
512 |
+
/**
|
513 |
+
* Get the mobile styling for rows, cells and widgets
|
514 |
+
*
|
515 |
+
* @param $css
|
516 |
+
* @param $style
|
517 |
+
*
|
518 |
+
* @return mixed
|
519 |
+
*/
|
520 |
+
static function general_style_mobile_css( $css, $style ){
|
521 |
+
if( ! empty( $style['mobile_padding'] ) ) {
|
522 |
+
$css['padding'] = $style[ 'mobile_padding' ];
|
523 |
+
}
|
524 |
+
|
525 |
+
if ( ! empty( $style['background_display'] ) &&
|
526 |
+
$style['background_display'] == 'fixed' &&
|
527 |
+
! ( empty( $style['background_image_attachment'] ) && empty( $style['background_image_attachment_fallback'] ) )
|
528 |
+
) {
|
529 |
+
$css[ 'background-attachment' ] = 'scroll';
|
530 |
+
}
|
531 |
+
|
532 |
+
if ( ! empty( $style[ 'mobile_css' ] ) ) {
|
533 |
+
preg_match_all( '/^([A-Za-z0-9\-]+?):(.+?);?$/m', $style[ 'mobile_css' ], $matches );
|
534 |
+
|
535 |
+
if ( ! empty( $matches[0] ) ) {
|
536 |
+
for ( $i = 0; $i < count( $matches[0] ); $i ++ ) {
|
537 |
+
$css[ $matches[1][ $i ] ] = $matches[2][ $i ];
|
538 |
+
}
|
539 |
+
}
|
540 |
+
}
|
541 |
+
|
542 |
+
return $css;
|
543 |
+
}
|
544 |
+
|
545 |
+
/**
|
546 |
+
* @param SiteOrigin_Panels_Css_Builder $css
|
547 |
+
* @param $panels_data
|
548 |
+
* @param $post_id
|
549 |
+
*
|
550 |
+
* @return mixed
|
551 |
+
*/
|
552 |
+
static function filter_css_object( $css, $panels_data, $post_id, $layout ) {
|
553 |
+
$mobile_width = siteorigin_panels_setting( 'mobile-width' );
|
554 |
+
if( empty( $layout ) ) {
|
555 |
+
return $css;
|
556 |
+
}
|
557 |
+
|
558 |
+
foreach( $layout as $ri => $row ) {
|
559 |
+
if( empty( $row[ 'style' ] ) ) $row[ 'style' ] = array();
|
560 |
+
|
561 |
+
$standard_css = apply_filters( 'siteorigin_panels_row_style_css', array(), $row['style'] );
|
562 |
+
$mobile_css = apply_filters( 'siteorigin_panels_row_style_mobile_css', array(), $row['style'] );
|
563 |
+
|
564 |
+
if ( ! empty( $standard_css ) ) {
|
565 |
+
$css->add_row_css(
|
566 |
+
$post_id,
|
567 |
+
$ri,
|
568 |
+
'> .panel-row-style',
|
569 |
+
$standard_css
|
570 |
+
);
|
571 |
+
}
|
572 |
+
if ( ! empty( $mobile_css ) ) {
|
573 |
+
$css->add_row_css(
|
574 |
+
$post_id,
|
575 |
+
$ri,
|
576 |
+
'> .panel-row-style',
|
577 |
+
$mobile_css,
|
578 |
+
$mobile_width
|
579 |
+
);
|
580 |
+
}
|
581 |
+
|
582 |
+
// Add in flexbox alignment to the main row element
|
583 |
+
if ( siteorigin_panels_setting( 'legacy-layout' ) != 'always' && ! SiteOrigin_Panels::is_legacy_browser() && ! empty( $row['style']['cell_alignment'] ) ) {
|
584 |
+
$css->add_row_css(
|
585 |
+
$post_id,
|
586 |
+
$ri,
|
587 |
+
array( '.panel-no-style', '.panel-has-style > .panel-row-style' ),
|
588 |
+
array(
|
589 |
+
'-webkit-align-items' => $row['style']['cell_alignment'],
|
590 |
+
'align-items' => $row['style']['cell_alignment'],
|
591 |
+
)
|
592 |
+
);
|
593 |
+
}
|
594 |
+
|
595 |
+
// Process the cells if there are any
|
596 |
+
if( empty( $row[ 'cells' ] ) ) continue;
|
597 |
+
|
598 |
+
foreach( $row[ 'cells' ] as $ci => $cell ) {
|
599 |
+
if( empty( $cell[ 'style' ] ) ) $cell[ 'style' ] = array();
|
600 |
+
|
601 |
+
$standard_css = apply_filters( 'siteorigin_panels_cell_style_css', array(), $cell['style'] );
|
602 |
+
$mobile_css = apply_filters( 'siteorigin_panels_cell_style_mobile_css', array(), $cell['style'] );
|
603 |
+
|
604 |
+
if ( ! empty( $standard_css ) ) {
|
605 |
+
$css->add_cell_css(
|
606 |
+
$post_id,
|
607 |
+
$ri,
|
608 |
+
$ci,
|
609 |
+
'> .panel-cell-style',
|
610 |
+
$standard_css
|
611 |
+
);
|
612 |
+
}
|
613 |
+
if ( ! empty( $mobile_css ) ) {
|
614 |
+
$css->add_cell_css(
|
615 |
+
$post_id,
|
616 |
+
$ri,
|
617 |
+
$ci,
|
618 |
+
'> .panel-cell-style',
|
619 |
+
$mobile_css,
|
620 |
+
$mobile_width
|
621 |
+
);
|
622 |
+
}
|
623 |
+
|
624 |
+
if ( ! empty( $cell[ 'style' ]['vertical_alignment'] ) ) {
|
625 |
+
$css->add_cell_css(
|
626 |
+
$post_id,
|
627 |
+
$ri,
|
628 |
+
$ci,
|
629 |
+
'',
|
630 |
+
array(
|
631 |
+
'align-self' => $cell[ 'style' ]['vertical_alignment']
|
632 |
+
)
|
633 |
+
);
|
634 |
+
}
|
635 |
+
|
636 |
+
// Process the widgets if there are any
|
637 |
+
if( empty( $cell[ 'widgets' ] ) ) continue;
|
638 |
+
|
639 |
+
foreach( $cell['widgets'] as $wi => $widget ) {
|
640 |
+
if ( empty( $widget['panels_info'] ) ) continue;
|
641 |
+
if ( empty( $widget['panels_info']['style'] ) ) $widget['panels_info']['style'] = array();
|
642 |
+
|
643 |
+
$standard_css = apply_filters( 'siteorigin_panels_widget_style_css', array(), $widget['panels_info']['style'] );
|
644 |
+
$mobile_css = apply_filters( 'siteorigin_panels_widget_style_mobile_css', array(), $widget['panels_info']['style'] );
|
645 |
+
|
646 |
+
if( ! empty( $standard_css ) ) {
|
647 |
+
$css->add_widget_css(
|
648 |
+
$post_id,
|
649 |
+
$ri,
|
650 |
+
$ci,
|
651 |
+
$wi,
|
652 |
+
'> .panel-widget-style',
|
653 |
+
$standard_css
|
654 |
+
);
|
655 |
+
}
|
656 |
+
|
657 |
+
if( ! empty( $mobile_css ) ) {
|
658 |
+
$css->add_widget_css(
|
659 |
+
$post_id,
|
660 |
+
$ri,
|
661 |
+
$ci,
|
662 |
+
$wi,
|
663 |
+
'> .panel-widget-style',
|
664 |
+
$mobile_css,
|
665 |
+
$mobile_width
|
666 |
+
);
|
667 |
+
}
|
668 |
+
|
669 |
+
if ( ! empty( $widget['panels_info']['style']['link_color'] ) ) {
|
670 |
+
$css->add_widget_css( $post_id, $ri, $ci, $wi, ' a', array(
|
671 |
+
'color' => $widget['panels_info']['style']['link_color']
|
672 |
+
) );
|
673 |
+
}
|
674 |
+
}
|
675 |
+
}
|
676 |
+
}
|
677 |
+
|
678 |
+
return $css;
|
679 |
+
}
|
680 |
+
|
681 |
+
/**
|
682 |
+
* Add in custom styles for the row's bottom margin
|
683 |
+
*
|
684 |
+
* @param $margin
|
685 |
+
* @param $grid
|
686 |
+
*
|
687 |
+
* @return mixed
|
688 |
+
*/
|
689 |
+
static function filter_row_bottom_margin( $margin, $grid ) {
|
690 |
+
if ( ! empty( $grid['style']['bottom_margin'] ) ) {
|
691 |
+
$margin = $grid['style']['bottom_margin'];
|
692 |
+
}
|
693 |
+
|
694 |
+
return $margin;
|
695 |
+
}
|
696 |
+
|
697 |
+
/**
|
698 |
+
* Add in custom styles for a row's mobile bottom margin
|
699 |
+
*
|
700 |
+
* @param $margin
|
701 |
+
* @param $grid
|
702 |
+
*
|
703 |
+
* @return mixed
|
704 |
+
*/
|
705 |
+
static function filter_row_mobile_bottom_margin( $margin, $grid ) {
|
706 |
+
if ( ! empty( $grid['style']['mobile_bottom_margin'] ) ) {
|
707 |
+
$margin = $grid['style']['mobile_bottom_margin'];
|
708 |
+
}
|
709 |
+
|
710 |
+
return $margin;
|
711 |
+
}
|
712 |
+
|
713 |
+
static function filter_row_gutter( $gutter, $grid ) {
|
714 |
+
if ( ! empty( $grid['style']['gutter'] ) ) {
|
715 |
+
$gutter = $grid['style']['gutter'];
|
716 |
+
}
|
717 |
+
|
718 |
+
return $gutter;
|
719 |
+
}
|
720 |
+
|
721 |
+
/**
|
722 |
+
* Adds widget specific styles not included in the general style fields.
|
723 |
+
*
|
724 |
+
* @param $widget_css The CSS properties and values
|
725 |
+
* @param $widget_style_data The style settings as obtained from the style fields.
|
726 |
+
*
|
727 |
+
* @return mixed
|
728 |
+
*/
|
729 |
+
static function filter_widget_style_css( $widget_css, $widget_style_data ) {
|
730 |
+
if ( ! empty( $widget_style_data['margin'] ) ) {
|
731 |
+
$widget_css['margin'] = $widget_style_data['margin'];
|
732 |
+
}
|
733 |
+
|
734 |
+
return $widget_css;
|
735 |
+
}
|
736 |
+
|
737 |
+
public static function get_attachment_image_src( $image, $size = 'full' ){
|
738 |
+
if( empty( $image ) ) {
|
739 |
+
return false;
|
740 |
+
}
|
741 |
+
else if( is_numeric( $image ) ) {
|
742 |
+
return wp_get_attachment_image_src( $image, $size );
|
743 |
+
}
|
744 |
+
else if( is_string( $image ) ) {
|
745 |
+
preg_match( '/(.*?)\#([0-9]+)x([0-9]+)$/', $image, $matches );
|
746 |
+
return ! empty( $matches ) ? $matches : false;
|
747 |
+
}
|
748 |
+
}
|
749 |
+
|
750 |
+
}
|
inc/widget-shortcode.php
CHANGED
@@ -1,122 +1,122 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class SiteOrigin_Panels_Widget_Shortcode {
|
4 |
-
|
5 |
-
static $text_widgets = array(
|
6 |
-
'SiteOrigin_Widget_Editor_Widget',
|
7 |
-
'SiteOrigin_Panels_Widgets_Layout',
|
8 |
-
'WP_Widget_Black_Studio_TinyMCE',
|
9 |
-
'WP_Widget_Text',
|
10 |
-
);
|
11 |
-
|
12 |
-
static function init() {
|
13 |
-
add_shortcode( 'siteorigin_widget', 'SiteOrigin_Panels_Widget_Shortcode::shortcode' );
|
14 |
-
}
|
15 |
-
|
16 |
-
static function add_filters() {
|
17 |
-
add_filter( 'siteorigin_panels_the_widget_html', 'SiteOrigin_Panels_Widget_Shortcode::widget_html', 10, 4 );
|
18 |
-
}
|
19 |
-
|
20 |
-
static function remove_filters(){
|
21 |
-
remove_filter( 'siteorigin_panels_the_widget_html', 'SiteOrigin_Panels_Widget_Shortcode::widget_html' );
|
22 |
-
}
|
23 |
-
|
24 |
-
/**
|
25 |
-
* This shortcode just displays a widget based on the given arguments
|
26 |
-
*
|
27 |
-
* @param $attr
|
28 |
-
* @param $content
|
29 |
-
*
|
30 |
-
* @return string
|
31 |
-
*/
|
32 |
-
static function shortcode( $attr, $content ){
|
33 |
-
$attr = shortcode_atts( array(
|
34 |
-
'class' => false,
|
35 |
-
'id' => '',
|
36 |
-
), $attr, 'siteorigin_widget' );
|
37 |
-
|
38 |
-
$attr[ 'class' ] = html_entity_decode( $attr[ 'class' ] );
|
39 |
-
$attr[ 'class' ] = apply_filters( 'siteorigin_panels_widget_class', $attr[ 'class' ] );
|
40 |
-
|
41 |
-
$the_widget = ! empty( $attr[ 'class' ] ) ? SiteOrigin_Panels::get_widget_instance( $attr['class'] ) : null;
|
42 |
-
if( ! empty( $the_widget ) ) {
|
43 |
-
|
44 |
-
$data = self::decode_data( $content );
|
45 |
-
|
46 |
-
$widget_args = ! empty( $data[ 'args' ] ) ? $data[ 'args' ] : array();
|
47 |
-
$widget_instance = ! empty( $data[ 'instance' ] ) ? $data[ 'instance' ] : array();
|
48 |
-
|
49 |
-
$widget_args = wp_parse_args( array(
|
50 |
-
'before_widget' => '',
|
51 |
-
'after_widget' => '',
|
52 |
-
'before_title' => '<h3 class="widget-title">',
|
53 |
-
'after_title' => '</h3>',
|
54 |
-
), $widget_args );
|
55 |
-
|
56 |
-
ob_start();
|
57 |
-
$the_widget->widget( $widget_args, $widget_instance );
|
58 |
-
return ob_get_clean();
|
59 |
-
}
|
60 |
-
}
|
61 |
-
|
62 |
-
/**
|
63 |
-
* Get the shortcode for a specific widget
|
64 |
-
*
|
65 |
-
* @param $widget
|
66 |
-
* @param $args
|
67 |
-
* @param $instance
|
68 |
-
*
|
69 |
-
* @return string
|
70 |
-
*/
|
71 |
-
static function get_shortcode( $widget, $args, $instance ){
|
72 |
-
unset( $instance[ 'panels_info' ] );
|
73 |
-
|
74 |
-
$data = array(
|
75 |
-
'instance' => $instance,
|
76 |
-
'args' => $args,
|
77 |
-
);
|
78 |
-
|
79 |
-
// This allows other plugins to implement their own shortcode. For example, to work when Page Builder isn't active
|
80 |
-
$shortcode_name = apply_filters( 'siteorigin_panels_cache_shortcode', 'siteorigin_widget', $widget, $instance, $args );
|
81 |
-
|
82 |
-
$shortcode = '[' . $shortcode_name . ' ';
|
83 |
-
$shortcode .= 'class="' . htmlentities( preg_replace( '/\\\\+/', '\\\\\\\\', get_class( $widget ) ) ) . '"]';
|
84 |
-
$shortcode .= self::encode_data( $data ) ;
|
85 |
-
$shortcode .= '[/' . $shortcode_name . ']';
|
86 |
-
|
87 |
-
return $shortcode;
|
88 |
-
}
|
89 |
-
|
90 |
-
/**
|
91 |
-
* A filter to replace widgets with
|
92 |
-
*/
|
93 |
-
static function widget_html( $html, $widget, $args, $instance ){
|
94 |
-
if(
|
95 |
-
empty( $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] ) ||
|
96 |
-
// Don't try create HTML if there already is some
|
97 |
-
! empty( $html ) ||
|
98 |
-
! is_object( $widget ) ||
|
99 |
-
// Skip for known text based widgets
|
100 |
-
in_array( get_class( $widget ), self::$text_widgets )
|
101 |
-
) {
|
102 |
-
return $html;
|
103 |
-
}
|
104 |
-
|
105 |
-
return self::get_shortcode( $widget, $args, $instance );
|
106 |
-
}
|
107 |
-
|
108 |
-
static function encode_data( $data ){
|
109 |
-
return '<input type="hidden" value="' . htmlentities( json_encode( $data ), ENT_QUOTES ) . '" />';
|
110 |
-
}
|
111 |
-
|
112 |
-
static function decode_data( $string ){
|
113 |
-
preg_match( '/value="([^"]*)"/', trim( $string ), $matches );
|
114 |
-
if( ! empty( $matches[1] ) ) {
|
115 |
-
$data = json_decode( html_entity_decode( $matches[1], ENT_QUOTES ), true );
|
116 |
-
return $data;
|
117 |
-
}
|
118 |
-
else {
|
119 |
-
return array();
|
120 |
-
}
|
121 |
-
}
|
122 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class SiteOrigin_Panels_Widget_Shortcode {
|
4 |
+
|
5 |
+
static $text_widgets = array(
|
6 |
+
'SiteOrigin_Widget_Editor_Widget',
|
7 |
+
'SiteOrigin_Panels_Widgets_Layout',
|
8 |
+
'WP_Widget_Black_Studio_TinyMCE',
|
9 |
+
'WP_Widget_Text',
|
10 |
+
);
|
11 |
+
|
12 |
+
static function init() {
|
13 |
+
add_shortcode( 'siteorigin_widget', 'SiteOrigin_Panels_Widget_Shortcode::shortcode' );
|
14 |
+
}
|
15 |
+
|
16 |
+
static function add_filters() {
|
17 |
+
add_filter( 'siteorigin_panels_the_widget_html', 'SiteOrigin_Panels_Widget_Shortcode::widget_html', 10, 4 );
|
18 |
+
}
|
19 |
+
|
20 |
+
static function remove_filters(){
|
21 |
+
remove_filter( 'siteorigin_panels_the_widget_html', 'SiteOrigin_Panels_Widget_Shortcode::widget_html' );
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* This shortcode just displays a widget based on the given arguments
|
26 |
+
*
|
27 |
+
* @param $attr
|
28 |
+
* @param $content
|
29 |
+
*
|
30 |
+
* @return string
|
31 |
+
*/
|
32 |
+
static function shortcode( $attr, $content ){
|
33 |
+
$attr = shortcode_atts( array(
|
34 |
+
'class' => false,
|
35 |
+
'id' => '',
|
36 |
+
), $attr, 'siteorigin_widget' );
|
37 |
+
|
38 |
+
$attr[ 'class' ] = html_entity_decode( $attr[ 'class' ] );
|
39 |
+
$attr[ 'class' ] = apply_filters( 'siteorigin_panels_widget_class', $attr[ 'class' ] );
|
40 |
+
|
41 |
+
$the_widget = ! empty( $attr[ 'class' ] ) ? SiteOrigin_Panels::get_widget_instance( $attr['class'] ) : null;
|
42 |
+
if( ! empty( $the_widget ) ) {
|
43 |
+
|
44 |
+
$data = self::decode_data( $content );
|
45 |
+
|
46 |
+
$widget_args = ! empty( $data[ 'args' ] ) ? $data[ 'args' ] : array();
|
47 |
+
$widget_instance = ! empty( $data[ 'instance' ] ) ? $data[ 'instance' ] : array();
|
48 |
+
|
49 |
+
$widget_args = wp_parse_args( array(
|
50 |
+
'before_widget' => '',
|
51 |
+
'after_widget' => '',
|
52 |
+
'before_title' => '<h3 class="widget-title">',
|
53 |
+
'after_title' => '</h3>',
|
54 |
+
), $widget_args );
|
55 |
+
|
56 |
+
ob_start();
|
57 |
+
$the_widget->widget( $widget_args, $widget_instance );
|
58 |
+
return ob_get_clean();
|
59 |
+
}
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Get the shortcode for a specific widget
|
64 |
+
*
|
65 |
+
* @param $widget
|
66 |
+
* @param $args
|
67 |
+
* @param $instance
|
68 |
+
*
|
69 |
+
* @return string
|
70 |
+
*/
|
71 |
+
static function get_shortcode( $widget, $args, $instance ){
|
72 |
+
unset( $instance[ 'panels_info' ] );
|
73 |
+
|
74 |
+
$data = array(
|
75 |
+
'instance' => $instance,
|
76 |
+
'args' => $args,
|
77 |
+
);
|
78 |
+
|
79 |
+
// This allows other plugins to implement their own shortcode. For example, to work when Page Builder isn't active
|
80 |
+
$shortcode_name = apply_filters( 'siteorigin_panels_cache_shortcode', 'siteorigin_widget', $widget, $instance, $args );
|
81 |
+
|
82 |
+
$shortcode = '[' . $shortcode_name . ' ';
|
83 |
+
$shortcode .= 'class="' . htmlentities( preg_replace( '/\\\\+/', '\\\\\\\\', get_class( $widget ) ) ) . '"]';
|
84 |
+
$shortcode .= self::encode_data( $data ) ;
|
85 |
+
$shortcode .= '[/' . $shortcode_name . ']';
|
86 |
+
|
87 |
+
return $shortcode;
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* A filter to replace widgets with
|
92 |
+
*/
|
93 |
+
static function widget_html( $html, $widget, $args, $instance ){
|
94 |
+
if(
|
95 |
+
empty( $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] ) ||
|
96 |
+
// Don't try create HTML if there already is some
|
97 |
+
! empty( $html ) ||
|
98 |
+
! is_object( $widget ) ||
|
99 |
+
// Skip for known text based widgets
|
100 |
+
in_array( get_class( $widget ), self::$text_widgets )
|
101 |
+
) {
|
102 |
+
return $html;
|
103 |
+
}
|
104 |
+
|
105 |
+
return self::get_shortcode( $widget, $args, $instance );
|
106 |
+
}
|
107 |
+
|
108 |
+
static function encode_data( $data ){
|
109 |
+
return '<input type="hidden" value="' . htmlentities( json_encode( $data ), ENT_QUOTES ) . '" />';
|
110 |
+
}
|
111 |
+
|
112 |
+
static function decode_data( $string ){
|
113 |
+
preg_match( '/value="([^"]*)"/', trim( $string ), $matches );
|
114 |
+
if( ! empty( $matches[1] ) ) {
|
115 |
+
$data = json_decode( html_entity_decode( $matches[1], ENT_QUOTES ), true );
|
116 |
+
return $data;
|
117 |
+
}
|
118 |
+
else {
|
119 |
+
return array();
|
120 |
+
}
|
121 |
+
}
|
122 |
+
}
|
inc/widgets/layout.php
CHANGED
@@ -1,134 +1,134 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* This widget give you the full Page Builder interface inside a widget. Fully nestable.
|
5 |
-
*
|
6 |
-
* Class SiteOrigin_Panels_Widgets_Builder
|
7 |
-
*/
|
8 |
-
class SiteOrigin_Panels_Widgets_Layout extends WP_Widget {
|
9 |
-
function __construct() {
|
10 |
-
parent::__construct(
|
11 |
-
'siteorigin-panels-builder',
|
12 |
-
// TRANSLATORS: This is the name of a widget
|
13 |
-
__( 'Layout Builder', 'siteorigin-panels' ),
|
14 |
-
array(
|
15 |
-
'description' => __( 'A complete SiteOrigin Page Builder layout as a widget.', 'siteorigin-panels' ),
|
16 |
-
'panels_title' => false,
|
17 |
-
),
|
18 |
-
array(
|
19 |
-
)
|
20 |
-
);
|
21 |
-
}
|
22 |
-
|
23 |
-
function widget($args, $instance) {
|
24 |
-
if( empty($instance['panels_data']) ) return;
|
25 |
-
|
26 |
-
if( is_string( $instance['panels_data'] ) ) {
|
27 |
-
$instance['panels_data'] = json_decode( $instance['panels_data'], true );
|
28 |
-
}
|
29 |
-
if(empty($instance['panels_data']['widgets'])) return;
|
30 |
-
|
31 |
-
if( ! empty( $instance['panels_data']['widgets'] ) ) {
|
32 |
-
foreach( $instance['panels_data']['widgets'] as & $widget ) {
|
33 |
-
$widget['panels_info']['class'] = str_replace( '\', '\\', $widget['panels_info']['class'] );
|
34 |
-
}
|
35 |
-
}
|
36 |
-
|
37 |
-
if( empty( $instance['builder_id'] ) ) $instance['builder_id'] = uniqid();
|
38 |
-
|
39 |
-
echo $args['before_widget'];
|
40 |
-
$is_content_render = ! empty( $GLOBALS['SITEORIGIN_PANELS_POST_CONTENT_RENDER'] ) &&
|
41 |
-
siteorigin_panels_setting( 'copy-styles' );
|
42 |
-
$is_preview_render = ! empty( $GLOBALS['SITEORIGIN_PANELS_PREVIEW_RENDER'] );
|
43 |
-
|
44 |
-
echo SiteOrigin_Panels::renderer()->render(
|
45 |
-
'w'.$instance['builder_id'],
|
46 |
-
true,
|
47 |
-
$instance['panels_data'],
|
48 |
-
$layout_data,
|
49 |
-
$is_content_render || $is_preview_render
|
50 |
-
);
|
51 |
-
echo $args['after_widget'];
|
52 |
-
}
|
53 |
-
|
54 |
-
function update($new, $old) {
|
55 |
-
$new['builder_id'] = uniqid();
|
56 |
-
|
57 |
-
if( is_string($new['panels_data']) && ! empty( $new['panels_data'] ) ) {
|
58 |
-
// This is still in a string format, so we'll convert it to an array for sanitization
|
59 |
-
$new['panels_data'] = json_decode( $new['panels_data'], true );
|
60 |
-
}
|
61 |
-
|
62 |
-
if ( ! empty( $new['panels_data'] ) ) {
|
63 |
-
if ( ! empty( $new['panels_data']['widgets'] ) ) {
|
64 |
-
$new['panels_data']['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets(
|
65 |
-
$new['panels_data']['widgets'],
|
66 |
-
! empty( $old['panels_data']['widgets'] ) ? $old['panels_data']['widgets'] : false
|
67 |
-
);
|
68 |
-
foreach( $new['panels_data']['widgets'] as & $widget ) {
|
69 |
-
$widget['panels_info']['class'] = str_replace( '\\', '\', $widget['panels_info']['class'] );
|
70 |
-
}
|
71 |
-
}
|
72 |
-
|
73 |
-
$new['panels_data'] = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $new['panels_data'] );
|
74 |
-
}
|
75 |
-
|
76 |
-
return $new;
|
77 |
-
}
|
78 |
-
|
79 |
-
function form( $instance ){
|
80 |
-
|
81 |
-
if ( ! is_admin() ) {
|
82 |
-
?>
|
83 |
-
<p>
|
84 |
-
<?php _e( 'This widget can currently only be used in the WordPress admin interface.', 'siteorigin-panels' ) ?>
|
85 |
-
</p>
|
86 |
-
<?php
|
87 |
-
return;
|
88 |
-
}
|
89 |
-
|
90 |
-
$instance = wp_parse_args($instance, array(
|
91 |
-
'panels_data' => '',
|
92 |
-
'builder_id' => uniqid(),
|
93 |
-
) );
|
94 |
-
$form_id = uniqid();
|
95 |
-
|
96 |
-
if( ! empty( $instance['panels_data']['widgets'] ) ) {
|
97 |
-
foreach( $instance['panels_data']['widgets'] as & $widget ) {
|
98 |
-
$widget['panels_info']['class'] = str_replace( '\', '\\', $widget['panels_info']['class'] );
|
99 |
-
}
|
100 |
-
}
|
101 |
-
|
102 |
-
if( ! is_string( $instance['panels_data'] ) ) {
|
103 |
-
$instance['panels_data'] = json_encode( $instance['panels_data'] );
|
104 |
-
}
|
105 |
-
|
106 |
-
?>
|
107 |
-
<div class="siteorigin-page-builder-widget" id="siteorigin-page-builder-widget-<?php echo esc_attr( $form_id ) ?>" data-builder-id="<?php echo esc_attr( $form_id ) ?>" data-type="layout_widget">
|
108 |
-
<p>
|
109 |
-
<button class="button-secondary siteorigin-panels-display-builder" ><?php _e('Open Builder', 'siteorigin-panels') ?></button>
|
110 |
-
</p>
|
111 |
-
|
112 |
-
<input type="hidden" data-panels-filter="json_parse" value="" class="panels-data" name="<?php echo $this->get_field_name('panels_data') ?>" id="<?php echo $this->get_field_id('panels_data') ?>" />
|
113 |
-
|
114 |
-
<script type="text/javascript">
|
115 |
-
( function( panelsData ){
|
116 |
-
// Create the panels_data input
|
117 |
-
document.getElementById('<?php echo $this->get_field_id('panels_data') ?>').value = JSON.stringify( panelsData );
|
118 |
-
} )( <?php echo $instance['panels_data']; ?> );
|
119 |
-
</script>
|
120 |
-
|
121 |
-
<input type="hidden" value="<?php echo esc_attr( $instance['builder_id'] ) ?>" name="<?php echo $this->get_field_name('builder_id') ?>" />
|
122 |
-
</div>
|
123 |
-
<script type="text/javascript">
|
124 |
-
if(
|
125 |
-
typeof jQuery.fn.soPanelsSetupBuilderWidget != 'undefined' &&
|
126 |
-
( ! jQuery('body').hasClass('wp-customizer') || jQuery( "#siteorigin-page-builder-widget-<?php echo esc_attr( $form_id ) ?>").closest( '.panel-dialog' ).length )
|
127 |
-
) {
|
128 |
-
jQuery( "#siteorigin-page-builder-widget-<?php echo esc_attr( $form_id ) ?>").soPanelsSetupBuilderWidget();
|
129 |
-
}
|
130 |
-
</script>
|
131 |
-
<?php
|
132 |
-
}
|
133 |
-
|
134 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* This widget give you the full Page Builder interface inside a widget. Fully nestable.
|
5 |
+
*
|
6 |
+
* Class SiteOrigin_Panels_Widgets_Builder
|
7 |
+
*/
|
8 |
+
class SiteOrigin_Panels_Widgets_Layout extends WP_Widget {
|
9 |
+
function __construct() {
|
10 |
+
parent::__construct(
|
11 |
+
'siteorigin-panels-builder',
|
12 |
+
// TRANSLATORS: This is the name of a widget
|
13 |
+
__( 'Layout Builder', 'siteorigin-panels' ),
|
14 |
+
array(
|
15 |
+
'description' => __( 'A complete SiteOrigin Page Builder layout as a widget.', 'siteorigin-panels' ),
|
16 |
+
'panels_title' => false,
|
17 |
+
),
|
18 |
+
array(
|
19 |
+
)
|
20 |
+
);
|
21 |
+
}
|
22 |
+
|
23 |
+
function widget($args, $instance) {
|
24 |
+
if( empty($instance['panels_data']) ) return;
|
25 |
+
|
26 |
+
if( is_string( $instance['panels_data'] ) ) {
|
27 |
+
$instance['panels_data'] = json_decode( $instance['panels_data'], true );
|
28 |
+
}
|
29 |
+
if(empty($instance['panels_data']['widgets'])) return;
|
30 |
+
|
31 |
+
if( ! empty( $instance['panels_data']['widgets'] ) ) {
|
32 |
+
foreach( $instance['panels_data']['widgets'] as & $widget ) {
|
33 |
+
$widget['panels_info']['class'] = str_replace( '\', '\\', $widget['panels_info']['class'] );
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
if( empty( $instance['builder_id'] ) ) $instance['builder_id'] = uniqid();
|
38 |
+
|
39 |
+
echo $args['before_widget'];
|
40 |
+
$is_content_render = ! empty( $GLOBALS['SITEORIGIN_PANELS_POST_CONTENT_RENDER'] ) &&
|
41 |
+
siteorigin_panels_setting( 'copy-styles' );
|
42 |
+
$is_preview_render = ! empty( $GLOBALS['SITEORIGIN_PANELS_PREVIEW_RENDER'] );
|
43 |
+
|
44 |
+
echo SiteOrigin_Panels::renderer()->render(
|
45 |
+
'w'.$instance['builder_id'],
|
46 |
+
true,
|
47 |
+
$instance['panels_data'],
|
48 |
+
$layout_data,
|
49 |
+
$is_content_render || $is_preview_render
|
50 |
+
);
|
51 |
+
echo $args['after_widget'];
|
52 |
+
}
|
53 |
+
|
54 |
+
function update($new, $old) {
|
55 |
+
$new['builder_id'] = uniqid();
|
56 |
+
|
57 |
+
if( is_string($new['panels_data']) && ! empty( $new['panels_data'] ) ) {
|
58 |
+
// This is still in a string format, so we'll convert it to an array for sanitization
|
59 |
+
$new['panels_data'] = json_decode( $new['panels_data'], true );
|
60 |
+
}
|
61 |
+
|
62 |
+
if ( ! empty( $new['panels_data'] ) ) {
|
63 |
+
if ( ! empty( $new['panels_data']['widgets'] ) ) {
|
64 |
+
$new['panels_data']['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets(
|
65 |
+
$new['panels_data']['widgets'],
|
66 |
+
! empty( $old['panels_data']['widgets'] ) ? $old['panels_data']['widgets'] : false
|
67 |
+
);
|
68 |
+
foreach( $new['panels_data']['widgets'] as & $widget ) {
|
69 |
+
$widget['panels_info']['class'] = str_replace( '\\', '\', $widget['panels_info']['class'] );
|
70 |
+
}
|
71 |
+
}
|
72 |
+
|
73 |
+
$new['panels_data'] = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $new['panels_data'] );
|
74 |
+
}
|
75 |
+
|
76 |
+
return $new;
|
77 |
+
}
|
78 |
+
|
79 |
+
function form( $instance ){
|
80 |
+
|
81 |
+
if ( ! is_admin() ) {
|
82 |
+
?>
|
83 |
+
<p>
|
84 |
+
<?php _e( 'This widget can currently only be used in the WordPress admin interface.', 'siteorigin-panels' ) ?>
|
85 |
+
</p>
|
86 |
+
<?php
|
87 |
+
return;
|
88 |
+
}
|
89 |
+
|
90 |
+
$instance = wp_parse_args($instance, array(
|
91 |
+
'panels_data' => '',
|
92 |
+
'builder_id' => uniqid(),
|
93 |
+
) );
|
94 |
+
$form_id = uniqid();
|
95 |
+
|
96 |
+
if( ! empty( $instance['panels_data']['widgets'] ) ) {
|
97 |
+
foreach( $instance['panels_data']['widgets'] as & $widget ) {
|
98 |
+
$widget['panels_info']['class'] = str_replace( '\', '\\', $widget['panels_info']['class'] );
|
99 |
+
}
|
100 |
+
}
|
101 |
+
|
102 |
+
if( ! is_string( $instance['panels_data'] ) ) {
|
103 |
+
$instance['panels_data'] = json_encode( $instance['panels_data'] );
|
104 |
+
}
|
105 |
+
|
106 |
+
?>
|
107 |
+
<div class="siteorigin-page-builder-widget" id="siteorigin-page-builder-widget-<?php echo esc_attr( $form_id ) ?>" data-builder-id="<?php echo esc_attr( $form_id ) ?>" data-type="layout_widget">
|
108 |
+
<p>
|
109 |
+
<button class="button-secondary siteorigin-panels-display-builder" ><?php _e('Open Builder', 'siteorigin-panels') ?></button>
|
110 |
+
</p>
|
111 |
+
|
112 |
+
<input type="hidden" data-panels-filter="json_parse" value="" class="panels-data" name="<?php echo $this->get_field_name('panels_data') ?>" id="<?php echo $this->get_field_id('panels_data') ?>" />
|
113 |
+
|
114 |
+
<script type="text/javascript">
|
115 |
+
( function( panelsData ){
|
116 |
+
// Create the panels_data input
|
117 |
+
document.getElementById('<?php echo $this->get_field_id('panels_data') ?>').value = JSON.stringify( panelsData );
|
118 |
+
} )( <?php echo $instance['panels_data']; ?> );
|
119 |
+
</script>
|
120 |
+
|
121 |
+
<input type="hidden" value="<?php echo esc_attr( $instance['builder_id'] ) ?>" name="<?php echo $this->get_field_name('builder_id') ?>" />
|
122 |
+
</div>
|
123 |
+
<script type="text/javascript">
|
124 |
+
if(
|
125 |
+
typeof jQuery.fn.soPanelsSetupBuilderWidget != 'undefined' &&
|
126 |
+
( ! jQuery('body').hasClass('wp-customizer') || jQuery( "#siteorigin-page-builder-widget-<?php echo esc_attr( $form_id ) ?>").closest( '.panel-dialog' ).length )
|
127 |
+
) {
|
128 |
+
jQuery( "#siteorigin-page-builder-widget-<?php echo esc_attr( $form_id ) ?>").soPanelsSetupBuilderWidget();
|
129 |
+
}
|
130 |
+
</script>
|
131 |
+
<?php
|
132 |
+
}
|
133 |
+
|
134 |
+
}
|
inc/widgets/post-loop-helper.php
CHANGED
@@ -1,100 +1,100 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* A helper widget for the main SiteOrigin_Panels_Widgets_PostLoop class
|
5 |
-
*
|
6 |
-
* Class SiteOrigin_Panels_Widgets_PostLoop_Helper
|
7 |
-
*/
|
8 |
-
class SiteOrigin_Panels_Widgets_PostLoop_Helper extends SiteOrigin_Widget {
|
9 |
-
|
10 |
-
/**
|
11 |
-
* SiteOrigin_Panels_Widgets_PostLoop_Helper constructor.
|
12 |
-
*
|
13 |
-
* @param array $templates
|
14 |
-
*/
|
15 |
-
function __construct( $templates ) {
|
16 |
-
|
17 |
-
$template_options = array();
|
18 |
-
if( ! empty( $templates ) ) {
|
19 |
-
foreach( $templates as $template ) {
|
20 |
-
$headers = get_file_data( locate_template( $template ), array(
|
21 |
-
'loop_name' => 'Loop Name',
|
22 |
-
) );
|
23 |
-
$template_options[ $template ] = esc_html( ! empty( $headers['loop_name'] ) ? $headers['loop_name'] : $template );
|
24 |
-
}
|
25 |
-
}
|
26 |
-
|
27 |
-
parent::__construct(
|
28 |
-
'siteorigin-panels-postloop-helper',
|
29 |
-
__( 'Post Loop', 'siteorigin-panels' ),
|
30 |
-
array(
|
31 |
-
'description' => __( 'Displays a post loop.', 'siteorigin-panels' ),
|
32 |
-
'has_preview' => false,
|
33 |
-
),
|
34 |
-
array(),
|
35 |
-
array(
|
36 |
-
'title' => array(
|
37 |
-
'type' => 'text',
|
38 |
-
'label' => __( 'Title', 'siteorigin-panels' ),
|
39 |
-
),
|
40 |
-
'template' => array(
|
41 |
-
'type' => 'select',
|
42 |
-
'label' => __( 'Template', 'siteorigin-panels' ),
|
43 |
-
'options' => $template_options,
|
44 |
-
'default' => 'loop.php',
|
45 |
-
),
|
46 |
-
'more' => array(
|
47 |
-
'type' => 'checkbox',
|
48 |
-
'label' => __( 'More link', 'so-widgets-bundle' ),
|
49 |
-
'description' => __( 'If the template supports it, cut posts and display the more link.', 'siteorigin-panels' ),
|
50 |
-
'default' => false,
|
51 |
-
),
|
52 |
-
'posts' => array(
|
53 |
-
'type' => 'posts',
|
54 |
-
'label' => __( 'Posts query', 'so-widgets-bundle' ),
|
55 |
-
'hide' => true
|
56 |
-
),
|
57 |
-
)
|
58 |
-
);
|
59 |
-
}
|
60 |
-
|
61 |
-
/**
|
62 |
-
* Convert this instance into one that's compatible with the posts field
|
63 |
-
*
|
64 |
-
* @param $instance
|
65 |
-
*
|
66 |
-
* @return mixed
|
67 |
-
*/
|
68 |
-
function modify_instance( $instance ) {
|
69 |
-
if( ! empty( $instance['post_type'] ) ) {
|
70 |
-
$value = array();
|
71 |
-
|
72 |
-
if( ! empty( $instance['post_type'] ) ) $value['post_type'] = $instance['post_type'];
|
73 |
-
if( ! empty( $instance['posts_per_page'] ) ) $value['posts_per_page'] = $instance['posts_per_page'];
|
74 |
-
if( ! empty( $instance['order'] ) ) $value['order'] = $instance['order'];
|
75 |
-
if( ! empty( $instance['orderby'] ) ) $value['orderby'] = $instance['orderby'];
|
76 |
-
if( ! empty( $instance['sticky'] ) ) $value['sticky'] = $instance['sticky'];
|
77 |
-
if( ! empty( $instance['additional'] ) ) $value['additional'] = $instance['additional'];
|
78 |
-
$instance[ 'posts' ] = $value;
|
79 |
-
|
80 |
-
unset( $instance[ 'post_type' ] );
|
81 |
-
unset( $instance[ 'posts_per_page' ] );
|
82 |
-
unset( $instance[ 'order' ] );
|
83 |
-
unset( $instance[ 'orderby' ] );
|
84 |
-
unset( $instance[ 'sticky' ] );
|
85 |
-
unset( $instance[ 'additional' ] );
|
86 |
-
}
|
87 |
-
|
88 |
-
return $instance;
|
89 |
-
}
|
90 |
-
|
91 |
-
/**
|
92 |
-
* @param array $args
|
93 |
-
* @param array $instance
|
94 |
-
*
|
95 |
-
* @return bool
|
96 |
-
*/
|
97 |
-
function widget( $args, $instance ) {
|
98 |
-
return false;
|
99 |
-
}
|
100 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* A helper widget for the main SiteOrigin_Panels_Widgets_PostLoop class
|
5 |
+
*
|
6 |
+
* Class SiteOrigin_Panels_Widgets_PostLoop_Helper
|
7 |
+
*/
|
8 |
+
class SiteOrigin_Panels_Widgets_PostLoop_Helper extends SiteOrigin_Widget {
|
9 |
+
|
10 |
+
/**
|
11 |
+
* SiteOrigin_Panels_Widgets_PostLoop_Helper constructor.
|
12 |
+
*
|
13 |
+
* @param array $templates
|
14 |
+
*/
|
15 |
+
function __construct( $templates ) {
|
16 |
+
|
17 |
+
$template_options = array();
|
18 |
+
if( ! empty( $templates ) ) {
|
19 |
+
foreach( $templates as $template ) {
|
20 |
+
$headers = get_file_data( locate_template( $template ), array(
|
21 |
+
'loop_name' => 'Loop Name',
|
22 |
+
) );
|
23 |
+
$template_options[ $template ] = esc_html( ! empty( $headers['loop_name'] ) ? $headers['loop_name'] : $template );
|
24 |
+
}
|
25 |
+
}
|
26 |
+
|
27 |
+
parent::__construct(
|
28 |
+
'siteorigin-panels-postloop-helper',
|
29 |
+
__( 'Post Loop', 'siteorigin-panels' ),
|
30 |
+
array(
|
31 |
+
'description' => __( 'Displays a post loop.', 'siteorigin-panels' ),
|
32 |
+
'has_preview' => false,
|
33 |
+
),
|
34 |
+
array(),
|
35 |
+
array(
|
36 |
+
'title' => array(
|
37 |
+
'type' => 'text',
|
38 |
+
'label' => __( 'Title', 'siteorigin-panels' ),
|
39 |
+
),
|
40 |
+
'template' => array(
|
41 |
+
'type' => 'select',
|
42 |
+
'label' => __( 'Template', 'siteorigin-panels' ),
|
43 |
+
'options' => $template_options,
|
44 |
+
'default' => 'loop.php',
|
45 |
+
),
|
46 |
+
'more' => array(
|
47 |
+
'type' => 'checkbox',
|
48 |
+
'label' => __( 'More link', 'so-widgets-bundle' ),
|
49 |
+
'description' => __( 'If the template supports it, cut posts and display the more link.', 'siteorigin-panels' ),
|
50 |
+
'default' => false,
|
51 |
+
),
|
52 |
+
'posts' => array(
|
53 |
+
'type' => 'posts',
|
54 |
+
'label' => __( 'Posts query', 'so-widgets-bundle' ),
|
55 |
+
'hide' => true
|
56 |
+
),
|
57 |
+
)
|
58 |
+
);
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Convert this instance into one that's compatible with the posts field
|
63 |
+
*
|
64 |
+
* @param $instance
|
65 |
+
*
|
66 |
+
* @return mixed
|
67 |
+
*/
|
68 |
+
function modify_instance( $instance ) {
|
69 |
+
if( ! empty( $instance['post_type'] ) ) {
|
70 |
+
$value = array();
|
71 |
+
|
72 |
+
if( ! empty( $instance['post_type'] ) ) $value['post_type'] = $instance['post_type'];
|
73 |
+
if( ! empty( $instance['posts_per_page'] ) ) $value['posts_per_page'] = $instance['posts_per_page'];
|
74 |
+
if( ! empty( $instance['order'] ) ) $value['order'] = $instance['order'];
|
75 |
+
if( ! empty( $instance['orderby'] ) ) $value['orderby'] = $instance['orderby'];
|
76 |
+
if( ! empty( $instance['sticky'] ) ) $value['sticky'] = $instance['sticky'];
|
77 |
+
if( ! empty( $instance['additional'] ) ) $value['additional'] = $instance['additional'];
|
78 |
+
$instance[ 'posts' ] = $value;
|
79 |
+
|
80 |
+
unset( $instance[ 'post_type' ] );
|
81 |
+
unset( $instance[ 'posts_per_page' ] );
|
82 |
+
unset( $instance[ 'order' ] );
|
83 |
+
unset( $instance[ 'orderby' ] );
|
84 |
+
unset( $instance[ 'sticky' ] );
|
85 |
+
unset( $instance[ 'additional' ] );
|
86 |
+
}
|
87 |
+
|
88 |
+
return $instance;
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* @param array $args
|
93 |
+
* @param array $instance
|
94 |
+
*
|
95 |
+
* @return bool
|
96 |
+
*/
|
97 |
+
function widget( $args, $instance ) {
|
98 |
+
return false;
|
99 |
+
}
|
100 |
+
}
|
inc/widgets/post-loop.php
CHANGED
@@ -1,422 +1,422 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Display a loop of posts.
|
5 |
-
*
|
6 |
-
* Class SiteOrigin_Panels_Widgets_PostLoop
|
7 |
-
*/
|
8 |
-
class SiteOrigin_Panels_Widgets_PostLoop extends WP_Widget {
|
9 |
-
|
10 |
-
static $rendering_loop;
|
11 |
-
|
12 |
-
static $current_loop_template;
|
13 |
-
static $current_loop_instance;
|
14 |
-
|
15 |
-
/**
|
16 |
-
* @var SiteOrigin_Panels_Widgets_PostLoop_Helper
|
17 |
-
*/
|
18 |
-
private $helper;
|
19 |
-
|
20 |
-
function __construct() {
|
21 |
-
parent::__construct(
|
22 |
-
'siteorigin-panels-postloop',
|
23 |
-
__( 'Post Loop', 'siteorigin-panels' ),
|
24 |
-
array(
|
25 |
-
'description' => __( 'Displays a post loop.', 'siteorigin-panels' ),
|
26 |
-
),
|
27 |
-
array(
|
28 |
-
'width' => 800,
|
29 |
-
)
|
30 |
-
);
|
31 |
-
}
|
32 |
-
|
33 |
-
/**
|
34 |
-
* Are we currently rendering a post loop
|
35 |
-
*
|
36 |
-
* @return bool
|
37 |
-
*/
|
38 |
-
static function is_rendering_loop() {
|
39 |
-
return self::$rendering_loop;
|
40 |
-
}
|
41 |
-
|
42 |
-
/**
|
43 |
-
* Which post loop is currently being rendered
|
44 |
-
*
|
45 |
-
* @return array
|
46 |
-
*/
|
47 |
-
static function get_current_loop_template() {
|
48 |
-
return self::$current_loop_template;
|
49 |
-
}
|
50 |
-
|
51 |
-
/**
|
52 |
-
* Which post loop is currently being rendered
|
53 |
-
*
|
54 |
-
* @return array
|
55 |
-
*/
|
56 |
-
static function get_current_loop_instance() {
|
57 |
-
return self::$current_loop_instance;
|
58 |
-
}
|
59 |
-
|
60 |
-
/**
|
61 |
-
* Update the widget
|
62 |
-
*
|
63 |
-
* @param array $new
|
64 |
-
* @param array $old
|
65 |
-
* @return array
|
66 |
-
*/
|
67 |
-
function update( $new, $old ){
|
68 |
-
if( class_exists( 'SiteOrigin_Widget' ) && class_exists( 'SiteOrigin_Widget_Field_Posts' ) ) {
|
69 |
-
$helper = $this->get_helper_widget( $this->get_loop_templates() );
|
70 |
-
return $helper->update( $new, $old );
|
71 |
-
}
|
72 |
-
else {
|
73 |
-
$new['more'] = !empty( $new['more'] );
|
74 |
-
return $new;
|
75 |
-
}
|
76 |
-
}
|
77 |
-
|
78 |
-
/**
|
79 |
-
* @param array $args
|
80 |
-
* @param array $instance
|
81 |
-
*/
|
82 |
-
function widget( $args, $instance ) {
|
83 |
-
if( empty( $instance['template'] ) ) return;
|
84 |
-
if( is_admin() ) return;
|
85 |
-
|
86 |
-
static $depth = 0;
|
87 |
-
$depth++;
|
88 |
-
if( $depth > 1 ) {
|
89 |
-
// Because of infinite loops, don't render this post loop if its inside another
|
90 |
-
$depth--;
|
91 |
-
echo $args['before_widget'].$args['after_widget'];
|
92 |
-
return;
|
93 |
-
}
|
94 |
-
|
95 |
-
$query_args = $instance;
|
96 |
-
//If Widgets Bundle post selector is available and a posts query has been saved using it.
|
97 |
-
if ( function_exists( 'siteorigin_widget_post_selector_process_query' ) && ! empty( $instance['posts'] ) ) {
|
98 |
-
$query_args = siteorigin_widget_post_selector_process_query($instance['posts']);
|
99 |
-
$query_args['additional'] = empty($instance['additional']) ? array() : $instance['additional'];
|
100 |
-
}
|
101 |
-
else {
|
102 |
-
if ( ! empty( $instance['posts'] ) ) {
|
103 |
-
// This is using the new WB 1.9 posts field
|
104 |
-
$query_args = wp_parse_args( $instance['posts'], $query_args );
|
105 |
-
}
|
106 |
-
|
107 |
-
if( ! empty( $query_args['sticky'] ) ) {
|
108 |
-
switch( $query_args['sticky'] ){
|
109 |
-
case 'ignore' :
|
110 |
-
$query_args['ignore_sticky_posts'] = 1;
|
111 |
-
break;
|
112 |
-
case 'only' :
|
113 |
-
$query_args['post__in'] = get_option( 'sticky_posts' );
|
114 |
-
break;
|
115 |
-
case 'exclude' :
|
116 |
-
$query_args['post__not_in'] = get_option( 'sticky_posts' );
|
117 |
-
break;
|
118 |
-
}
|
119 |
-
}
|
120 |
-
unset($query_args['template']);
|
121 |
-
unset($query_args['title']);
|
122 |
-
unset($query_args['sticky']);
|
123 |
-
if (empty($query_args['additional'])) {
|
124 |
-
$query_args['additional'] = array();
|
125 |
-
}
|
126 |
-
}
|
127 |
-
$query_args = wp_parse_args($query_args['additional'], $query_args);
|
128 |
-
unset($query_args['additional']);
|
129 |
-
|
130 |
-
global $wp_rewrite;
|
131 |
-
|
132 |
-
if( $wp_rewrite->using_permalinks() ) {
|
133 |
-
|
134 |
-
if( get_query_var('paged') ) {
|
135 |
-
// When the widget appears on a sub page.
|
136 |
-
$query_args['paged'] = get_query_var('paged');
|
137 |
-
}
|
138 |
-
elseif( strpos( $_SERVER['REQUEST_URI'], '/page/' ) !== false ) {
|
139 |
-
// When the widget appears on the home page.
|
140 |
-
preg_match('/\/page\/([0-9]+)\//', $_SERVER['REQUEST_URI'], $matches);
|
141 |
-
if(!empty($matches[1])) $query_args['paged'] = intval($matches[1]);
|
142 |
-
else $query_args['paged'] = 1;
|
143 |
-
}
|
144 |
-
else $query_args['paged'] = 1;
|
145 |
-
}
|
146 |
-
else {
|
147 |
-
// Get current page number when we're not using permalinks
|
148 |
-
$query_args['paged'] = isset($_GET['paged']) ? intval($_GET['paged']) : 1;
|
149 |
-
}
|
150 |
-
|
151 |
-
// Exclude the current post to prevent possible infinite loop
|
152 |
-
|
153 |
-
global $siteorigin_panels_current_post;
|
154 |
-
|
155 |
-
if( !empty($siteorigin_panels_current_post) ){
|
156 |
-
if( !empty( $query_args['post__not_in'] ) ){
|
157 |
-
if( !is_array( $query_args['post__not_in'] ) ){
|
158 |
-
$query_args['post__not_in'] = explode( ',', $query_args['post__not_in'] );
|
159 |
-
$query_args['post__not_in'] = array_map( 'intval', $query_args['post__not_in'] );
|
160 |
-
}
|
161 |
-
$query_args['post__not_in'][] = $siteorigin_panels_current_post;
|
162 |
-
}
|
163 |
-
else {
|
164 |
-
$query_args['post__not_in'] = array( $siteorigin_panels_current_post );
|
165 |
-
}
|
166 |
-
}
|
167 |
-
|
168 |
-
if( !empty($query_args['post__in']) && !is_array($query_args['post__in']) ) {
|
169 |
-
$query_args['post__in'] = explode(',', $query_args['post__in']);
|
170 |
-
$query_args['post__in'] = array_map('intval', $query_args['post__in']);
|
171 |
-
}
|
172 |
-
|
173 |
-
// Create the query
|
174 |
-
query_posts( apply_filters( 'siteorigin_panels_postloop_query_args', $query_args ) );
|
175 |
-
echo $args['before_widget'];
|
176 |
-
|
177 |
-
// Filter the title
|
178 |
-
$instance['title'] = apply_filters('widget_title', $instance['title'], $instance, $this->id_base);
|
179 |
-
if ( !empty( $instance['title'] ) ) {
|
180 |
-
echo $args['before_title'] . $instance['title'] . $args['after_title'];
|
181 |
-
}
|
182 |
-
|
183 |
-
global $more; $old_more = $more; $more = empty($instance['more']);
|
184 |
-
self::$rendering_loop = true;
|
185 |
-
self::$current_loop_instance = $instance;
|
186 |
-
self::$current_loop_template = $instance['template'];
|
187 |
-
if(strpos('/'.$instance['template'], '/content') !== false) {
|
188 |
-
while( have_posts() ) {
|
189 |
-
the_post();
|
190 |
-
locate_template($instance['template'], true, false);
|
191 |
-
}
|
192 |
-
}
|
193 |
-
else {
|
194 |
-
locate_template($instance['template'], true, false);
|
195 |
-
}
|
196 |
-
self::$rendering_loop = false;
|
197 |
-
self::$current_loop_instance = null;
|
198 |
-
self::$current_loop_template = null;
|
199 |
-
|
200 |
-
echo $args['after_widget'];
|
201 |
-
|
202 |
-
// Reset everything
|
203 |
-
wp_reset_query();
|
204 |
-
$depth--;
|
205 |
-
}
|
206 |
-
|
207 |
-
/**
|
208 |
-
* Display the form for the post loop.
|
209 |
-
*
|
210 |
-
* @param array $instance
|
211 |
-
* @return string|void
|
212 |
-
*/
|
213 |
-
function form( $instance ) {
|
214 |
-
$templates = $this->get_loop_templates();
|
215 |
-
if( empty($templates) ) {
|
216 |
-
?><p><?php _e("Your theme doesn't have any post loops.", 'siteorigin-panels') ?></p><?php
|
217 |
-
return;
|
218 |
-
}
|
219 |
-
|
220 |
-
// If the Widgets Bundle is installed and the post selector is available, use that.
|
221 |
-
// Otherwise revert back to our own form fields.
|
222 |
-
if( class_exists( 'SiteOrigin_Widget' ) && class_exists( 'SiteOrigin_Widget_Field_Posts' ) ) {
|
223 |
-
$helper = $this->get_helper_widget( $templates );
|
224 |
-
$helper->form( $instance );
|
225 |
-
}
|
226 |
-
else {
|
227 |
-
$instance = wp_parse_args( $instance, array(
|
228 |
-
'title' => '',
|
229 |
-
'template' => 'loop.php',
|
230 |
-
|
231 |
-
// Query args
|
232 |
-
'post_type' => 'post',
|
233 |
-
'posts_per_page' => '',
|
234 |
-
|
235 |
-
'order' => 'DESC',
|
236 |
-
'orderby' => 'date',
|
237 |
-
|
238 |
-
'sticky' => '',
|
239 |
-
|
240 |
-
'additional' => '',
|
241 |
-
'more' => false,
|
242 |
-
) );
|
243 |
-
|
244 |
-
?>
|
245 |
-
<p>
|
246 |
-
<label for="<?php echo $this->get_field_id( 'title' ) ?>"><?php _e( 'Title', 'siteorigin-panels' ) ?></label>
|
247 |
-
<input type="text" class="widefat" name="<?php echo $this->get_field_name( 'title' ) ?>" id="<?php echo $this->get_field_id( 'title' ) ?>" value="<?php echo esc_attr( $instance['title'] ) ?>">
|
248 |
-
</p>
|
249 |
-
<p>
|
250 |
-
<label for="<?php echo $this->get_field_id('template') ?>"><?php _e('Template', 'siteorigin-panels') ?></label>
|
251 |
-
<select id="<?php echo $this->get_field_id( 'template' ) ?>" name="<?php echo $this->get_field_name( 'template' ) ?>">
|
252 |
-
<?php foreach($templates as $template) : ?>
|
253 |
-
<option value="<?php echo esc_attr($template) ?>" <?php selected($instance['template'], $template) ?>>
|
254 |
-
<?php
|
255 |
-
$headers = get_file_data( locate_template($template), array(
|
256 |
-
'loop_name' => 'Loop Name',
|
257 |
-
) );
|
258 |
-
echo esc_html(!empty($headers['loop_name']) ? $headers['loop_name'] : $template);
|
259 |
-
?>
|
260 |
-
</option>
|
261 |
-
<?php endforeach; ?>
|
262 |
-
</select>
|
263 |
-
</p>
|
264 |
-
|
265 |
-
<p>
|
266 |
-
<label for="<?php echo $this->get_field_id('more') ?>"><?php _e('More Link', 'siteorigin-panels') ?></label>
|
267 |
-
<input type="checkbox" class="widefat" id="<?php echo $this->get_field_id( 'more' ) ?>" name="<?php echo $this->get_field_name( 'more' ) ?>" <?php checked( $instance['more'] ) ?> /><br/>
|
268 |
-
<small><?php _e('If the template supports it, cut posts and display the more link.', 'siteorigin-panels') ?></small>
|
269 |
-
</p>
|
270 |
-
<?php
|
271 |
-
|
272 |
-
if ( ! empty( $instance['posts'] ) ) {
|
273 |
-
$instance = wp_parse_args( $instance['posts'] , $instance );
|
274 |
-
unset( $instance['posts'] );
|
275 |
-
//unset post__in and taxonomies?
|
276 |
-
}
|
277 |
-
// Get all the loop template files
|
278 |
-
$post_types = get_post_types(array('public' => true));
|
279 |
-
$post_types = array_values($post_types);
|
280 |
-
$post_types = array_diff($post_types, array('attachment', 'revision', 'nav_menu_item'));
|
281 |
-
?>
|
282 |
-
<p>
|
283 |
-
<label for="<?php echo $this->get_field_id('post_type') ?>"><?php _e('Post Type', 'siteorigin-panels') ?></label>
|
284 |
-
<select id="<?php echo $this->get_field_id( 'post_type' ) ?>" name="<?php echo $this->get_field_name( 'post_type' ) ?>" value="<?php echo esc_attr($instance['post_type']) ?>">
|
285 |
-
<?php foreach($post_types as $type) : ?>
|
286 |
-
<option value="<?php echo esc_attr($type) ?>" <?php selected($instance['post_type'], $type) ?>><?php echo esc_html($type) ?></option>
|
287 |
-
<?php endforeach; ?>
|
288 |
-
</select>
|
289 |
-
</p>
|
290 |
-
|
291 |
-
<p>
|
292 |
-
<label for="<?php echo $this->get_field_id('posts_per_page') ?>"><?php _e('Posts Per Page', 'siteorigin-panels') ?></label>
|
293 |
-
<input type="text" class="small-text" id="<?php echo $this->get_field_id( 'posts_per_page' ) ?>" name="<?php echo $this->get_field_name( 'posts_per_page' ) ?>" value="<?php echo esc_attr($instance['posts_per_page']) ?>" />
|
294 |
-
</p>
|
295 |
-
|
296 |
-
<p>
|
297 |
-
<label <?php echo $this->get_field_id('orderby') ?>><?php _e('Order By', 'siteorigin-panels') ?></label>
|
298 |
-
<select id="<?php echo $this->get_field_id( 'orderby' ) ?>" name="<?php echo $this->get_field_name( 'orderby' ) ?>" value="<?php echo esc_attr($instance['orderby']) ?>">
|
299 |
-
<option value="none" <?php selected($instance['orderby'], 'none') ?>><?php esc_html_e('None', 'siteorigin-panels') ?></option>
|
300 |
-
<option value="ID" <?php selected($instance['orderby'], 'ID') ?>><?php esc_html_e('Post ID', 'siteorigin-panels') ?></option>
|
301 |
-
<option value="author" <?php selected($instance['orderby'], 'author') ?>><?php esc_html_e('Author', 'siteorigin-panels') ?></option>
|
302 |
-
<option value="name" <?php selected($instance['orderby'], 'name') ?>><?php esc_html_e('Name', 'siteorigin-panels') ?></option>
|
303 |
-
<option value="name" <?php selected($instance['orderby'], 'name') ?>><?php esc_html_e('Name', 'siteorigin-panels') ?></option>
|
304 |
-
<option value="date" <?php selected($instance['orderby'], 'date') ?>><?php esc_html_e('Date', 'siteorigin-panels') ?></option>
|
305 |
-
<option value="modified" <?php selected($instance['orderby'], 'modified') ?>><?php esc_html_e('Modified', 'siteorigin-panels') ?></option>
|
306 |
-
<option value="parent" <?php selected($instance['orderby'], 'parent') ?>><?php esc_html_e('Parent', 'siteorigin-panels') ?></option>
|
307 |
-
<option value="rand" <?php selected($instance['orderby'], 'rand') ?>><?php esc_html_e('Random', 'siteorigin-panels') ?></option>
|
308 |
-
<option value="comment_count" <?php selected($instance['orderby'], 'comment_count') ?>><?php esc_html_e('Comment Count', 'siteorigin-panels') ?></option>
|
309 |
-
<option value="menu_order" <?php selected($instance['orderby'], 'menu_order') ?>><?php esc_html_e('Menu Order', 'siteorigin-panels') ?></option>
|
310 |
-
<option value="post__in" <?php selected($instance['orderby'], 'post__in') ?>><?php esc_html_e('Post In Order', 'siteorigin-panels') ?></option>
|
311 |
-
</select>
|
312 |
-
</p>
|
313 |
-
|
314 |
-
<p>
|
315 |
-
<label for="<?php echo $this->get_field_id('order') ?>"><?php _e('Order', 'siteorigin-panels') ?></label>
|
316 |
-
<select id="<?php echo $this->get_field_id( 'order' ) ?>" name="<?php echo $this->get_field_name( 'order' ) ?>" value="<?php echo esc_attr($instance['order']) ?>">
|
317 |
-
<option value="DESC" <?php selected($instance['order'], 'DESC') ?>><?php esc_html_e('Descending', 'siteorigin-panels') ?></option>
|
318 |
-
<option value="ASC" <?php selected($instance['order'], 'ASC') ?>><?php esc_html_e('Ascending', 'siteorigin-panels') ?></option>
|
319 |
-
</select>
|
320 |
-
</p>
|
321 |
-
|
322 |
-
<p>
|
323 |
-
<label for="<?php echo $this->get_field_id('sticky') ?>"><?php _e('Sticky Posts', 'siteorigin-panels') ?></label>
|
324 |
-
<select id="<?php echo $this->get_field_id( 'sticky' ) ?>" name="<?php echo $this->get_field_name( 'sticky' ) ?>" value="<?php echo esc_attr($instance['sticky']) ?>">
|
325 |
-
<option value="" <?php selected($instance['sticky'], '') ?>><?php esc_html_e('Default', 'siteorigin-panels') ?></option>
|
326 |
-
<option value="ignore" <?php selected($instance['sticky'], 'ignore') ?>><?php esc_html_e('Ignore Sticky', 'siteorigin-panels') ?></option>
|
327 |
-
<option value="exclude" <?php selected($instance['sticky'], 'exclude') ?>><?php esc_html_e('Exclude Sticky', 'siteorigin-panels') ?></option>
|
328 |
-
<option value="only" <?php selected($instance['sticky'], 'only') ?>><?php esc_html_e('Only Sticky', 'siteorigin-panels') ?></option>
|
329 |
-
</select>
|
330 |
-
</p>
|
331 |
-
|
332 |
-
<p>
|
333 |
-
<label for="<?php echo $this->get_field_id('additional') ?>"><?php _e('Additional ', 'siteorigin-panels') ?></label>
|
334 |
-
<input type="text" class="widefat" id="<?php echo $this->get_field_id( 'additional' ) ?>" name="<?php echo $this->get_field_name( 'additional' ) ?>" value="<?php echo esc_attr($instance['additional']) ?>" />
|
335 |
-
<small>
|
336 |
-
<?php
|
337 |
-
echo preg_replace(
|
338 |
-
'/1\{ *(.*?) *\}/',
|
339 |
-
'<a href="http://codex.wordpress.org/Function_Reference/query_posts">$1</a>',
|
340 |
-
__('Additional query arguments. See 1{query_posts}.', 'siteorigin-panels')
|
341 |
-
)
|
342 |
-
?>
|
343 |
-
</small>
|
344 |
-
</p>
|
345 |
-
<?php
|
346 |
-
}
|
347 |
-
}
|
348 |
-
|
349 |
-
/**
|
350 |
-
* Get all the existing files
|
351 |
-
*
|
352 |
-
* @return array
|
353 |
-
*/
|
354 |
-
function get_loop_templates(){
|
355 |
-
$templates = array();
|
356 |
-
|
357 |
-
$template_files = array(
|
358 |
-
'loop*.php',
|
359 |
-
'*/loop*.php',
|
360 |
-
'content*.php',
|
361 |
-
'*/content*.php',
|
362 |
-
);
|
363 |
-
|
364 |
-
$template_dirs = array( get_template_directory(), get_stylesheet_directory() );
|
365 |
-
$template_dirs = apply_filters( 'siteorigin_panels_postloop_template_directory', $template_dirs );
|
366 |
-
$template_dirs = array_unique( $template_dirs );
|
367 |
-
foreach( $template_dirs as $dir ){
|
368 |
-
foreach( $template_files as $template_file ) {
|
369 |
-
foreach( (array) glob($dir.'/'.$template_file) as $file ) {
|
370 |
-
if( file_exists( $file ) ) $templates[] = str_replace($dir.'/', '', $file);
|
371 |
-
}
|
372 |
-
}
|
373 |
-
}
|
374 |
-
|
375 |
-
$templates = array_unique( apply_filters( 'siteorigin_panels_postloop_templates', $templates ) );
|
376 |
-
foreach ( $templates as $template_key => $template) {
|
377 |
-
$invalid = false;
|
378 |
-
|
379 |
-
// Ensure the provided file has a valid name and path
|
380 |
-
if ( validate_file( $template ) != 0 ) {
|
381 |
-
$invalid = true;
|
382 |
-
}
|
383 |
-
|
384 |
-
// Don't expect non-PHP files
|
385 |
-
if ( substr( $template, -4 ) != '.php' ) {
|
386 |
-
$invalid = true;
|
387 |
-
}
|
388 |
-
|
389 |
-
$template = locate_template( $template );
|
390 |
-
if ( empty( $template ) || $invalid ) {
|
391 |
-
unset( $templates[ $template_key ] );
|
392 |
-
}
|
393 |
-
}
|
394 |
-
// Update array indexes to ensure logical indexing
|
395 |
-
sort( $templates );
|
396 |
-
sort( $templates );
|
397 |
-
|
398 |
-
return $templates;
|
399 |
-
}
|
400 |
-
|
401 |
-
|
402 |
-
/**
|
403 |
-
* Get the helper widget based on the Widgets Bundle's classes.
|
404 |
-
*
|
405 |
-
* @param $templates array Blog loop templates.
|
406 |
-
*
|
407 |
-
* @return mixed
|
408 |
-
*/
|
409 |
-
private function get_helper_widget( $templates ) {
|
410 |
-
if ( empty( $this->helper ) &&
|
411 |
-
class_exists( 'SiteOrigin_Widget' ) &&
|
412 |
-
class_exists( 'SiteOrigin_Widget_Field_Posts' ) ) {
|
413 |
-
$this->helper = new SiteOrigin_Panels_Widgets_PostLoop_Helper( $templates );
|
414 |
-
}
|
415 |
-
// These ensure the form fields name attributes are correct.
|
416 |
-
$this->helper->id_base = $this->id_base;
|
417 |
-
$this->helper->id = $this->id;
|
418 |
-
$this->helper->number = $this->number;
|
419 |
-
|
420 |
-
return $this->helper;
|
421 |
-
}
|
422 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Display a loop of posts.
|
5 |
+
*
|
6 |
+
* Class SiteOrigin_Panels_Widgets_PostLoop
|
7 |
+
*/
|
8 |
+
class SiteOrigin_Panels_Widgets_PostLoop extends WP_Widget {
|
9 |
+
|
10 |
+
static $rendering_loop;
|
11 |
+
|
12 |
+
static $current_loop_template;
|
13 |
+
static $current_loop_instance;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @var SiteOrigin_Panels_Widgets_PostLoop_Helper
|
17 |
+
*/
|
18 |
+
private $helper;
|
19 |
+
|
20 |
+
function __construct() {
|
21 |
+
parent::__construct(
|
22 |
+
'siteorigin-panels-postloop',
|
23 |
+
__( 'Post Loop', 'siteorigin-panels' ),
|
24 |
+
array(
|
25 |
+
'description' => __( 'Displays a post loop.', 'siteorigin-panels' ),
|
26 |
+
),
|
27 |
+
array(
|
28 |
+
'width' => 800,
|
29 |
+
)
|
30 |
+
);
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Are we currently rendering a post loop
|
35 |
+
*
|
36 |
+
* @return bool
|
37 |
+
*/
|
38 |
+
static function is_rendering_loop() {
|
39 |
+
return self::$rendering_loop;
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Which post loop is currently being rendered
|
44 |
+
*
|
45 |
+
* @return array
|
46 |
+
*/
|
47 |
+
static function get_current_loop_template() {
|
48 |
+
return self::$current_loop_template;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Which post loop is currently being rendered
|
53 |
+
*
|
54 |
+
* @return array
|
55 |
+
*/
|
56 |
+
static function get_current_loop_instance() {
|
57 |
+
return self::$current_loop_instance;
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Update the widget
|
62 |
+
*
|
63 |
+
* @param array $new
|
64 |
+
* @param array $old
|
65 |
+
* @return array
|
66 |
+
*/
|
67 |
+
function update( $new, $old ){
|
68 |
+
if( class_exists( 'SiteOrigin_Widget' ) && class_exists( 'SiteOrigin_Widget_Field_Posts' ) ) {
|
69 |
+
$helper = $this->get_helper_widget( $this->get_loop_templates() );
|
70 |
+
return $helper->update( $new, $old );
|
71 |
+
}
|
72 |
+
else {
|
73 |
+
$new['more'] = !empty( $new['more'] );
|
74 |
+
return $new;
|
75 |
+
}
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* @param array $args
|
80 |
+
* @param array $instance
|
81 |
+
*/
|
82 |
+
function widget( $args, $instance ) {
|
83 |
+
if( empty( $instance['template'] ) ) return;
|
84 |
+
if( is_admin() ) return;
|
85 |
+
|
86 |
+
static $depth = 0;
|
87 |
+
$depth++;
|
88 |
+
if( $depth > 1 ) {
|
89 |
+
// Because of infinite loops, don't render this post loop if its inside another
|
90 |
+
$depth--;
|
91 |
+
echo $args['before_widget'].$args['after_widget'];
|
92 |
+
return;
|
93 |
+
}
|
94 |
+
|
95 |
+
$query_args = $instance;
|
96 |
+
//If Widgets Bundle post selector is available and a posts query has been saved using it.
|
97 |
+
if ( function_exists( 'siteorigin_widget_post_selector_process_query' ) && ! empty( $instance['posts'] ) ) {
|
98 |
+
$query_args = siteorigin_widget_post_selector_process_query($instance['posts']);
|
99 |
+
$query_args['additional'] = empty($instance['additional']) ? array() : $instance['additional'];
|
100 |
+
}
|
101 |
+
else {
|
102 |
+
if ( ! empty( $instance['posts'] ) ) {
|
103 |
+
// This is using the new WB 1.9 posts field
|
104 |
+
$query_args = wp_parse_args( $instance['posts'], $query_args );
|
105 |
+
}
|
106 |
+
|
107 |
+
if( ! empty( $query_args['sticky'] ) ) {
|
108 |
+
switch( $query_args['sticky'] ){
|
109 |
+
case 'ignore' :
|
110 |
+
$query_args['ignore_sticky_posts'] = 1;
|
111 |
+
break;
|
112 |
+
case 'only' :
|
113 |
+
$query_args['post__in'] = get_option( 'sticky_posts' );
|
114 |
+
break;
|
115 |
+
case 'exclude' :
|
116 |
+
$query_args['post__not_in'] = get_option( 'sticky_posts' );
|
117 |
+
break;
|
118 |
+
}
|
119 |
+
}
|
120 |
+
unset($query_args['template']);
|
121 |
+
unset($query_args['title']);
|
122 |
+
unset($query_args['sticky']);
|
123 |
+
if (empty($query_args['additional'])) {
|
124 |
+
$query_args['additional'] = array();
|
125 |
+
}
|
126 |
+
}
|
127 |
+
$query_args = wp_parse_args($query_args['additional'], $query_args);
|
128 |
+
unset($query_args['additional']);
|
129 |
+
|
130 |
+
global $wp_rewrite;
|
131 |
+
|
132 |
+
if( $wp_rewrite->using_permalinks() ) {
|
133 |
+
|
134 |
+
if( get_query_var('paged') ) {
|
135 |
+
// When the widget appears on a sub page.
|
136 |
+
$query_args['paged'] = get_query_var('paged');
|
137 |
+
}
|
138 |
+
elseif( strpos( $_SERVER['REQUEST_URI'], '/page/' ) !== false ) {
|
139 |
+
// When the widget appears on the home page.
|
140 |
+
preg_match('/\/page\/([0-9]+)\//', $_SERVER['REQUEST_URI'], $matches);
|
141 |
+
if(!empty($matches[1])) $query_args['paged'] = intval($matches[1]);
|
142 |
+
else $query_args['paged'] = 1;
|
143 |
+
}
|
144 |
+
else $query_args['paged'] = 1;
|
145 |
+
}
|
146 |
+
else {
|
147 |
+
// Get current page number when we're not using permalinks
|
148 |
+
$query_args['paged'] = isset($_GET['paged']) ? intval($_GET['paged']) : 1;
|
149 |
+
}
|
150 |
+
|
151 |
+
// Exclude the current post to prevent possible infinite loop
|
152 |
+
|
153 |
+
global $siteorigin_panels_current_post;
|
154 |
+
|
155 |
+
if( !empty($siteorigin_panels_current_post) ){
|
156 |
+
if( !empty( $query_args['post__not_in'] ) ){
|
157 |
+
if( !is_array( $query_args['post__not_in'] ) ){
|
158 |
+
$query_args['post__not_in'] = explode( ',', $query_args['post__not_in'] );
|
159 |
+
$query_args['post__not_in'] = array_map( 'intval', $query_args['post__not_in'] );
|
160 |
+
}
|
161 |
+
$query_args['post__not_in'][] = $siteorigin_panels_current_post;
|
162 |
+
}
|
163 |
+
else {
|
164 |
+
$query_args['post__not_in'] = array( $siteorigin_panels_current_post );
|
165 |
+
}
|
166 |
+
}
|
167 |
+
|
168 |
+
if( !empty($query_args['post__in']) && !is_array($query_args['post__in']) ) {
|
169 |
+
$query_args['post__in'] = explode(',', $query_args['post__in']);
|
170 |
+
$query_args['post__in'] = array_map('intval', $query_args['post__in']);
|
171 |
+
}
|
172 |
+
|
173 |
+
// Create the query
|
174 |
+
query_posts( apply_filters( 'siteorigin_panels_postloop_query_args', $query_args ) );
|
175 |
+
echo $args['before_widget'];
|
176 |
+
|
177 |
+
// Filter the title
|
178 |
+
$instance['title'] = apply_filters('widget_title', $instance['title'], $instance, $this->id_base);
|
179 |
+
if ( !empty( $instance['title'] ) ) {
|
180 |
+
echo $args['before_title'] . $instance['title'] . $args['after_title'];
|
181 |
+
}
|
182 |
+
|
183 |
+
global $more; $old_more = $more; $more = empty($instance['more']);
|
184 |
+
self::$rendering_loop = true;
|
185 |
+
self::$current_loop_instance = $instance;
|
186 |
+
self::$current_loop_template = $instance['template'];
|
187 |
+
if(strpos('/'.$instance['template'], '/content') !== false) {
|
188 |
+
while( have_posts() ) {
|
189 |
+
the_post();
|
190 |
+
locate_template($instance['template'], true, false);
|
191 |
+
}
|
192 |
+
}
|
193 |
+
else {
|
194 |
+
locate_template($instance['template'], true, false);
|
195 |
+
}
|
196 |
+
self::$rendering_loop = false;
|
197 |
+
self::$current_loop_instance = null;
|
198 |
+
self::$current_loop_template = null;
|
199 |
+
|
200 |
+
echo $args['after_widget'];
|
201 |
+
|
202 |
+
// Reset everything
|
203 |
+
wp_reset_query();
|
204 |
+
$depth--;
|
205 |
+
}
|
206 |
+
|
207 |
+
/**
|
208 |
+
* Display the form for the post loop.
|
209 |
+
*
|
210 |
+
* @param array $instance
|
211 |
+
* @return string|void
|
212 |
+
*/
|
213 |
+
function form( $instance ) {
|
214 |
+
$templates = $this->get_loop_templates();
|
215 |
+
if( empty($templates) ) {
|
216 |
+
?><p><?php _e("Your theme doesn't have any post loops.", 'siteorigin-panels') ?></p><?php
|
217 |
+
return;
|
218 |
+
}
|
219 |
+
|
220 |
+
// If the Widgets Bundle is installed and the post selector is available, use that.
|
221 |
+
// Otherwise revert back to our own form fields.
|
222 |
+
if( class_exists( 'SiteOrigin_Widget' ) && class_exists( 'SiteOrigin_Widget_Field_Posts' ) ) {
|
223 |
+
$helper = $this->get_helper_widget( $templates );
|
224 |
+
$helper->form( $instance );
|
225 |
+
}
|
226 |
+
else {
|
227 |
+
$instance = wp_parse_args( $instance, array(
|
228 |
+
'title' => '',
|
229 |
+
'template' => 'loop.php',
|
230 |
+
|
231 |
+
// Query args
|
232 |
+
'post_type' => 'post',
|
233 |
+
'posts_per_page' => '',
|
234 |
+
|
235 |
+
'order' => 'DESC',
|
236 |
+
'orderby' => 'date',
|
237 |
+
|
238 |
+
'sticky' => '',
|
239 |
+
|
240 |
+
'additional' => '',
|
241 |
+
'more' => false,
|
242 |
+
) );
|
243 |
+
|
244 |
+
?>
|
245 |
+
<p>
|
246 |
+
<label for="<?php echo $this->get_field_id( 'title' ) ?>"><?php _e( 'Title', 'siteorigin-panels' ) ?></label>
|
247 |
+
<input type="text" class="widefat" name="<?php echo $this->get_field_name( 'title' ) ?>" id="<?php echo $this->get_field_id( 'title' ) ?>" value="<?php echo esc_attr( $instance['title'] ) ?>">
|
248 |
+
</p>
|
249 |
+
<p>
|
250 |
+
<label for="<?php echo $this->get_field_id('template') ?>"><?php _e('Template', 'siteorigin-panels') ?></label>
|
251 |
+
<select id="<?php echo $this->get_field_id( 'template' ) ?>" name="<?php echo $this->get_field_name( 'template' ) ?>">
|
252 |
+
<?php foreach($templates as $template) : ?>
|
253 |
+
<option value="<?php echo esc_attr($template) ?>" <?php selected($instance['template'], $template) ?>>
|
254 |
+
<?php
|
255 |
+
$headers = get_file_data( locate_template($template), array(
|
256 |
+
'loop_name' => 'Loop Name',
|
257 |
+
) );
|
258 |
+
echo esc_html(!empty($headers['loop_name']) ? $headers['loop_name'] : $template);
|
259 |
+
?>
|
260 |
+
</option>
|
261 |
+
<?php endforeach; ?>
|
262 |
+
</select>
|
263 |
+
</p>
|
264 |
+
|
265 |
+
<p>
|
266 |
+
<label for="<?php echo $this->get_field_id('more') ?>"><?php _e('More Link', 'siteorigin-panels') ?></label>
|
267 |
+
<input type="checkbox" class="widefat" id="<?php echo $this->get_field_id( 'more' ) ?>" name="<?php echo $this->get_field_name( 'more' ) ?>" <?php checked( $instance['more'] ) ?> /><br/>
|
268 |
+
<small><?php _e('If the template supports it, cut posts and display the more link.', 'siteorigin-panels') ?></small>
|
269 |
+
</p>
|
270 |
+
<?php
|
271 |
+
|
272 |
+
if ( ! empty( $instance['posts'] ) ) {
|
273 |
+
$instance = wp_parse_args( $instance['posts'] , $instance );
|
274 |
+
unset( $instance['posts'] );
|
275 |
+
//unset post__in and taxonomies?
|
276 |
+
}
|
277 |
+
// Get all the loop template files
|
278 |
+
$post_types = get_post_types(array('public' => true));
|
279 |
+
$post_types = array_values($post_types);
|
280 |
+
$post_types = array_diff($post_types, array('attachment', 'revision', 'nav_menu_item'));
|
281 |
+
?>
|
282 |
+
<p>
|
283 |
+
<label for="<?php echo $this->get_field_id('post_type') ?>"><?php _e('Post Type', 'siteorigin-panels') ?></label>
|
284 |
+
<select id="<?php echo $this->get_field_id( 'post_type' ) ?>" name="<?php echo $this->get_field_name( 'post_type' ) ?>" value="<?php echo esc_attr($instance['post_type']) ?>">
|
285 |
+
<?php foreach($post_types as $type) : ?>
|
286 |
+
<option value="<?php echo esc_attr($type) ?>" <?php selected($instance['post_type'], $type) ?>><?php echo esc_html($type) ?></option>
|
287 |
+
<?php endforeach; ?>
|
288 |
+
</select>
|
289 |
+
</p>
|
290 |
+
|
291 |
+
<p>
|
292 |
+
<label for="<?php echo $this->get_field_id('posts_per_page') ?>"><?php _e('Posts Per Page', 'siteorigin-panels') ?></label>
|
293 |
+
<input type="text" class="small-text" id="<?php echo $this->get_field_id( 'posts_per_page' ) ?>" name="<?php echo $this->get_field_name( 'posts_per_page' ) ?>" value="<?php echo esc_attr($instance['posts_per_page']) ?>" />
|
294 |
+
</p>
|
295 |
+
|
296 |
+
<p>
|
297 |
+
<label <?php echo $this->get_field_id('orderby') ?>><?php _e('Order By', 'siteorigin-panels') ?></label>
|
298 |
+
<select id="<?php echo $this->get_field_id( 'orderby' ) ?>" name="<?php echo $this->get_field_name( 'orderby' ) ?>" value="<?php echo esc_attr($instance['orderby']) ?>">
|
299 |
+
<option value="none" <?php selected($instance['orderby'], 'none') ?>><?php esc_html_e('None', 'siteorigin-panels') ?></option>
|
300 |
+
<option value="ID" <?php selected($instance['orderby'], 'ID') ?>><?php esc_html_e('Post ID', 'siteorigin-panels') ?></option>
|
301 |
+
<option value="author" <?php selected($instance['orderby'], 'author') ?>><?php esc_html_e('Author', 'siteorigin-panels') ?></option>
|
302 |
+
<option value="name" <?php selected($instance['orderby'], 'name') ?>><?php esc_html_e('Name', 'siteorigin-panels') ?></option>
|
303 |
+
<option value="name" <?php selected($instance['orderby'], 'name') ?>><?php esc_html_e('Name', 'siteorigin-panels') ?></option>
|
304 |
+
<option value="date" <?php selected($instance['orderby'], 'date') ?>><?php esc_html_e('Date', 'siteorigin-panels') ?></option>
|
305 |
+
<option value="modified" <?php selected($instance['orderby'], 'modified') ?>><?php esc_html_e('Modified', 'siteorigin-panels') ?></option>
|
306 |
+
<option value="parent" <?php selected($instance['orderby'], 'parent') ?>><?php esc_html_e('Parent', 'siteorigin-panels') ?></option>
|
307 |
+
<option value="rand" <?php selected($instance['orderby'], 'rand') ?>><?php esc_html_e('Random', 'siteorigin-panels') ?></option>
|
308 |
+
<option value="comment_count" <?php selected($instance['orderby'], 'comment_count') ?>><?php esc_html_e('Comment Count', 'siteorigin-panels') ?></option>
|
309 |
+
<option value="menu_order" <?php selected($instance['orderby'], 'menu_order') ?>><?php esc_html_e('Menu Order', 'siteorigin-panels') ?></option>
|
310 |
+
<option value="post__in" <?php selected($instance['orderby'], 'post__in') ?>><?php esc_html_e('Post In Order', 'siteorigin-panels') ?></option>
|
311 |
+
</select>
|
312 |
+
</p>
|
313 |
+
|
314 |
+
<p>
|
315 |
+
<label for="<?php echo $this->get_field_id('order') ?>"><?php _e('Order', 'siteorigin-panels') ?></label>
|
316 |
+
<select id="<?php echo $this->get_field_id( 'order' ) ?>" name="<?php echo $this->get_field_name( 'order' ) ?>" value="<?php echo esc_attr($instance['order']) ?>">
|
317 |
+
<option value="DESC" <?php selected($instance['order'], 'DESC') ?>><?php esc_html_e('Descending', 'siteorigin-panels') ?></option>
|
318 |
+
<option value="ASC" <?php selected($instance['order'], 'ASC') ?>><?php esc_html_e('Ascending', 'siteorigin-panels') ?></option>
|
319 |
+
</select>
|
320 |
+
</p>
|
321 |
+
|
322 |
+
<p>
|
323 |
+
<label for="<?php echo $this->get_field_id('sticky') ?>"><?php _e('Sticky Posts', 'siteorigin-panels') ?></label>
|
324 |
+
<select id="<?php echo $this->get_field_id( 'sticky' ) ?>" name="<?php echo $this->get_field_name( 'sticky' ) ?>" value="<?php echo esc_attr($instance['sticky']) ?>">
|
325 |
+
<option value="" <?php selected($instance['sticky'], '') ?>><?php esc_html_e('Default', 'siteorigin-panels') ?></option>
|
326 |
+
<option value="ignore" <?php selected($instance['sticky'], 'ignore') ?>><?php esc_html_e('Ignore Sticky', 'siteorigin-panels') ?></option>
|
327 |
+
<option value="exclude" <?php selected($instance['sticky'], 'exclude') ?>><?php esc_html_e('Exclude Sticky', 'siteorigin-panels') ?></option>
|
328 |
+
<option value="only" <?php selected($instance['sticky'], 'only') ?>><?php esc_html_e('Only Sticky', 'siteorigin-panels') ?></option>
|
329 |
+
</select>
|
330 |
+
</p>
|
331 |
+
|
332 |
+
<p>
|
333 |
+
<label for="<?php echo $this->get_field_id('additional') ?>"><?php _e('Additional ', 'siteorigin-panels') ?></label>
|
334 |
+
<input type="text" class="widefat" id="<?php echo $this->get_field_id( 'additional' ) ?>" name="<?php echo $this->get_field_name( 'additional' ) ?>" value="<?php echo esc_attr($instance['additional']) ?>" />
|
335 |
+
<small>
|
336 |
+
<?php
|
337 |
+
echo preg_replace(
|
338 |
+
'/1\{ *(.*?) *\}/',
|
339 |
+
'<a href="http://codex.wordpress.org/Function_Reference/query_posts">$1</a>',
|
340 |
+
__('Additional query arguments. See 1{query_posts}.', 'siteorigin-panels')
|
341 |
+
)
|
342 |
+
?>
|
343 |
+
</small>
|
344 |
+
</p>
|
345 |
+
<?php
|
346 |
+
}
|
347 |
+
}
|
348 |
+
|
349 |
+
/**
|
350 |
+
* Get all the existing files
|
351 |
+
*
|
352 |
+
* @return array
|
353 |
+
*/
|
354 |
+
function get_loop_templates(){
|
355 |
+
$templates = array();
|
356 |
+
|
357 |
+
$template_files = array(
|
358 |
+
'loop*.php',
|
359 |
+
'*/loop*.php',
|
360 |
+
'content*.php',
|
361 |
+
'*/content*.php',
|
362 |
+
);
|
363 |
+
|
364 |
+
$template_dirs = array( get_template_directory(), get_stylesheet_directory() );
|
365 |
+
$template_dirs = apply_filters( 'siteorigin_panels_postloop_template_directory', $template_dirs );
|
366 |
+
$template_dirs = array_unique( $template_dirs );
|
367 |
+
foreach( $template_dirs as $dir ){
|
368 |
+
foreach( $template_files as $template_file ) {
|
369 |
+
foreach( (array) glob($dir.'/'.$template_file) as $file ) {
|
370 |
+
if( file_exists( $file ) ) $templates[] = str_replace($dir.'/', '', $file);
|
371 |
+
}
|
372 |
+
}
|
373 |
+
}
|
374 |
+
|
375 |
+
$templates = array_unique( apply_filters( 'siteorigin_panels_postloop_templates', $templates ) );
|
376 |
+
foreach ( $templates as $template_key => $template) {
|
377 |
+
$invalid = false;
|
378 |
+
|
379 |
+
// Ensure the provided file has a valid name and path
|
380 |
+
if ( validate_file( $template ) != 0 ) {
|
381 |
+
$invalid = true;
|
382 |
+
}
|
383 |
+
|
384 |
+
// Don't expect non-PHP files
|
385 |
+
if ( substr( $template, -4 ) != '.php' ) {
|
386 |
+
$invalid = true;
|
387 |
+
}
|
388 |
+
|
389 |
+
$template = locate_template( $template );
|
390 |
+
if ( empty( $template ) || $invalid ) {
|
391 |
+
unset( $templates[ $template_key ] );
|
392 |
+
}
|
393 |
+
}
|
394 |
+
// Update array indexes to ensure logical indexing
|
395 |
+
sort( $templates );
|
396 |
+
sort( $templates );
|
397 |
+
|
398 |
+
return $templates;
|
399 |
+
}
|
400 |
+
|
401 |
+
|
402 |
+
/**
|
403 |
+
* Get the helper widget based on the Widgets Bundle's classes.
|
404 |
+
*
|
405 |
+
* @param $templates array Blog loop templates.
|
406 |
+
*
|
407 |
+
* @return mixed
|
408 |
+
*/
|
409 |
+
private function get_helper_widget( $templates ) {
|
410 |
+
if ( empty( $this->helper ) &&
|
411 |
+
class_exists( 'SiteOrigin_Widget' ) &&
|
412 |
+
class_exists( 'SiteOrigin_Widget_Field_Posts' ) ) {
|
413 |
+
$this->helper = new SiteOrigin_Panels_Widgets_PostLoop_Helper( $templates );
|
414 |
+
}
|
415 |
+
// These ensure the form fields name attributes are correct.
|
416 |
+
$this->helper->id_base = $this->id_base;
|
417 |
+
$this->helper->id = $this->id;
|
418 |
+
$this->helper->number = $this->number;
|
419 |
+
|
420 |
+
return $this->helper;
|
421 |
+
}
|
422 |
+
}
|
js/siteorigin-panels-2106.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(c)return c(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 c="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,c=jQuery;t.exports=a.view.dialog.extend({cellPreviewTemplate:_.template(a.helpers.utils.processTemplate(c("#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.openSelectedCellStyles()},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(c("#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(){c(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=c(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=c('<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(),c(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;c(this).data("newCellClone").css("width",d.width()*l).find(".preview-cell-weight").html(Math.round(1e3*l)/10),c(this).data("prevCellClone").css("width",d.width()*o).find(".preview-cell-weight").html(Math.round(1e3*o)/10)},stop:function(e,t){c(this).data("newCellClone").remove(),c(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(c(e.target).is(".preview-cell")||c(e.target).is(".preview-cell-in")){var t=c(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();c('<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&&c(this).removeClass("no-user-interacted"),13===e.keyCode&&(e.preventDefault(),c(this).blur())}).keydown(function(e){if(9===e.keyCode){e.preventDefault();var t=d.find(".preview-cell-weight-input"),i=t.index(c(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(c(t).val()))&&c(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(c(t).val());i=isNaN(i)?1/r.row.cells.length:Math.round(10*i)/1e3;var s=!c(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");c(t).animate({width:Math.round(1e3*i)/10+"%"},250),c(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(){c(this).select()})}),c(this).siblings(".preview-cell-weight-input").select()})},this),this.trigger("form_loaded",this)},getSelectedCellIndex:function(){var i=-1;return this.$(".preview-cell .preview-cell-in").each(function(e,t){c(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(),e.off("styles_loaded")}),this.cellStylesCache=[]},scaleRowWidths:function(){var s=this;this.$(".row-preview .preview-cell").each(function(e,t){var i=s.row.cells.at(e);c(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");c(t).animate({width:Math.round(1e3*i)/10+"%"},250),c(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 i=this.$(".so-sidebar-tabs");_.each(panelsOptions.widget_dialog_tabs,function(e,t){o(this.dialogTabTemplate({title:e.title,tab:t})).data({message:e.message,filter:e.filter}).appendTo(i)},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,c=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=c.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(),c(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});i(document).trigger("before_panels_setup",d),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()}),i(window).on("keyup",function(e){27===e.which&&i(".so-panels-dialog-wrapper, .so-panels-live-editor").filter(":visible").last().find(".so-title-bar .so-close, .live-editor-close").click()})})},{"./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,h){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(c,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:c,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:c,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,h),panels_info:l})):(l.class=h,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=h,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:h,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:h,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)"_"!==s.charAt(0)&&"so_sidebar_emulator_id"!==s&&"option_name"!==s&&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",s)},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=d('<h3 class="so-parent-link"></h3>').html(this.parentDialog.text+'<div class="so-separator"></div>');t.click(function(e){e.preventDefault(),this.closeDialog(),this.parentDialog.dialog.openDialog()}.bind(this)),this.$(".so-title-bar .so-title").before(t)}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(),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(),e.silent||(this.trigger("close_dialog_complete"),this.builder.trigger("close_dialog",this))},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-save":"closeAndSave","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(){if(this.setElement(this.template()),this.$el.hide(),0<o("#submitdiv #save-post").length){var e=this.$el.find(".live-editor-save");e.text(e.data("save"))}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")},closeAndSave:function(){this.close(),o('#submitdiv input[type="submit"][name="save"]').click()},collapse:function(){this.$el.toggleClass("so-collapsed")},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){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(),widget_class:this.model.attributes.class})),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 c=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=c('<div class="media-widget-control"></div>');n.before(a);var r={};n.find(".media-widget-instance-property").each(function(){var e=c(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 c=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=c("<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-2106.js → siteorigin-panels-2107.js}
RENAMED
@@ -383,2727 +383,2727 @@ module.exports = panels.view.dialog.extend( {
|
|
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 |
-
|
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.openSelectedCellStyles();
|
846 |
-
}, this);
|
847 |
-
|
848 |
-
// This is the default row layout
|
849 |
-
this.row = {
|
850 |
-
cells: new panels.collection.cells([{weight: 0.5}, {weight: 0.5}]),
|
851 |
-
style: {}
|
852 |
-
};
|
853 |
-
|
854 |
-
// Refresh panels data after both dialog form components are loaded
|
855 |
-
this.dialogFormsLoaded = 0;
|
856 |
-
var thisView = this;
|
857 |
-
this.on('form_loaded styles_loaded', function () {
|
858 |
-
this.dialogFormsLoaded++;
|
859 |
-
if (this.dialogFormsLoaded === 2) {
|
860 |
-
thisView.updateModel({
|
861 |
-
refreshArgs: {
|
862 |
-
silent: true
|
863 |
-
}
|
864 |
-
});
|
865 |
-
}
|
866 |
-
});
|
867 |
-
|
868 |
-
this.on('close_dialog', this.closeHandler);
|
869 |
-
|
870 |
-
this.on( 'edit_label', function ( text ) {
|
871 |
-
// If text is set to default values, just clear it.
|
872 |
-
if ( text === panelsOptions.loc.row.add || text === panelsOptions.loc.row.edit ) {
|
873 |
-
text = '';
|
874 |
-
}
|
875 |
-
this.model.set( 'label', text );
|
876 |
-
if ( _.isEmpty( text ) ) {
|
877 |
-
var title = this.dialogType === 'create' ? panelsOptions.loc.row.add : panelsOptions.loc.row.edit;
|
878 |
-
this.$( '.so-title').text( title );
|
879 |
-
}
|
880 |
-
}.bind( this ) );
|
881 |
-
},
|
882 |
-
|
883 |
-
/**
|
884 |
-
*
|
885 |
-
* @param dialogType Either "edit" or "create"
|
886 |
-
*/
|
887 |
-
setRowDialogType: function (dialogType) {
|
888 |
-
this.dialogType = dialogType;
|
889 |
-
},
|
890 |
-
|
891 |
-
/**
|
892 |
-
* Render the new row dialog
|
893 |
-
*/
|
894 |
-
render: function () {
|
895 |
-
var title = this.dialogType === 'create' ? panelsOptions.loc.row.add : panelsOptions.loc.row.edit;
|
896 |
-
this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-row' ).html(), {
|
897 |
-
title: title,
|
898 |
-
dialogType: this.dialogType
|
899 |
-
} ) );
|
900 |
-
|
901 |
-
var titleElt = this.$( '.so-title' );
|
902 |
-
|
903 |
-
if ( this.model.has( 'label' ) && ! _.isEmpty( this.model.get( 'label' ) ) ) {
|
904 |
-
titleElt.text( this.model.get( 'label' ) );
|
905 |
-
}
|
906 |
-
this.$( '.so-edit-title' ).val( titleElt.text() );
|
907 |
-
|
908 |
-
if (!this.builder.supports('addRow')) {
|
909 |
-
this.$('.so-buttons .so-duplicate').remove();
|
910 |
-
}
|
911 |
-
if (!this.builder.supports('deleteRow')) {
|
912 |
-
this.$('.so-buttons .so-delete').remove();
|
913 |
-
}
|
914 |
-
|
915 |
-
if (!_.isUndefined(this.model)) {
|
916 |
-
// Set the initial value of the
|
917 |
-
this.$( 'input[name="cells"].so-row-field' ).val( this.model.get( 'cells' ).length );
|
918 |
-
if ( this.model.has( 'ratio' ) ) {
|
919 |
-
this.$( 'select[name="ratio"].so-row-field' ).val( this.model.get( 'ratio' ) );
|
920 |
-
}
|
921 |
-
if ( this.model.has( 'ratio_direction' ) ) {
|
922 |
-
this.$( 'select[name="ratio_direction"].so-row-field' ).val( this.model.get( 'ratio_direction' ) );
|
923 |
-
}
|
924 |
-
}
|
925 |
-
|
926 |
-
this.$('input.so-row-field').keyup(function () {
|
927 |
-
$(this).trigger('change');
|
928 |
-
});
|
929 |
-
|
930 |
-
return this;
|
931 |
-
},
|
932 |
-
|
933 |
-
renderStyles: function () {
|
934 |
-
if ( this.styles ) {
|
935 |
-
this.styles.off( 'styles_loaded' );
|
936 |
-
this.styles.remove();
|
937 |
-
}
|
938 |
-
|
939 |
-
// Now we need to attach the style window
|
940 |
-
this.styles = new panels.view.styles();
|
941 |
-
this.styles.model = this.model;
|
942 |
-
this.styles.render('row', this.builder.config.postId, {
|
943 |
-
builderType: this.builder.config.builderType,
|
944 |
-
dialog: this
|
945 |
-
});
|
946 |
-
|
947 |
-
var $rightSidebar = this.$('.so-sidebar.so-right-sidebar');
|
948 |
-
this.styles.attach( $rightSidebar );
|
949 |
-
|
950 |
-
// Handle the loading class
|
951 |
-
this.styles.on('styles_loaded', function (hasStyles) {
|
952 |
-
if ( ! hasStyles ) {
|
953 |
-
// If we don't have styles remove the view.
|
954 |
-
this.styles.remove();
|
955 |
-
|
956 |
-
// If the sidebar is empty, hide it.
|
957 |
-
if ( $rightSidebar.children().length === 0 ) {
|
958 |
-
$rightSidebar.closest('.so-panels-dialog').removeClass('so-panels-dialog-has-right-sidebar');
|
959 |
-
$rightSidebar.hide();
|
960 |
-
}
|
961 |
-
}
|
962 |
-
}, this);
|
963 |
-
},
|
964 |
-
|
965 |
-
/**
|
966 |
-
* Set the row model we'll be using for this dialog.
|
967 |
-
*
|
968 |
-
* @param model
|
969 |
-
*/
|
970 |
-
setRowModel: function (model) {
|
971 |
-
this.model = model;
|
972 |
-
|
973 |
-
if (_.isEmpty(this.model)) {
|
974 |
-
return this;
|
975 |
-
}
|
976 |
-
|
977 |
-
// Set the rows to be a copy of the model
|
978 |
-
this.row = {
|
979 |
-
cells: this.model.get('cells').clone(),
|
980 |
-
style: {},
|
981 |
-
ratio: this.model.get('ratio'),
|
982 |
-
ratio_direction: this.model.get('ratio_direction'),
|
983 |
-
};
|
984 |
-
|
985 |
-
// Set the initial value of the cell field.
|
986 |
-
this.$( 'input[name="cells"].so-row-field' ).val( this.model.get( 'cells' ).length );
|
987 |
-
if ( this.model.has( 'ratio' ) ) {
|
988 |
-
this.$( 'select[name="ratio"].so-row-field' ).val( this.model.get( 'ratio' ) );
|
989 |
-
}
|
990 |
-
if ( this.model.has( 'ratio_direction' ) ) {
|
991 |
-
this.$( 'select[name="ratio_direction"].so-row-field' ).val( this.model.get( 'ratio_direction' ) );
|
992 |
-
}
|
993 |
-
|
994 |
-
this.clearCellStylesCache();
|
995 |
-
|
996 |
-
return this;
|
997 |
-
},
|
998 |
-
|
999 |
-
/**
|
1000 |
-
* Regenerate the row preview and resizing interface.
|
1001 |
-
*/
|
1002 |
-
regenerateRowPreview: function () {
|
1003 |
-
var thisDialog = this;
|
1004 |
-
var rowPreview = this.$('.row-preview');
|
1005 |
-
|
1006 |
-
// If no selected cell, select the first cell.
|
1007 |
-
var selectedIndex = this.getSelectedCellIndex();
|
1008 |
-
|
1009 |
-
rowPreview.empty();
|
1010 |
-
|
1011 |
-
var timeout;
|
1012 |
-
|
1013 |
-
// Represent the cells
|
1014 |
-
this.row.cells.each(function (cellModel, i) {
|
1015 |
-
var newCell = $(this.cellPreviewTemplate({weight: cellModel.get('weight')}));
|
1016 |
-
rowPreview.append(newCell);
|
1017 |
-
|
1018 |
-
if(i == selectedIndex) {
|
1019 |
-
newCell.find('.preview-cell-in').addClass('cell-selected');
|
1020 |
-
}
|
1021 |
-
|
1022 |
-
var prevCell = newCell.prev();
|
1023 |
-
var handle;
|
1024 |
-
|
1025 |
-
if (prevCell.length) {
|
1026 |
-
handle = $('<div class="resize-handle"></div>');
|
1027 |
-
handle
|
1028 |
-
.appendTo(newCell)
|
1029 |
-
.dblclick(function () {
|
1030 |
-
var prevCellModel = thisDialog.row.cells.at(i - 1);
|
1031 |
-
var t = cellModel.get('weight') + prevCellModel.get('weight');
|
1032 |
-
cellModel.set('weight', t / 2);
|
1033 |
-
prevCellModel.set('weight', t / 2);
|
1034 |
-
thisDialog.scaleRowWidths();
|
1035 |
-
});
|
1036 |
-
|
1037 |
-
handle.draggable({
|
1038 |
-
axis: 'x',
|
1039 |
-
containment: rowPreview,
|
1040 |
-
start: function (e, ui) {
|
1041 |
-
|
1042 |
-
// Create the clone for the current cell
|
1043 |
-
var newCellClone = newCell.clone().appendTo(ui.helper).css({
|
1044 |
-
position: 'absolute',
|
1045 |
-
top: '0',
|
1046 |
-
width: newCell.outerWidth(),
|
1047 |
-
left: 6,
|
1048 |
-
height: newCell.outerHeight()
|
1049 |
-
});
|
1050 |
-
newCellClone.find('.resize-handle').remove();
|
1051 |
-
|
1052 |
-
// Create the clone for the previous cell
|
1053 |
-
var prevCellClone = prevCell.clone().appendTo(ui.helper).css({
|
1054 |
-
position: 'absolute',
|
1055 |
-
top: '0',
|
1056 |
-
width: prevCell.outerWidth(),
|
1057 |
-
right: 6,
|
1058 |
-
height: prevCell.outerHeight()
|
1059 |
-
});
|
1060 |
-
prevCellClone.find('.resize-handle').remove();
|
1061 |
-
|
1062 |
-
$(this).data({
|
1063 |
-
'newCellClone': newCellClone,
|
1064 |
-
'prevCellClone': prevCellClone
|
1065 |
-
});
|
1066 |
-
|
1067 |
-
// Hide the
|
1068 |
-
newCell.find('> .preview-cell-in').css('visibility', 'hidden');
|
1069 |
-
prevCell.find('> .preview-cell-in').css('visibility', 'hidden');
|
1070 |
-
},
|
1071 |
-
drag: function (e, ui) {
|
1072 |
-
// Calculate the new cell and previous cell widths as a percent
|
1073 |
-
var cellWeight = thisDialog.row.cells.at(i).get('weight');
|
1074 |
-
var prevCellWeight = thisDialog.row.cells.at(i - 1).get('weight');
|
1075 |
-
var ncw = cellWeight - (
|
1076 |
-
(
|
1077 |
-
ui.position.left + 6
|
1078 |
-
) / rowPreview.width()
|
1079 |
-
);
|
1080 |
-
var pcw = prevCellWeight + (
|
1081 |
-
(
|
1082 |
-
ui.position.left + 6
|
1083 |
-
) / rowPreview.width()
|
1084 |
-
);
|
1085 |
-
|
1086 |
-
var helperLeft = ui.helper.offset().left - rowPreview.offset().left - 6;
|
1087 |
-
|
1088 |
-
$(this).data('newCellClone').css('width', rowPreview.width() * ncw)
|
1089 |
-
.find('.preview-cell-weight').html(Math.round(ncw * 1000) / 10);
|
1090 |
-
|
1091 |
-
$(this).data('prevCellClone').css('width', rowPreview.width() * pcw)
|
1092 |
-
.find('.preview-cell-weight').html(Math.round(pcw * 1000) / 10);
|
1093 |
-
},
|
1094 |
-
stop: function (e, ui) {
|
1095 |
-
// Remove the clones
|
1096 |
-
$(this).data('newCellClone').remove();
|
1097 |
-
$(this).data('prevCellClone').remove();
|
1098 |
-
|
1099 |
-
// Reshow the main cells
|
1100 |
-
newCell.find('.preview-cell-in').css('visibility', 'visible');
|
1101 |
-
prevCell.find('.preview-cell-in').css('visibility', 'visible');
|
1102 |
-
|
1103 |
-
// Calculate the new cell weights
|
1104 |
-
var offset = ui.position.left + 6;
|
1105 |
-
var percent = offset / rowPreview.width();
|
1106 |
-
|
1107 |
-
// Ignore this if any of the cells are below 2% in width.
|
1108 |
-
var cellModel = thisDialog.row.cells.at(i);
|
1109 |
-
var prevCellModel = thisDialog.row.cells.at(i - 1);
|
1110 |
-
if (cellModel.get('weight') - percent > 0.02 && prevCellModel.get('weight') + percent > 0.02) {
|
1111 |
-
cellModel.set('weight', cellModel.get('weight') - percent);
|
1112 |
-
prevCellModel.set('weight', prevCellModel.get('weight') + percent);
|
1113 |
-
}
|
1114 |
-
|
1115 |
-
thisDialog.scaleRowWidths();
|
1116 |
-
ui.helper.css('left', -6);
|
1117 |
-
}
|
1118 |
-
});
|
1119 |
-
}
|
1120 |
-
|
1121 |
-
newCell.click(function (event) {
|
1122 |
-
|
1123 |
-
if ( ! ( $(event.target).is('.preview-cell') || $(event.target).is('.preview-cell-in') ) ) {
|
1124 |
-
return;
|
1125 |
-
}
|
1126 |
-
|
1127 |
-
var cell = $(event.target);
|
1128 |
-
cell.closest('.row-preview').find('.preview-cell .preview-cell-in').removeClass('cell-selected');
|
1129 |
-
cell.addClass('cell-selected');
|
1130 |
-
|
1131 |
-
this.openSelectedCellStyles();
|
1132 |
-
|
1133 |
-
}.bind(this));
|
1134 |
-
|
1135 |
-
// Make this row weight click editable
|
1136 |
-
newCell.find('.preview-cell-weight').click(function (ci) {
|
1137 |
-
|
1138 |
-
// Disable the draggable while entering values
|
1139 |
-
thisDialog.$('.resize-handle').css('pointer-event', 'none').draggable('disable');
|
1140 |
-
|
1141 |
-
rowPreview.find('.preview-cell-weight').each(function () {
|
1142 |
-
var $$ = jQuery(this).hide();
|
1143 |
-
$('<input type="text" class="preview-cell-weight-input no-user-interacted" />')
|
1144 |
-
.val(parseFloat($$.html())).insertAfter($$)
|
1145 |
-
.focus(function () {
|
1146 |
-
clearTimeout(timeout);
|
1147 |
-
})
|
1148 |
-
.keyup(function (e) {
|
1149 |
-
if (e.keyCode !== 9) {
|
1150 |
-
// Only register the interaction if the user didn't press tab
|
1151 |
-
$(this).removeClass('no-user-interacted');
|
1152 |
-
}
|
1153 |
-
|
1154 |
-
// Enter is clicked
|
1155 |
-
if (e.keyCode === 13) {
|
1156 |
-
e.preventDefault();
|
1157 |
-
$(this).blur();
|
1158 |
-
}
|
1159 |
-
})
|
1160 |
-
.keydown(function (e) {
|
1161 |
-
if (e.keyCode === 9) {
|
1162 |
-
e.preventDefault();
|
1163 |
-
|
1164 |
-
// Tab will always cycle around the row inputs
|
1165 |
-
var inputs = rowPreview.find('.preview-cell-weight-input');
|
1166 |
-
var i = inputs.index($(this));
|
1167 |
-
if (i === inputs.length - 1) {
|
1168 |
-
inputs.eq(0).focus().select();
|
1169 |
-
} else {
|
1170 |
-
inputs.eq(i + 1).focus().select();
|
1171 |
-
}
|
1172 |
-
}
|
1173 |
-
})
|
1174 |
-
.blur(function () {
|
1175 |
-
rowPreview.find('.preview-cell-weight-input').each(function (i, el) {
|
1176 |
-
if (isNaN(parseFloat($(el).val()))) {
|
1177 |
-
$(el).val(Math.floor(thisDialog.row.cells.at(i).get('weight') * 1000) / 10);
|
1178 |
-
}
|
1179 |
-
});
|
1180 |
-
|
1181 |
-
timeout = setTimeout(function () {
|
1182 |
-
// If there are no weight inputs, then skip this
|
1183 |
-
if (rowPreview.find('.preview-cell-weight-input').length === 0) {
|
1184 |
-
return false;
|
1185 |
-
}
|
1186 |
-
|
1187 |
-
// Go through all the inputs
|
1188 |
-
var rowWeights = [],
|
1189 |
-
rowChanged = [],
|
1190 |
-
changedSum = 0,
|
1191 |
-
unchangedSum = 0;
|
1192 |
-
|
1193 |
-
rowPreview.find('.preview-cell-weight-input').each(function (i, el) {
|
1194 |
-
var val = parseFloat($(el).val());
|
1195 |
-
if (isNaN(val)) {
|
1196 |
-
val = 1 / thisDialog.row.cells.length;
|
1197 |
-
} else {
|
1198 |
-
val = Math.round(val * 10) / 1000;
|
1199 |
-
}
|
1200 |
-
|
1201 |
-
// Check within 3 decimal points
|
1202 |
-
var changed = !$(el).hasClass('no-user-interacted');
|
1203 |
-
|
1204 |
-
rowWeights.push(val);
|
1205 |
-
rowChanged.push(changed);
|
1206 |
-
|
1207 |
-
if (changed) {
|
1208 |
-
changedSum += val;
|
1209 |
-
} else {
|
1210 |
-
unchangedSum += val;
|
1211 |
-
}
|
1212 |
-
});
|
1213 |
-
|
1214 |
-
if (changedSum > 0 && unchangedSum > 0 && (
|
1215 |
-
1 - changedSum
|
1216 |
-
) > 0) {
|
1217 |
-
// Balance out the unchanged rows to occupy the weight left over by the changed sum
|
1218 |
-
for (var i = 0; i < rowWeights.length; i++) {
|
1219 |
-
if (!rowChanged[i]) {
|
1220 |
-
rowWeights[i] = (
|
1221 |
-
rowWeights[i] / unchangedSum
|
1222 |
-
) * (
|
1223 |
-
1 - changedSum
|
1224 |
-
);
|
1225 |
-
}
|
1226 |
-
}
|
1227 |
-
}
|
1228 |
-
|
1229 |
-
// Last check to ensure total weight is 1
|
1230 |
-
var sum = _.reduce(rowWeights, function (memo, num) {
|
1231 |
-
return memo + num;
|
1232 |
-
});
|
1233 |
-
rowWeights = rowWeights.map(function (w) {
|
1234 |
-
return w / sum;
|
1235 |
-
});
|
1236 |
-
|
1237 |
-
// Set the new cell weights and regenerate the preview.
|
1238 |
-
if (Math.min.apply(Math, rowWeights) > 0.01) {
|
1239 |
-
thisDialog.row.cells.each(function (cell, i) {
|
1240 |
-
cell.set('weight', rowWeights[i]);
|
1241 |
-
});
|
1242 |
-
}
|
1243 |
-
|
1244 |
-
// Now lets animate the cells into their new widths
|
1245 |
-
rowPreview.find('.preview-cell').each(function (i, el) {
|
1246 |
-
var cellWeight = thisDialog.row.cells.at(i).get('weight');
|
1247 |
-
$(el).animate({'width': Math.round(cellWeight * 1000) / 10 + "%"}, 250);
|
1248 |
-
$(el).find('.preview-cell-weight-input').val(Math.round(cellWeight * 1000) / 10);
|
1249 |
-
});
|
1250 |
-
|
1251 |
-
// So the draggable handle is not hidden.
|
1252 |
-
rowPreview.find('.preview-cell').css('overflow', 'visible');
|
1253 |
-
setTimeout(thisDialog.regenerateRowPreview.bind(thisDialog), 260);
|
1254 |
-
|
1255 |
-
}, 100);
|
1256 |
-
})
|
1257 |
-
.click(function () {
|
1258 |
-
$(this).select();
|
1259 |
-
});
|
1260 |
-
});
|
1261 |
-
|
1262 |
-
$(this).siblings('.preview-cell-weight-input').select();
|
1263 |
-
|
1264 |
-
});
|
1265 |
-
|
1266 |
-
}, this);
|
1267 |
-
|
1268 |
-
this.trigger('form_loaded', this);
|
1269 |
-
},
|
1270 |
-
|
1271 |
-
getSelectedCellIndex: function() {
|
1272 |
-
var selectedIndex = -1;
|
1273 |
-
this.$('.preview-cell .preview-cell-in').each(function(index, el) {
|
1274 |
-
if($(el).is('.cell-selected')) {
|
1275 |
-
selectedIndex = index;
|
1276 |
-
}
|
1277 |
-
});
|
1278 |
-
return selectedIndex;
|
1279 |
-
},
|
1280 |
-
|
1281 |
-
openSelectedCellStyles: function() {
|
1282 |
-
if (!_.isUndefined(this.cellStyles)) {
|
1283 |
-
if (this.cellStyles.stylesLoaded) {
|
1284 |
-
var style = {};
|
1285 |
-
try {
|
1286 |
-
style = this.getFormValues('.so-sidebar .so-visual-styles.so-cell-styles').style;
|
1287 |
-
}
|
1288 |
-
catch (err) {
|
1289 |
-
console.log('Error retrieving cell styles - ' + err.message);
|
1290 |
-
}
|
1291 |
-
|
1292 |
-
this.cellStyles.model.set('style', style);
|
1293 |
-
}
|
1294 |
-
this.cellStyles.detach();
|
1295 |
-
}
|
1296 |
-
|
1297 |
-
this.cellStyles = this.getSelectedCellStyles();
|
1298 |
-
|
1299 |
-
if ( this.cellStyles ) {
|
1300 |
-
var $rightSidebar = this.$( '.so-sidebar.so-right-sidebar' );
|
1301 |
-
this.cellStyles.attach( $rightSidebar );
|
1302 |
-
this.cellStyles.on( 'styles_loaded', function ( hasStyles ) {
|
1303 |
-
if ( hasStyles ) {
|
1304 |
-
$rightSidebar.closest('.so-panels-dialog').addClass('so-panels-dialog-has-right-sidebar');
|
1305 |
-
$rightSidebar.show();
|
1306 |
-
}
|
1307 |
-
} );
|
1308 |
-
}
|
1309 |
-
},
|
1310 |
-
|
1311 |
-
getSelectedCellStyles: function () {
|
1312 |
-
var cellIndex = this.getSelectedCellIndex();
|
1313 |
-
if ( cellIndex > -1 ) {
|
1314 |
-
var cellStyles = this.cellStylesCache[cellIndex];
|
1315 |
-
if ( !cellStyles ) {
|
1316 |
-
cellStyles = new panels.view.styles();
|
1317 |
-
cellStyles.model = this.row.cells.at( cellIndex );
|
1318 |
-
cellStyles.render( 'cell', this.builder.config.postId, {
|
1319 |
-
builderType: this.builder.config.builderType,
|
1320 |
-
dialog: this,
|
1321 |
-
index: cellIndex,
|
1322 |
-
} );
|
1323 |
-
this.cellStylesCache[cellIndex] = cellStyles;
|
1324 |
-
}
|
1325 |
-
}
|
1326 |
-
|
1327 |
-
return cellStyles;
|
1328 |
-
},
|
1329 |
-
|
1330 |
-
clearCellStylesCache: function () {
|
1331 |
-
// Call remove() on all cell styles to remove data, event listeners etc.
|
1332 |
-
this.cellStylesCache.forEach(function (cellStyles) {
|
1333 |
-
cellStyles.remove();
|
1334 |
-
cellStyles.off( 'styles_loaded' );
|
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 |
-
|
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 |
-
|
1891 |
-
|
1892 |
-
|
1893 |
-
|
1894 |
-
|
1895 |
-
|
1896 |
-
|
1897 |
-
|
1898 |
-
|
1899 |
-
|
1900 |
-
|
1901 |
-
|
1902 |
-
|
1903 |
-
|
1904 |
-
|
1905 |
-
'
|
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, key ) {
|
1951 |
-
$( this.dialogTabTemplate( {'title': tab.title, 'tab': key} ) ).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 |
-
*
|
2135 |
-
* @returns {boolean|*}
|
2136 |
Â
*/
|
2137 |
-
|
2138 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2139 |
Â
},
|
2140 |
Â
|
2141 |
Â
/**
|
2142 |
-
*
|
2143 |
Â
*/
|
2144 |
-
|
2145 |
-
|
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 |
-
|
2157 |
-
localStorage[ 'panels_clipboard_' + panelsOptions.user ] = JSON.stringify( serial );
|
2158 |
-
return true;
|
2159 |
Â
},
|
2160 |
Â
|
2161 |
Â
/**
|
2162 |
-
*
|
Â
|
|
Â
|
|
2163 |
Â
*/
|
2164 |
-
|
2165 |
-
|
2166 |
-
|
2167 |
-
|
Â
|
|
Â
|
|
2168 |
Â
|
2169 |
-
|
2170 |
-
|
2171 |
-
|
2172 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2173 |
Â
}
|
2174 |
Â
|
2175 |
-
|
2176 |
Â
},
|
2177 |
Â
|
2178 |
Â
/**
|
2179 |
-
*
|
2180 |
Â
*/
|
2181 |
-
|
2182 |
-
|
2183 |
-
|
2184 |
-
}
|
2185 |
Â
|
2186 |
-
var
|
2187 |
-
|
2188 |
-
|
2189 |
-
|
2190 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2191 |
Â
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2192 |
Â
}
|
2193 |
Â
|
2194 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2195 |
Â
},
|
2196 |
-
};
|
2197 |
Â
|
2198 |
-
},{}],12:[function(require,module,exports){
|
2199 |
-
module.exports = {
|
2200 |
Â
/**
|
2201 |
-
*
|
Â
|
|
Â
|
|
2202 |
Â
*/
|
2203 |
-
|
2204 |
-
|
2205 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2206 |
Â
}
|
2207 |
Â
|
2208 |
-
|
2209 |
-
|
2210 |
-
|
2211 |
-
|
2212 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2213 |
Â
|
2214 |
-
|
2215 |
-
|
2216 |
-
'scroll-position': scrollPosition
|
2217 |
-
} )
|
2218 |
-
.css( 'overflow', 'hidden' );
|
2219 |
Â
|
2220 |
-
|
2221 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2222 |
Â
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2223 |
Â
},
|
2224 |
Â
|
2225 |
Â
/**
|
2226 |
-
*
|
Â
|
|
2227 |
Â
*/
|
2228 |
-
|
2229 |
-
|
2230 |
-
|
2231 |
-
|
Â
|
|
Â
|
|
2232 |
Â
|
2233 |
-
|
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 |
-
|
2239 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2240 |
Â
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2241 |
Â
}
|
2242 |
Â
},
|
2243 |
-
};
|
2244 |
Â
|
2245 |
-
|
2246 |
-
|
2247 |
-
|
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 |
-
|
2357 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2358 |
Â
|
2359 |
-
|
2360 |
-
|
2361 |
-
|
2362 |
-
|
Â
|
|
Â
|
|
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 |
-
|
2373 |
-
|
2374 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2375 |
Â
}
|
2376 |
-
s = s.replace( /{{%/g, '<%' );
|
2377 |
-
s = s.replace( /%}}/g, '%>' );
|
2378 |
-
s = s.trim();
|
2379 |
-
return s;
|
2380 |
Â
},
|
2381 |
Â
|
2382 |
-
|
2383 |
-
|
2384 |
-
|
2385 |
-
|
2386 |
-
|
2387 |
-
|
2388 |
-
|
2389 |
-
},
|
2390 |
Â
|
2391 |
-
}
|
Â
|
|
2392 |
Â
|
2393 |
-
|
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 |
-
|
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 |
-
// Trigger an event before the panels setup to allow adding listeners for various builder events which are
|
2600 |
-
// triggered during initial setup.
|
2601 |
-
$(document).trigger('before_panels_setup', builderView);
|
2602 |
-
|
2603 |
-
// Set up the builder view
|
2604 |
-
builderView
|
2605 |
-
.render()
|
2606 |
-
.attach( {
|
2607 |
-
container: container
|
2608 |
-
} )
|
2609 |
-
.setDataField( field )
|
2610 |
-
.attachToEditor();
|
2611 |
-
|
2612 |
-
// When the form is submitted, update the panels data
|
2613 |
-
form.submit( function () {
|
2614 |
-
// Refresh the data
|
2615 |
-
builderModel.refreshPanelsData();
|
2616 |
-
} );
|
2617 |
-
|
2618 |
-
container.removeClass( 'so-panels-loading' );
|
2619 |
-
|
2620 |
-
// Trigger a global jQuery event after we've setup the builder view. Everything is accessible form there
|
2621 |
-
$( document ).trigger( 'panels_setup', builderView, window.panels );
|
2622 |
-
}
|
2623 |
-
|
2624 |
-
// Setup new widgets when they're added in the standard widget interface
|
2625 |
-
$( document ).on( 'widget-added', function ( e, widget ) {
|
2626 |
-
$( widget ).find( '.siteorigin-page-builder-widget' ).soPanelsSetupBuilderWidget();
|
2627 |
-
} );
|
2628 |
-
|
2629 |
-
// Setup existing widgets on the page (for the widgets interface)
|
2630 |
-
if ( ! $( 'body' ).hasClass( 'wp-customizer' ) ) {
|
2631 |
-
$( function () {
|
2632 |
-
$( '.siteorigin-page-builder-widget' ).soPanelsSetupBuilderWidget();
|
2633 |
-
} );
|
2634 |
-
}
|
2635 |
-
|
2636 |
-
// A global escape handler
|
2637 |
-
$(window).on('keyup', function(e){
|
2638 |
-
// [Esc] to close
|
2639 |
-
if ( e.which === 27 ) {
|
2640 |
-
// Trigger a click on the last visible Page Builder window
|
2641 |
-
$( '.so-panels-dialog-wrapper, .so-panels-live-editor' ).filter(':visible')
|
2642 |
-
.last().find('.so-title-bar .so-close, .live-editor-close').click();
|
2643 |
-
}
|
2644 |
-
});
|
2645 |
-
} );
|
2646 |
Â
|
2647 |
-
|
2648 |
-
module.exports = Backbone.Model.extend({
|
2649 |
-
layoutPosition: {
|
2650 |
-
BEFORE: 'before',
|
2651 |
-
AFTER: 'after',
|
2652 |
-
REPLACE: 'replace',
|
2653 |
-
},
|
2654 |
Â
|
2655 |
-
|
Â
|
|
2656 |
Â
|
2657 |
-
|
2658 |
-
'
|
2659 |
-
|
2660 |
-
|
2661 |
-
|
2662 |
-
}
|
2663 |
-
},
|
2664 |
Â
|
2665 |
-
|
2666 |
-
|
2667 |
-
|
2668 |
Â
},
|
2669 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2670 |
Â
/**
|
2671 |
-
*
|
2672 |
-
*
|
2673 |
-
* @param attrs
|
2674 |
-
* @param cells
|
2675 |
-
* @param options
|
2676 |
Â
*/
|
2677 |
-
|
2678 |
-
|
2679 |
-
|
2680 |
-
|
2681 |
-
|
2682 |
-
|
2683 |
Â
|
2684 |
-
|
2685 |
-
collection: this.get('rows'),
|
2686 |
-
cells: cellCollection,
|
2687 |
-
}, attrs);
|
2688 |
Â
|
2689 |
-
|
2690 |
-
|
2691 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2692 |
Â
|
2693 |
-
|
Â
|
|
Â
|
|
Â
|
|
2694 |
Â
|
2695 |
-
|
2696 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2697 |
Â
|
2698 |
Â
/**
|
2699 |
-
* Load the panels data into the builder
|
2700 |
Â
*
|
2701 |
-
* @param
|
2702 |
-
* @param position string Where to place the new layout. Allowed options are 'before', 'after'. Anything else will
|
2703 |
-
* cause the new layout to replace the old one.
|
2704 |
Â
*/
|
2705 |
-
|
2706 |
-
|
2707 |
-
|
2708 |
-
data = this.concatPanelsData( data, this.getPanelsData() );
|
2709 |
-
} else if ( position === this.layoutPosition.AFTER ) {
|
2710 |
-
data = this.concatPanelsData( this.getPanelsData(), data );
|
2711 |
-
}
|
2712 |
Â
|
2713 |
-
|
2714 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2715 |
Â
|
2716 |
-
|
2717 |
-
this.set( 'data', JSON.parse( JSON.stringify( data ) ), {silent: true} );
|
2718 |
Â
|
2719 |
-
|
2720 |
-
|
Â
|
|
Â
|
|
2721 |
Â
|
2722 |
-
|
2723 |
-
|
2724 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2725 |
Â
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2726 |
Â
|
2727 |
-
|
2728 |
-
|
2729 |
-
|
2730 |
-
if ( _.isUndefined( rows[gi] ) ) {
|
2731 |
-
rows[gi] = [];
|
2732 |
-
}
|
2733 |
Â
|
2734 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2735 |
Â
}
|
Â
|
|
Â
|
|
2736 |
Â
|
2737 |
-
|
2738 |
-
|
2739 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2740 |
Â
|
2741 |
-
|
2742 |
-
|
2743 |
-
|
2744 |
Â
|
2745 |
-
|
2746 |
-
|
2747 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2748 |
Â
|
2749 |
-
|
2750 |
-
|
2751 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2752 |
Â
|
2753 |
-
|
2754 |
-
rowAttrs.color_label = data.grids[i].color_label;
|
2755 |
-
}
|
2756 |
Â
|
2757 |
-
|
2758 |
-
|
2759 |
-
|
2760 |
-
|
2761 |
-
|
2762 |
-
|
Â
|
|
Â
|
|
Â
|
|
2763 |
Â
|
Â
|
|
Â
|
|
2764 |
Â
|
2765 |
-
|
2766 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2767 |
Â
}
|
2768 |
Â
|
2769 |
-
|
2770 |
-
|
2771 |
-
|
2772 |
-
|
2773 |
-
|
2774 |
-
|
2775 |
-
|
2776 |
-
|
2777 |
-
|
2778 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2779 |
Â
|
2780 |
-
|
2781 |
-
|
Â
|
|
Â
|
|
Â
|
|
2782 |
Â
|
2783 |
-
|
2784 |
-
class: panels_info.class,
|
2785 |
-
values: widgetData
|
2786 |
-
} );
|
2787 |
Â
|
2788 |
-
if ( !
|
2789 |
-
|
2790 |
Â
}
|
2791 |
Â
|
2792 |
-
|
2793 |
-
|
2794 |
-
|
2795 |
-
|
2796 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2797 |
Â
}
|
2798 |
-
|
2799 |
-
|
2800 |
Â
}
|
2801 |
Â
|
2802 |
-
|
2803 |
-
|
2804 |
-
|
Â
|
|
2805 |
Â
|
2806 |
-
|
2807 |
-
cell.get('widgets').add( newWidget, { noAnimate: true } );
|
2808 |
-
} );
|
2809 |
Â
|
2810 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2811 |
Â
}
|
2812 |
-
|
2813 |
-
console.log( 'Error loading data: ' + err.message );
|
2814 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2815 |
Â
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2816 |
Â
},
|
2817 |
Â
|
2818 |
Â
/**
|
2819 |
-
*
|
2820 |
-
* part it's up to the caller to ensure the Page Builder data is well formed.
|
2821 |
Â
*/
|
2822 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2823 |
Â
|
2824 |
-
|
2825 |
-
|
2826 |
-
|
2827 |
-
|
2828 |
Â
|
2829 |
-
|
2830 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2831 |
Â
}
|
2832 |
Â
|
2833 |
-
var gridsBOffset = panelsDataA.grids.length;
|
2834 |
-
var widgetsBOffset = ! _.isUndefined( panelsDataA.widgets ) ? panelsDataA.widgets.length : 0;
|
2835 |
-
var newPanelsData = {grids: [], 'grid_cells': [], 'widgets': []};
|
2836 |
Â
|
2837 |
-
//
|
2838 |
-
|
Â
|
|
2839 |
Â
|
2840 |
-
|
2841 |
-
|
2842 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2843 |
Â
}
|
2844 |
-
|
2845 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2846 |
Â
}
|
2847 |
Â
|
2848 |
-
|
2849 |
-
|
2850 |
-
|
2851 |
-
var
|
2852 |
-
|
2853 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2854 |
Â
}
|
2855 |
Â
|
2856 |
-
//
|
2857 |
-
if (
|
2858 |
-
|
2859 |
-
|
2860 |
-
|
2861 |
-
|
2862 |
-
|
Â
|
|
Â
|
|
2863 |
Â
}
|
Â
|
|
Â
|
|
2864 |
Â
}
|
2865 |
Â
|
2866 |
-
|
Â
|
|
Â
|
|
2867 |
Â
},
|
2868 |
Â
|
2869 |
Â
/**
|
2870 |
-
*
|
2871 |
Â
*/
|
2872 |
-
|
Â
|
|
2873 |
Â
|
2874 |
-
|
2875 |
Â
|
2876 |
-
var
|
2877 |
-
|
2878 |
-
|
2879 |
-
'grid_cells': []
|
2880 |
-
};
|
2881 |
-
var widgetId = 0;
|
2882 |
Â
|
2883 |
-
|
Â
|
|
Â
|
|
Â
|
|
2884 |
Â
|
2885 |
-
|
Â
|
|
Â
|
|
2886 |
Â
|
2887 |
-
|
2888 |
-
// Add the data for the widget, including the panels_info field.
|
2889 |
-
var panels_info = {
|
2890 |
-
class: widget.get( 'class' ),
|
2891 |
-
raw: widget.get( 'raw' ),
|
2892 |
-
grid: ri,
|
2893 |
-
cell: ci,
|
2894 |
-
// Strictly this should be an index
|
2895 |
-
id: widgetId ++,
|
2896 |
-
widget_id: widget.get( 'widget_id' ),
|
2897 |
-
style: widget.get( 'style' ),
|
2898 |
-
label: widget.get( 'label' ),
|
2899 |
-
};
|
2900 |
-
|
2901 |
-
if( _.isEmpty( panels_info.widget_id ) ) {
|
2902 |
-
panels_info.widget_id = panels.helpers.utils.generateUUID();
|
2903 |
-
}
|
2904 |
Â
|
2905 |
-
|
2906 |
-
panels_info: panels_info
|
2907 |
-
} );
|
2908 |
-
data.widgets.push( values );
|
2909 |
-
} );
|
2910 |
Â
|
2911 |
-
|
2912 |
-
|
2913 |
-
grid: ri,
|
2914 |
-
index: ci,
|
2915 |
-
weight: cell.get( 'weight' ),
|
2916 |
-
style: cell.get( 'style' ),
|
2917 |
-
} );
|
2918 |
Â
|
2919 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2920 |
Â
|
2921 |
-
|
2922 |
-
cells: row.get('cells').length,
|
2923 |
-
style: row.get( 'style' ),
|
2924 |
-
ratio: row.get('ratio'),
|
2925 |
-
ratio_direction: row.get('ratio_direction'),
|
2926 |
-
color_label: row.get( 'color_label' ),
|
2927 |
-
label: row.get( 'label' ),
|
2928 |
-
} );
|
2929 |
Â
|
2930 |
-
|
Â
|
|
2931 |
Â
|
2932 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2933 |
Â
|
Â
|
|
2934 |
Â
},
|
2935 |
Â
|
2936 |
Â
/**
|
2937 |
-
*
|
2938 |
Â
*/
|
2939 |
-
|
2940 |
-
|
2941 |
-
silent: false
|
2942 |
-
}, args );
|
2943 |
Â
|
2944 |
-
var
|
2945 |
-
var newData = this.getPanelsData();
|
2946 |
-
this.set( 'data', newData, {silent: true} );
|
2947 |
Â
|
2948 |
-
|
2949 |
-
|
2950 |
-
|
2951 |
-
|
2952 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2953 |
Â
}
|
2954 |
Â
},
|
2955 |
Â
|
2956 |
-
|
2957 |
-
* Empty all the rows and the cells/widgets they contain.
|
2958 |
-
*/
|
2959 |
-
emptyRows: function () {
|
2960 |
-
_.invoke( this.get('rows').toArray(), 'destroy' );
|
2961 |
-
this.get('rows').reset();
|
2962 |
Â
|
2963 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2964 |
Â
},
|
2965 |
Â
|
2966 |
-
|
2967 |
-
|
2968 |
-
|
2969 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
2970 |
Â
},
|
2971 |
Â
|
2972 |
Â
/**
|
2973 |
-
*
|
2974 |
-
* @param html
|
2975 |
Â
*/
|
2976 |
-
|
2977 |
-
|
2978 |
-
|
Â
|
|
2979 |
Â
|
2980 |
-
|
2981 |
-
|
2982 |
-
|
2983 |
-
grids: [],
|
2984 |
-
grid_cells: [],
|
2985 |
-
widgets: [],
|
2986 |
-
};
|
2987 |
Â
|
2988 |
-
|
2989 |
-
|
2990 |
-
|
2991 |
-
|
2992 |
-
|
Â
|
|
2993 |
Â
|
2994 |
-
|
2995 |
-
|
2996 |
-
|
2997 |
-
|
2998 |
-
|
2999 |
-
|
3000 |
-
|
3001 |
-
element.textContent = '';
|
3002 |
-
}
|
3003 |
Â
|
3004 |
-
|
3005 |
-
|
3006 |
Â
|
3007 |
-
|
3008 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3009 |
Â
|
3010 |
-
|
3011 |
-
|
3012 |
-
|
3013 |
-
|
3014 |
-
|
3015 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3016 |
Â
|
3017 |
-
|
3018 |
-
|
3019 |
-
|
3020 |
-
|
3021 |
-
|
Â
|
|
Â
|
|
Â
|
|
3022 |
Â
}
|
Â
|
|
Â
|
|
3023 |
Â
|
3024 |
-
|
3025 |
-
|
3026 |
Â
|
3027 |
-
|
3028 |
-
|
3029 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3030 |
Â
}
|
Â
|
|
Â
|
|
3031 |
Â
|
3032 |
-
|
3033 |
-
|
3034 |
-
text: $divs.eq(i).html(),
|
3035 |
-
};
|
3036 |
-
};
|
3037 |
Â
|
3038 |
-
|
3039 |
-
|
3040 |
-
|
3041 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3042 |
Â
|
3043 |
-
|
3044 |
-
var $row = jQuery( el ),
|
3045 |
-
$cells = $row.find( '.panel-grid-cell' ).filter( filterNestedLayout );
|
3046 |
Â
|
3047 |
-
|
3048 |
-
|
3049 |
-
|
3050 |
-
|
3051 |
-
|
3052 |
-
|
3053 |
-
|
3054 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3055 |
Â
|
3056 |
-
|
3057 |
-
|
3058 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3059 |
Â
|
3060 |
-
|
3061 |
-
|
3062 |
-
weight: ! _.isUndefined( $cell.data( 'weight' ) ) ? parseFloat( $cell.data( 'weight' ) ) : 1,
|
3063 |
-
style: $cell.data( 'style' ),
|
3064 |
-
} );
|
3065 |
Â
|
3066 |
-
|
3067 |
-
|
3068 |
-
|
3069 |
-
|
3070 |
-
|
3071 |
-
|
3072 |
-
|
3073 |
-
|
3074 |
-
|
3075 |
-
};
|
3076 |
Â
|
3077 |
-
|
Â
|
|
Â
|
|
3078 |
Â
|
3079 |
-
|
3080 |
-
|
3081 |
-
|
3082 |
-
|
3083 |
-
|
3084 |
-
|
3085 |
-
|
3086 |
-
|
Â
|
|
Â
|
|
3087 |
Â
|
3088 |
-
|
3089 |
-
panels_info.raw = false;
|
3090 |
Â
|
3091 |
-
|
3092 |
-
|
3093 |
-
|
3094 |
-
|
3095 |
-
// There was a problem, so treat this as a standard editor widget
|
3096 |
-
panels_info.class = editorClass;
|
3097 |
-
panels_data.widgets.push( _.extend( getTextWidgetContents( $widget ), {
|
3098 |
-
filter: "1",
|
3099 |
-
type: "visual",
|
3100 |
-
panels_info: panels_info
|
3101 |
-
} ) );
|
3102 |
-
}
|
3103 |
Â
|
3104 |
-
|
3105 |
-
|
3106 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3107 |
Â
else if( widgetContent.indexOf( 'panel-layout' ) !== -1 ) {
|
3108 |
Â
// Check if this is a layout widget
|
3109 |
Â
var $widgetContent = jQuery( '<div>' + widgetContent + '</div>' );
|
@@ -3115,4190 +3115,4192 @@ module.exports = Backbone.Model.extend({
|
|
3115 |
Â
panels_info: panels_info
|
3116 |
Â
} );
|
3117 |
Â
|
3118 |
-
// continue
|
3119 |
-
return true;
|
3120 |
-
}
|
3121 |
-
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3122 |
Â
|
3123 |
-
|
3124 |
-
|
3125 |
-
|
3126 |
-
|
3127 |
-
|
3128 |
-
|
3129 |
-
|
3130 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3131 |
Â
} );
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3132 |
Â
} );
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3133 |
Â
} );
|
Â
|
|
3134 |
Â
|
3135 |
-
|
3136 |
-
|
3137 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3138 |
Â
|
3139 |
-
|
3140 |
-
|
3141 |
-
|
3142 |
-
|
3143 |
-
|
3144 |
-
|
3145 |
-
|
3146 |
-
|
3147 |
-
|
3148 |
-
|
3149 |
-
|
3150 |
-
|
3151 |
-
text: $html.html().replace(/^\s+|\s+$/gm,''),
|
3152 |
-
title: "",
|
3153 |
-
type: "visual",
|
3154 |
-
panels_info: {
|
3155 |
-
class: editorClass,
|
3156 |
-
raw: false,
|
3157 |
-
grid: panels_data.grids.length - 1,
|
3158 |
-
cell: 0
|
3159 |
-
}
|
3160 |
-
} );
|
3161 |
-
}
|
3162 |
Â
|
3163 |
-
return panels_data;
|
3164 |
-
}
|
3165 |
-
else {
|
3166 |
-
// This is probably just old school post content
|
3167 |
-
return {
|
3168 |
-
grid_cells: [ { grid: 0, weight: 1 } ],
|
3169 |
-
grids: [ { cells: 1 } ],
|
3170 |
-
widgets: [
|
3171 |
-
{
|
3172 |
-
filter: "1",
|
3173 |
-
text: html,
|
3174 |
-
title: "",
|
3175 |
-
type: "visual",
|
3176 |
-
panels_info: {
|
3177 |
-
class: editorClass,
|
3178 |
-
raw: false,
|
3179 |
-
grid: 0,
|
3180 |
-
cell: 0
|
3181 |
-
}
|
3182 |
-
}
|
3183 |
-
]
|
3184 |
-
};
|
3185 |
-
}
|
3186 |
Â
}
|
3187 |
Â
} );
|
3188 |
Â
|
3189 |
-
},{}],
|
3190 |
-
|
3191 |
-
/* A collection of widgets */
|
3192 |
-
widgets: {},
|
3193 |
Â
|
3194 |
-
|
3195 |
-
|
3196 |
Â
|
3197 |
-
|
3198 |
-
|
3199 |
-
|
Â
|
|
Â
|
|
3200 |
Â
},
|
3201 |
Â
|
3202 |
-
|
Â
|
|
3203 |
Â
|
3204 |
Â
/**
|
3205 |
-
*
|
3206 |
Â
*/
|
3207 |
Â
initialize: function () {
|
3208 |
-
|
3209 |
-
this.
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3210 |
Â
},
|
3211 |
Â
|
3212 |
Â
/**
|
3213 |
-
*
|
Â
|
|
Â
|
|
3214 |
Â
*/
|
3215 |
-
|
3216 |
-
|
3217 |
-
|
3218 |
-
this.
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3219 |
Â
},
|
3220 |
Â
|
3221 |
Â
/**
|
3222 |
-
*
|
3223 |
Â
*/
|
3224 |
-
|
3225 |
-
|
3226 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3227 |
Â
}
|
3228 |
-
cloneOptions = _.extend( {cloneWidgets: true}, cloneOptions );
|
3229 |
Â
|
3230 |
-
var
|
3231 |
-
clone.set( 'collection', row.get('cells'), {silent: true} );
|
3232 |
-
clone.row = row;
|
3233 |
Â
|
3234 |
-
if
|
3235 |
-
|
3236 |
-
this.get('widgets').each( function ( widget ) {
|
3237 |
-
clone.get('widgets').add( widget.clone( clone, cloneOptions ), {silent: true} );
|
3238 |
-
} );
|
3239 |
Â
}
|
3240 |
Â
|
3241 |
-
|
3242 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3243 |
Â
|
3244 |
-
|
Â
|
|
Â
|
|
3245 |
Â
|
3246 |
-
|
3247 |
-
|
3248 |
-
|
3249 |
-
|
3250 |
-
|
3251 |
-
|
3252 |
-
|
3253 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3254 |
Â
} );
|
3255 |
Â
|
3256 |
-
},{}],
|
3257 |
-
|
3258 |
-
/* The builder model */
|
3259 |
-
builder: null,
|
3260 |
Â
|
3261 |
-
|
3262 |
-
style: {}
|
3263 |
-
},
|
3264 |
Â
|
3265 |
-
|
3266 |
Â
|
3267 |
-
/**
|
3268 |
-
* Initialize the row model
|
3269 |
-
*/
|
3270 |
Â
initialize: function () {
|
3271 |
-
if ( _.isEmpty(this.get('cells') ) ) {
|
3272 |
-
this.set('cells', new panels.collection.cells());
|
3273 |
-
}
|
3274 |
-
else {
|
3275 |
-
// Make sure that the cells have this row set as their parent
|
3276 |
-
this.get('cells').each( function( cell ){
|
3277 |
-
cell.row = this;
|
3278 |
-
}.bind( this ) );
|
3279 |
-
}
|
3280 |
-
this.on( 'destroy', this.onDestroy, this );
|
3281 |
-
},
|
3282 |
Â
|
Â
|
|
Â
|
|
3283 |
Â
/**
|
3284 |
-
*
|
3285 |
Â
*
|
3286 |
-
* @param
|
Â
|
|
Â
|
|
3287 |
Â
*/
|
3288 |
-
|
3289 |
-
|
3290 |
-
|
3291 |
-
|
3292 |
-
currentCells.each(function (cell, i) {
|
3293 |
-
var newCell = newCells.at(i);
|
3294 |
-
if(newCell) {
|
3295 |
-
cell.set('weight', newCell.get('weight'));
|
3296 |
-
} else {
|
3297 |
-
var newParentCell = currentCells.at( newCells.length - 1 );
|
3298 |
Â
|
3299 |
-
|
3300 |
-
|
3301 |
-
|
3302 |
-
|
3303 |
-
|
3304 |
Â
|
3305 |
-
|
3306 |
-
}
|
3307 |
-
});
|
3308 |
Â
|
3309 |
-
|
3310 |
-
|
3311 |
-
}
|
3312 |
Â
|
3313 |
-
if(
|
3314 |
-
|
3315 |
-
// TODO: make sure row and collection is set correctly when cell is created then we can just add new cells
|
3316 |
-
newCell.set({collection: currentCells});
|
3317 |
-
newCell.row = this;
|
3318 |
-
currentCells.add(newCell);
|
3319 |
-
}.bind(this));
|
3320 |
Â
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3321 |
Â
|
3322 |
-
|
3323 |
-
this.reweightCells();
|
3324 |
Â
},
|
3325 |
Â
|
3326 |
Â
/**
|
3327 |
-
*
|
Â
|
|
Â
|
|
3328 |
Â
*/
|
3329 |
-
|
3330 |
-
|
3331 |
-
var cells = this.get('cells');
|
3332 |
-
cells.each( function ( cell ) {
|
3333 |
-
totalWeight += cell.get( 'weight' );
|
3334 |
-
} );
|
3335 |
-
|
3336 |
-
cells.each( function ( cell ) {
|
3337 |
-
cell.set( 'weight', cell.get( 'weight' ) / totalWeight );
|
3338 |
-
} );
|
3339 |
-
|
3340 |
-
// This is for the row view to hook into and resize
|
3341 |
-
this.trigger( 'reweight_cells' );
|
3342 |
Â
},
|
3343 |
Â
|
3344 |
Â
/**
|
3345 |
-
*
|
3346 |
Â
*/
|
3347 |
-
|
3348 |
-
|
3349 |
-
_.invoke( this.get('cells').toArray(), 'destroy' );
|
3350 |
-
this.get('cells').reset();
|
3351 |
Â
},
|
3352 |
Â
|
3353 |
Â
/**
|
3354 |
-
*
|
3355 |
-
*
|
3356 |
-
* @param {panels.model.builder} builder The builder model to attach this to.
|
3357 |
-
*
|
3358 |
-
* @return {panels.model.row} The cloned row.
|
3359 |
Â
*/
|
3360 |
-
|
3361 |
-
if ( _.isUndefined( builder ) ) {
|
3362 |
-
builder = this.builder;
|
3363 |
-
}
|
3364 |
Â
|
3365 |
-
|
3366 |
-
|
3367 |
-
|
3368 |
Â
|
3369 |
-
|
3370 |
-
|
3371 |
-
|
Â
|
|
3372 |
Â
} );
|
3373 |
Â
|
3374 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3375 |
Â
|
3376 |
-
|
3377 |
-
|
3378 |
-
|
Â
|
|
3379 |
Â
|
3380 |
-
|
3381 |
-
|
3382 |
-
* Model for an instance of a widget
|
3383 |
-
*/
|
3384 |
-
module.exports = Backbone.Model.extend( {
|
3385 |
-
|
3386 |
-
cell: null,
|
3387 |
-
|
3388 |
-
defaults: {
|
3389 |
-
// The PHP Class of the widget
|
3390 |
-
class: null,
|
3391 |
-
|
3392 |
-
// Is this class missing? Missing widgets are a special case.
|
3393 |
-
missing: false,
|
3394 |
-
|
3395 |
-
// The values of the widget
|
3396 |
-
values: {},
|
3397 |
-
|
3398 |
-
// Have the current values been passed through the widgets update function
|
3399 |
-
raw: false,
|
3400 |
-
|
3401 |
-
// Visual style fields
|
3402 |
-
style: {},
|
3403 |
-
|
3404 |
-
read_only: false,
|
3405 |
-
widget_id: '',
|
3406 |
-
},
|
3407 |
-
|
3408 |
-
indexes: null,
|
3409 |
-
|
3410 |
-
initialize: function () {
|
3411 |
-
var widgetClass = this.get( 'class' );
|
3412 |
-
if ( _.isUndefined( panelsOptions.widgets[widgetClass] ) || ! panelsOptions.widgets[widgetClass].installed ) {
|
3413 |
-
this.set( 'missing', true );
|
3414 |
-
}
|
3415 |
-
},
|
3416 |
-
|
3417 |
-
/**
|
3418 |
-
* @param field
|
3419 |
-
* @returns {*}
|
3420 |
-
*/
|
3421 |
-
getWidgetField: function ( field ) {
|
3422 |
-
if ( _.isUndefined( panelsOptions.widgets[this.get( 'class' )] ) ) {
|
3423 |
-
if ( field === 'title' || field === 'description' ) {
|
3424 |
-
return panelsOptions.loc.missing_widget[field];
|
3425 |
-
} else {
|
3426 |
-
return '';
|
3427 |
-
}
|
3428 |
-
} else if ( this.has( 'label' ) && ! _.isEmpty( this.get( 'label' ) ) ) {
|
3429 |
-
// Use the label instead of the actual widget title
|
3430 |
-
return this.get( 'label' );
|
3431 |
-
} else {
|
3432 |
-
return panelsOptions.widgets[ this.get( 'class' ) ][ field ];
|
3433 |
-
}
|
3434 |
-
},
|
3435 |
-
|
3436 |
-
/**
|
3437 |
-
* Move this widget model to a new cell. Called by the views.
|
3438 |
-
*
|
3439 |
-
* @param panels.model.cell newCell
|
3440 |
-
* @param object options The options passed to the
|
3441 |
-
*
|
3442 |
-
* @return boolean Indicating if the widget was moved into a different cell
|
3443 |
-
*/
|
3444 |
-
moveToCell: function ( newCell, options, at ) {
|
3445 |
-
options = _.extend( {
|
3446 |
-
silent: true,
|
3447 |
-
}, options );
|
3448 |
-
|
3449 |
-
this.cell = newCell;
|
3450 |
-
this.collection.remove( this, options );
|
3451 |
-
newCell.get('widgets').add( this, _.extend( {
|
3452 |
-
at: at
|
3453 |
-
}, options ) );
|
3454 |
-
|
3455 |
-
// This should be used by views to reposition everything.
|
3456 |
-
this.trigger( 'move_to_cell', newCell, at );
|
3457 |
-
|
3458 |
-
return this;
|
3459 |
-
},
|
3460 |
-
|
3461 |
-
/**
|
3462 |
-
* This is basically a wrapper for set that checks if we need to trigger a change
|
3463 |
-
*/
|
3464 |
-
setValues: function ( values ) {
|
3465 |
-
var hasChanged = false;
|
3466 |
-
if ( JSON.stringify( values ) !== JSON.stringify( this.get( 'values' ) ) ) {
|
3467 |
-
hasChanged = true;
|
3468 |
-
}
|
3469 |
-
|
3470 |
-
this.set( 'values', values, {silent: true} );
|
3471 |
-
|
3472 |
-
if ( hasChanged ) {
|
3473 |
-
// We'll trigger our own change events.
|
3474 |
-
// NB: Must include the model being changed (i.e. `this`) as a workaround for a bug in Backbone 1.2.3
|
3475 |
-
this.trigger( 'change', this );
|
3476 |
-
this.trigger( 'change:values' );
|
3477 |
-
}
|
3478 |
-
},
|
3479 |
-
|
3480 |
-
/**
|
3481 |
-
* Create a clone of this widget attached to the given cell.
|
3482 |
-
*
|
3483 |
-
* @param {panels.model.cell} cell The cell model we're attaching this widget clone to.
|
3484 |
-
* @returns {panels.model.widget}
|
3485 |
-
*/
|
3486 |
-
clone: function ( cell, options ) {
|
3487 |
-
if ( _.isUndefined( cell ) ) {
|
3488 |
-
cell = this.cell;
|
3489 |
-
}
|
3490 |
-
|
3491 |
-
var clone = new this.constructor( this.attributes );
|
3492 |
-
|
3493 |
-
// Create a deep clone of the original values
|
3494 |
-
var cloneValues = JSON.parse( JSON.stringify( this.get( 'values' ) ) );
|
3495 |
-
|
3496 |
-
// We want to exclude any fields that start with _ from the clone. Assuming these are internal.
|
3497 |
-
var cleanClone = function ( vals ) {
|
3498 |
-
_.each( vals, function ( el, i ) {
|
3499 |
-
if ( _.isString( i ) && i[0] === '_' ) {
|
3500 |
-
delete vals[i];
|
3501 |
-
}
|
3502 |
-
else if ( _.isObject( vals[i] ) ) {
|
3503 |
-
cleanClone( vals[i] );
|
3504 |
-
}
|
3505 |
-
} );
|
3506 |
-
|
3507 |
-
return vals;
|
3508 |
-
};
|
3509 |
-
cloneValues = cleanClone( cloneValues );
|
3510 |
-
|
3511 |
-
if ( this.get( 'class' ) === "SiteOrigin_Panels_Widgets_Layout" ) {
|
3512 |
-
// Special case of this being a layout widget, it needs a new ID
|
3513 |
-
cloneValues.builder_id = Math.random().toString( 36 ).substr( 2 );
|
3514 |
-
}
|
3515 |
-
|
3516 |
-
clone.set( 'widget_id', '' );
|
3517 |
-
clone.set( 'values', cloneValues, {silent: true} );
|
3518 |
-
clone.set( 'collection', cell.get('widgets'), {silent: true} );
|
3519 |
-
clone.cell = cell;
|
3520 |
-
|
3521 |
-
// This is used to force a form reload later on
|
3522 |
-
clone.isDuplicate = true;
|
3523 |
-
|
3524 |
-
return clone;
|
3525 |
-
},
|
3526 |
-
|
3527 |
-
/**
|
3528 |
-
* Gets the value that makes most sense as the title.
|
3529 |
-
*/
|
3530 |
-
getTitle: function () {
|
3531 |
-
var widgetData = panelsOptions.widgets[this.get( 'class' )];
|
3532 |
-
|
3533 |
-
if ( _.isUndefined( widgetData ) ) {
|
3534 |
-
return this.get( 'class' ).replace( /_/g, ' ' );
|
3535 |
-
}
|
3536 |
-
else if ( ! _.isUndefined( widgetData.panels_title ) ) {
|
3537 |
-
// This means that the widget has told us which field it wants us to use as a title
|
3538 |
-
if ( widgetData.panels_title === false ) {
|
3539 |
-
return panelsOptions.widgets[this.get( 'class' )].description;
|
3540 |
-
}
|
3541 |
-
}
|
3542 |
-
|
3543 |
-
var values = this.get( 'values' );
|
3544 |
-
|
3545 |
-
// Create a list of fields to check for a title
|
3546 |
-
var titleFields = ['title', 'text'];
|
3547 |
-
|
3548 |
-
for ( var k in values ) {
|
3549 |
-
if(k.charAt(0) === '_' || k === 'so_sidebar_emulator_id' || k === 'option_name'){
|
3550 |
-
// Skip Widgets Bundle supporting fields
|
3551 |
-
continue;
|
3552 |
-
}
|
3553 |
-
if ( values.hasOwnProperty( k ) ) {
|
3554 |
-
titleFields.push( k );
|
3555 |
-
}
|
3556 |
-
}
|
3557 |
-
|
3558 |
-
titleFields = _.uniq( titleFields );
|
3559 |
-
|
3560 |
-
for ( var i in titleFields ) {
|
3561 |
-
if (
|
3562 |
-
! _.isUndefined( values[titleFields[i]] ) &&
|
3563 |
-
_.isString( values[titleFields[i]] ) &&
|
3564 |
-
values[titleFields[i]] !== '' &&
|
3565 |
-
values[titleFields[i]] !== 'on' &&
|
3566 |
-
titleFields[i][0] !== '_' && ! jQuery.isNumeric( values[titleFields[i]] )
|
3567 |
-
) {
|
3568 |
-
var title = values[titleFields[i]];
|
3569 |
-
title = title.replace( /<\/?[^>]+(>|$)/g, "" );
|
3570 |
-
var parts = title.split( " " );
|
3571 |
-
parts = parts.slice( 0, 20 );
|
3572 |
-
return parts.join( ' ' );
|
3573 |
-
}
|
3574 |
-
}
|
3575 |
-
|
3576 |
-
// If we still have nothing, then just return the widget description
|
3577 |
-
return this.getWidgetField( 'description' );
|
3578 |
-
}
|
3579 |
-
|
3580 |
-
} );
|
3581 |
Â
|
3582 |
-
|
3583 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3584 |
Â
|
3585 |
-
|
3586 |
-
|
3587 |
-
sectionTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-context-menu-section' ).html() ) ),
|
3588 |
Â
|
3589 |
-
|
3590 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3591 |
Â
|
3592 |
-
|
3593 |
-
|
3594 |
-
|
Â
|
|
Â
|
|
Â
|
|
3595 |
Â
|
3596 |
-
|
3597 |
-
* Intialize the context menu
|
3598 |
-
*/
|
3599 |
-
initialize: function () {
|
3600 |
-
this.listenContextMenu();
|
3601 |
-
this.render();
|
3602 |
-
this.attach();
|
3603 |
-
},
|
3604 |
Â
|
3605 |
-
|
3606 |
-
* Listen for the right click context menu
|
3607 |
-
*/
|
3608 |
-
listenContextMenu: function () {
|
3609 |
-
var thisView = this;
|
3610 |
Â
|
3611 |
-
|
3612 |
-
|
3613 |
-
thisView.closeMenu();
|
3614 |
-
thisView.active = false;
|
3615 |
Â
e.preventDefault();
|
3616 |
-
|
3617 |
-
|
Â
|
|
Â
|
|
Â
|
|
3618 |
Â
|
3619 |
-
|
3620 |
-
|
3621 |
-
|
3622 |
-
}
|
3623 |
Â
|
3624 |
-
|
3625 |
-
|
3626 |
-
|
3627 |
Â
|
3628 |
-
|
3629 |
-
|
3630 |
-
|
3631 |
Â
|
3632 |
-
|
3633 |
-
|
3634 |
-
|
3635 |
-
|
3636 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3637 |
Â
} );
|
3638 |
-
}
|
3639 |
Â
|
3640 |
-
|
3641 |
-
this.setElement( this.wrapperTemplate() );
|
3642 |
-
},
|
3643 |
Â
|
3644 |
-
|
3645 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3646 |
Â
},
|
3647 |
Â
|
3648 |
Â
/**
|
3649 |
-
*
|
3650 |
-
*
|
3651 |
-
* @param position
|
3652 |
Â
*/
|
3653 |
-
|
3654 |
-
this.
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3655 |
Â
|
3656 |
-
|
3657 |
-
|
3658 |
-
|
Â
|
|
Â
|
|
3659 |
Â
|
3660 |
-
|
3661 |
-
this.$el.css( 'max-height', $( window ).height() - 20 );
|
3662 |
Â
|
3663 |
-
//
|
3664 |
-
if
|
3665 |
-
|
Â
|
|
3666 |
Â
}
|
3667 |
-
if
|
3668 |
-
|
Â
|
|
3669 |
Â
}
|
3670 |
-
|
3671 |
-
|
3672 |
-
|
3673 |
-
position.top = $( window ).height() + $( window ).scrollTop() - this.$el.outerHeight() - 10;
|
3674 |
Â
}
|
3675 |
-
if
|
3676 |
-
|
Â
|
|
Â
|
|
Â
|
|
3677 |
Â
}
|
3678 |
Â
|
3679 |
-
|
3680 |
-
|
3681 |
-
|
3682 |
-
top: position.top + 1
|
3683 |
-
} ).show();
|
3684 |
-
this.$( '.so-search-wrapper input' ).focus();
|
3685 |
-
},
|
3686 |
Â
|
3687 |
-
|
3688 |
-
|
Â
|
|
3689 |
Â
|
3690 |
-
|
3691 |
-
|
3692 |
-
$( window ).off( 'click', this.clickOutsideListen );
|
3693 |
Â
|
3694 |
-
|
3695 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3696 |
Â
},
|
3697 |
Â
|
3698 |
Â
/**
|
3699 |
-
*
|
3700 |
Â
*/
|
3701 |
-
|
3702 |
-
|
Â
|
|
3703 |
Â
|
3704 |
-
|
3705 |
-
|
3706 |
-
|
3707 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3708 |
Â
}
|
Â
|
|
3709 |
Â
},
|
3710 |
Â
|
3711 |
Â
/**
|
3712 |
-
*
|
3713 |
-
* @param e
|
3714 |
Â
*/
|
3715 |
-
|
3716 |
-
|
3717 |
-
if (
|
3718 |
-
|
3719 |
Â
}
|
Â
|
|
Â
|
|
Â
|
|
3720 |
Â
},
|
3721 |
Â
|
3722 |
Â
/**
|
3723 |
-
*
|
3724 |
Â
*
|
3725 |
-
* @
|
3726 |
-
* @param items
|
3727 |
-
* @param callback
|
3728 |
Â
*/
|
3729 |
-
|
3730 |
-
|
3731 |
-
|
3732 |
-
display: 5,
|
3733 |
-
defaultDisplay: false,
|
3734 |
-
search: true,
|
3735 |
-
|
3736 |
-
// All the labels
|
3737 |
-
sectionTitle: '',
|
3738 |
-
searchPlaceholder: '',
|
3739 |
-
|
3740 |
-
// This is the key to be used in items for the title. Makes it easier to list objects
|
3741 |
-
titleKey: 'title'
|
3742 |
-
}, settings );
|
3743 |
Â
|
3744 |
-
// Create the new
|
3745 |
-
var
|
3746 |
-
settings: settings,
|
3747 |
-
items: items
|
3748 |
-
} ) ).attr( 'id', 'panels-menu-section-' + id );
|
3749 |
-
this.$el.append( section );
|
3750 |
Â
|
3751 |
-
|
3752 |
-
|
3753 |
-
|
3754 |
-
thisView.closeMenu();
|
3755 |
Â
} );
|
3756 |
Â
|
3757 |
-
|
3758 |
-
|
Â
|
|
3759 |
Â
|
3760 |
-
|
3761 |
-
|
3762 |
-
|
3763 |
-
|
3764 |
-
|
Â
|
|
3765 |
Â
|
3766 |
-
|
3767 |
-
|
3768 |
-
|
3769 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3770 |
Â
|
3771 |
-
|
3772 |
-
|
3773 |
-
|
3774 |
-
|
3775 |
-
} );
|
3776 |
Â
|
3777 |
-
|
Â
|
|
Â
|
|
3778 |
Â
|
3779 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3780 |
Â
},
|
3781 |
Â
|
3782 |
Â
/**
|
3783 |
-
*
|
3784 |
-
*
|
3785 |
-
* @param id
|
3786 |
-
* @returns {boolean}
|
3787 |
Â
*/
|
3788 |
-
|
3789 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3790 |
Â
},
|
3791 |
Â
|
3792 |
Â
/**
|
3793 |
-
*
|
3794 |
Â
*
|
3795 |
Â
* @param e
|
3796 |
-
* @
|
3797 |
Â
*/
|
3798 |
-
|
3799 |
-
|
3800 |
-
|
3801 |
-
|
3802 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3803 |
Â
|
3804 |
-
|
3805 |
-
|
3806 |
-
|
3807 |
-
|
3808 |
-
|
3809 |
Â
|
3810 |
-
|
3811 |
-
items.removeClass( 'so-active' );
|
3812 |
Â
|
3813 |
-
|
Â
|
|
Â
|
|
Â
|
|
3814 |
Â
|
3815 |
-
|
3816 |
-
if ( activeIndex - 1 < 0 ) {
|
3817 |
-
activeItem = items.last();
|
3818 |
-
} else {
|
3819 |
-
activeItem = items.eq( activeIndex - 1 );
|
3820 |
-
}
|
3821 |
-
}
|
3822 |
-
else if ( e.which === 40 ) {
|
3823 |
-
if ( activeIndex + 1 >= items.length ) {
|
3824 |
-
activeItem = items.first();
|
3825 |
-
} else {
|
3826 |
-
activeItem = items.eq( activeIndex + 1 );
|
3827 |
-
}
|
3828 |
-
}
|
3829 |
-
}
|
3830 |
-
else if ( e.which === 38 ) {
|
3831 |
-
activeItem = items.last();
|
3832 |
-
}
|
3833 |
-
else if ( e.which === 40 ) {
|
3834 |
-
activeItem = items.first();
|
3835 |
-
}
|
3836 |
Â
|
3837 |
-
|
3838 |
-
|
3839 |
-
}
|
3840 |
-
if ( e.which === 13 ) {
|
3841 |
-
if ( section.find( 'ul li:visible' ).length === 1 ) {
|
3842 |
-
// We'll treat a single visible item as active when enter is clicked
|
3843 |
-
section.find( 'ul li:visible' ).trigger( 'click' );
|
3844 |
-
return false;
|
3845 |
-
}
|
3846 |
-
section.find( 'ul li.so-active:visible' ).trigger( 'click' );
|
3847 |
-
return false;
|
3848 |
Â
}
|
3849 |
Â
|
3850 |
-
|
3851 |
-
|
3852 |
-
|
3853 |
-
section.find( '.so-item' ).hide();
|
3854 |
-
for ( var i = 0; i < settings.defaultDisplay.length; i ++ ) {
|
3855 |
-
section.find( '.so-item[data-key="' + settings.defaultDisplay[i] + '"]' ).show();
|
3856 |
-
}
|
3857 |
-
} else {
|
3858 |
-
// We'll just display all the items
|
3859 |
-
section.find( '.so-item' ).show();
|
3860 |
-
}
|
3861 |
-
} else {
|
3862 |
-
section.find( '.so-item' ).hide().each( function () {
|
3863 |
-
var item = $( this );
|
3864 |
-
if ( item.html().toLowerCase().indexOf( $$.val().toLowerCase() ) !== - 1 ) {
|
3865 |
-
item.show();
|
3866 |
-
}
|
3867 |
-
} );
|
3868 |
Â
}
|
3869 |
Â
|
3870 |
-
|
3871 |
-
|
3872 |
-
|
3873 |
-
) + ')' ).hide();
|
3874 |
Â
|
Â
|
|
Â
|
|
Â
|
|
3875 |
Â
|
3876 |
-
if
|
3877 |
-
|
3878 |
-
|
3879 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3880 |
Â
}
|
Â
|
|
Â
|
|
Â
|
|
3881 |
Â
},
|
3882 |
Â
|
3883 |
Â
/**
|
3884 |
-
*
|
3885 |
-
* @param
|
3886 |
-
* @param event
|
3887 |
Â
*/
|
3888 |
-
|
3889 |
-
|
3890 |
-
|
3891 |
-
|
3892 |
-
];
|
3893 |
-
|
3894 |
-
// Return if this event is over the given element
|
3895 |
-
return (
|
3896 |
-
event.pageX >= elPos[0][0] && event.pageX <= elPos[1][0] &&
|
3897 |
-
event.pageY >= elPos[0][1] && event.pageY <= elPos[1][1]
|
3898 |
-
);
|
3899 |
Â
}
|
3900 |
Â
|
3901 |
Â
} );
|
3902 |
Â
|
3903 |
-
},{}],23:[function(require,module,exports){
|
3904 |
-
var panels = window.panels, $ = jQuery;
|
3905 |
-
|
3906 |
-
module.exports = Backbone.View.extend( {
|
3907 |
-
|
3908 |
-
// Config options
|
3909 |
-
config: {},
|
3910 |
-
|
3911 |
-
template: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-builder' ).html() ) ),
|
3912 |
-
dialogs: {},
|
3913 |
-
rowsSortable: null,
|
3914 |
-
dataField: false,
|
3915 |
-
currentData: '',
|
3916 |
-
|
3917 |
-
attachedToEditor: false,
|
3918 |
-
attachedVisible: false,
|
3919 |
-
liveEditor: undefined,
|
3920 |
-
menu: false,
|
3921 |
-
|
3922 |
-
activeCell: null,
|
3923 |
-
|
3924 |
-
events: {
|
3925 |
-
'click .so-tool-button.so-widget-add': 'displayAddWidgetDialog',
|
3926 |
-
'click .so-tool-button.so-row-add': 'displayAddRowDialog',
|
3927 |
-
'click .so-tool-button.so-prebuilt-add': 'displayAddPrebuiltDialog',
|
3928 |
-
'click .so-tool-button.so-history': 'displayHistoryDialog',
|
3929 |
-
'click .so-tool-button.so-live-editor': 'displayLiveEditor'
|
3930 |
-
},
|
3931 |
-
|
3932 |
-
/* A row collection */
|
3933 |
-
rows: null,
|
3934 |
-
|
3935 |
-
/**
|
3936 |
-
* Initialize the builder
|
3937 |
-
*/
|
3938 |
-
initialize: function ( options ) {
|
3939 |
-
var builder = this;
|
3940 |
-
|
3941 |
-
this.config = _.extend( {
|
3942 |
-
loadLiveEditor: false,
|
3943 |
-
builderSupports: {}
|
3944 |
-
}, options.config );
|
3945 |
-
|
3946 |
-
// These are the actions that a user can perform in the builder
|
3947 |
-
this.config.builderSupports = _.extend( {
|
3948 |
-
addRow: true,
|
3949 |
-
editRow: true,
|
3950 |
-
deleteRow: true,
|
3951 |
-
moveRow: true,
|
3952 |
-
addWidget: true,
|
3953 |
-
editWidget: true,
|
3954 |
-
deleteWidget: true,
|
3955 |
-
moveWidget: true,
|
3956 |
-
prebuilt: true,
|
3957 |
-
history: true,
|
3958 |
-
liveEditor: true,
|
3959 |
-
revertToEditor: true
|
3960 |
-
}, this.config.builderSupports );
|
3961 |
-
|
3962 |
-
// Automatically load the live editor as soon as it's ready
|
3963 |
-
if ( options.config.loadLiveEditor ) {
|
3964 |
-
this.on( 'builder_live_editor_added', function () {
|
3965 |
-
this.displayLiveEditor();
|
3966 |
-
} );
|
3967 |
-
}
|
3968 |
-
|
3969 |
-
// Now lets create all the dialog boxes that the main builder interface uses
|
3970 |
-
this.dialogs = {
|
3971 |
-
widgets: new panels.dialog.widgets(),
|
3972 |
-
row: new panels.dialog.row(),
|
3973 |
-
prebuilt: new panels.dialog.prebuilt()
|
3974 |
-
};
|
3975 |
-
|
3976 |
-
// Set the builder for each dialog and render it.
|
3977 |
-
_.each( this.dialogs, function ( p, i, d ) {
|
3978 |
-
d[ i ].setBuilder( builder );
|
3979 |
-
} );
|
3980 |
-
|
3981 |
-
this.dialogs.row.setRowDialogType( 'create' );
|
3982 |
-
|
3983 |
-
// This handles a new row being added to the collection - we'll display it in the interface
|
3984 |
-
this.listenTo( this.model.get( 'rows' ), 'add', this.onAddRow );
|
3985 |
-
|
3986 |
-
// Reflow the entire builder when ever the
|
3987 |
-
$( window ).resize( function ( e ) {
|
3988 |
-
if ( e.target === window ) {
|
3989 |
-
builder.trigger( 'builder_resize' );
|
3990 |
-
}
|
3991 |
-
} );
|
3992 |
-
|
3993 |
-
// When the data changes in the model, store it in the field
|
3994 |
-
this.listenTo( this.model, 'change:data load_panels_data', this.storeModelData );
|
3995 |
-
this.listenTo( this.model, 'change:data load_panels_data', this.toggleWelcomeDisplay );
|
3996 |
-
|
3997 |
-
// Handle a content change
|
3998 |
-
this.on( 'content_change', this.handleContentChange, this );
|
3999 |
-
this.on( 'display_builder', this.handleDisplayBuilder, this );
|
4000 |
-
this.on( 'hide_builder', this.handleHideBuilder, this );
|
4001 |
-
this.on( 'builder_rendered builder_resize', this.handleBuilderSizing, this );
|
4002 |
-
|
4003 |
-
this.on( 'display_builder', this.wrapEditorExpandAdjust, this );
|
4004 |
-
|
4005 |
-
// Create the context menu for this builder
|
4006 |
-
this.menu = new panels.utils.menu( {} );
|
4007 |
-
this.listenTo( this.menu, 'activate_context', this.activateContextMenu )
|
4008 |
-
|
4009 |
-
if ( this.config.loadOnAttach ) {
|
4010 |
-
this.on( 'builder_attached_to_editor', function () {
|
4011 |
-
this.displayAttachedBuilder( { confirm: false } );
|
4012 |
-
}, this );
|
4013 |
-
}
|
4014 |
-
|
4015 |
-
return this;
|
4016 |
-
},
|
4017 |
-
|
4018 |
-
/**
|
4019 |
-
* Render the builder interface.
|
4020 |
-
*
|
4021 |
-
* @return {panels.view.builder}
|
4022 |
-
*/
|
4023 |
-
render: function () {
|
4024 |
-
// this.$el.html( this.template() );
|
4025 |
-
this.setElement( this.template() );
|
4026 |
-
this.$el
|
4027 |
-
.attr( 'id', 'siteorigin-panels-builder-' + this.cid )
|
4028 |
-
.addClass( 'so-builder-container' );
|
4029 |
-
|
4030 |
-
this.trigger( 'builder_rendered' );
|
4031 |
-
|
4032 |
-
return this;
|
4033 |
-
},
|
4034 |
-
|
4035 |
-
/**
|
4036 |
-
* Attach the builder to the given container
|
4037 |
-
*
|
4038 |
-
* @param container
|
4039 |
-
* @returns {panels.view.builder}
|
4040 |
-
*/
|
4041 |
-
attach: function ( options ) {
|
4042 |
-
|
4043 |
-
options = _.extend( {
|
4044 |
-
container: false,
|
4045 |
-
dialog: false
|
4046 |
-
}, options );
|
4047 |
-
|
4048 |
-
if ( options.dialog ) {
|
4049 |
-
// We're going to add this to a dialog
|
4050 |
-
this.dialog = new panels.dialog.builder();
|
4051 |
-
this.dialog.builder = this;
|
4052 |
-
} else {
|
4053 |
-
// Attach this in the standard way
|
4054 |
-
this.$el.appendTo( options.container );
|
4055 |
-
this.metabox = options.container.closest( '.postbox' );
|
4056 |
-
this.initSortable();
|
4057 |
-
this.trigger( 'attached_to_container', options.container );
|
4058 |
-
}
|
4059 |
-
|
4060 |
-
this.trigger( 'builder_attached' );
|
4061 |
-
|
4062 |
-
// Add support for components we have
|
4063 |
-
|
4064 |
-
if ( this.supports( 'liveEditor' ) ) {
|
4065 |
-
this.addLiveEditor();
|
4066 |
-
}
|
4067 |
-
if ( this.supports( 'history' ) ) {
|
4068 |
-
this.addHistoryBrowser();
|
4069 |
-
}
|
4070 |
-
|
4071 |
-
// Hide toolbar buttons we don't support
|
4072 |
-
var toolbar = this.$( '.so-builder-toolbar' );
|
4073 |
-
var welcomeMessageContainer = this.$( '.so-panels-welcome-message' );
|
4074 |
-
var welcomeMessage = panelsOptions.loc.welcomeMessage;
|
4075 |
-
|
4076 |
-
var supportedItems = [];
|
4077 |
-
|
4078 |
-
if ( !this.supports( 'addWidget' ) ) {
|
4079 |
-
toolbar.find( '.so-widget-add' ).hide();
|
4080 |
-
} else {
|
4081 |
-
supportedItems.push( welcomeMessage.addWidgetButton );
|
4082 |
-
}
|
4083 |
-
if ( !this.supports( 'addRow' ) ) {
|
4084 |
-
toolbar.find( '.so-row-add' ).hide();
|
4085 |
-
} else {
|
4086 |
-
supportedItems.push( welcomeMessage.addRowButton );
|
4087 |
-
}
|
4088 |
-
if ( !this.supports( 'prebuilt' ) ) {
|
4089 |
-
toolbar.find( '.so-prebuilt-add' ).hide();
|
4090 |
-
} else {
|
4091 |
-
supportedItems.push( welcomeMessage.addPrebuiltButton );
|
4092 |
-
}
|
4093 |
-
|
4094 |
-
var msg = '';
|
4095 |
-
if ( supportedItems.length === 3 ) {
|
4096 |
-
msg = welcomeMessage.threeEnabled;
|
4097 |
-
} else if ( supportedItems.length === 2 ) {
|
4098 |
-
msg = welcomeMessage.twoEnabled;
|
4099 |
-
} else if ( supportedItems.length === 1 ) {
|
4100 |
-
msg = welcomeMessage.oneEnabled;
|
4101 |
-
} else if ( supportedItems.length === 0 ) {
|
4102 |
-
msg = welcomeMessage.addingDisabled;
|
4103 |
-
}
|
4104 |
-
|
4105 |
-
var resTemplate = _.template( panels.helpers.utils.processTemplate( msg ) );
|
4106 |
-
var msgHTML = resTemplate( { items: supportedItems } ) + ' ' + welcomeMessage.docsMessage;
|
4107 |
-
welcomeMessageContainer.find( '.so-message-wrapper' ).html( msgHTML );
|
4108 |
-
|
4109 |
-
return this;
|
4110 |
-
},
|
4111 |
-
|
4112 |
-
/**
|
4113 |
-
* This will move the Page Builder meta box into the editor if we're in the post/page edit interface.
|
4114 |
-
*
|
4115 |
-
* @returns {panels.view.builder}
|
4116 |
-
*/
|
4117 |
-
attachToEditor: function () {
|
4118 |
-
if ( this.config.editorType !== 'tinyMCE' ) {
|
4119 |
-
return this;
|
4120 |
-
}
|
4121 |
-
|
4122 |
-
this.attachedToEditor = true;
|
4123 |
-
var metabox = this.metabox;
|
4124 |
-
var thisView = this;
|
4125 |
-
|
4126 |
-
// Handle switching between the page builder and other tabs
|
4127 |
-
$( '#wp-content-wrap .wp-editor-tabs' )
|
4128 |
-
.find( '.wp-switch-editor' )
|
4129 |
-
.click( function ( e ) {
|
4130 |
-
e.preventDefault();
|
4131 |
-
$( '#wp-content-editor-container' ).show();
|
4132 |
-
|
4133 |
-
// metabox.hide();
|
4134 |
-
$( '#wp-content-wrap' ).removeClass( 'panels-active' );
|
4135 |
-
$( '#content-resize-handle' ).show();
|
4136 |
-
|
4137 |
-
// Make sure the word count is visible
|
4138 |
-
thisView.trigger( 'hide_builder' );
|
4139 |
-
} ).end()
|
4140 |
-
.append(
|
4141 |
-
$( '<button type="button" id="content-panels" class="hide-if-no-js wp-switch-editor switch-panels">' + metabox.find( '.hndle span' ).html() + '</button>' )
|
4142 |
-
.click( function ( e ) {
|
4143 |
-
if ( thisView.displayAttachedBuilder( { confirm: true } ) ) {
|
4144 |
-
e.preventDefault();
|
4145 |
-
}
|
4146 |
-
} )
|
4147 |
-
);
|
4148 |
-
|
4149 |
-
// Switch back to the standard editor
|
4150 |
-
if ( this.supports( 'revertToEditor' ) ) {
|
4151 |
-
metabox.find( '.so-switch-to-standard' ).click( function ( e ) {
|
4152 |
-
e.preventDefault();
|
4153 |
-
|
4154 |
-
if ( !confirm( panelsOptions.loc.confirm_stop_builder ) ) {
|
4155 |
-
return;
|
4156 |
-
}
|
4157 |
-
|
4158 |
-
// User is switching to the standard visual editor
|
4159 |
-
thisView.addHistoryEntry( 'back_to_editor' );
|
4160 |
-
thisView.model.loadPanelsData( false );
|
4161 |
-
|
4162 |
-
// Switch back to the standard editor
|
4163 |
-
$( '#wp-content-wrap' ).show();
|
4164 |
-
metabox.hide();
|
4165 |
-
|
4166 |
-
// Resize to trigger reflow of WordPress editor stuff
|
4167 |
-
$( window ).resize();
|
4168 |
-
|
4169 |
-
thisView.attachedVisible = false;
|
4170 |
-
thisView.trigger( 'hide_builder' );
|
4171 |
-
} ).show();
|
4172 |
-
}
|
4173 |
-
|
4174 |
-
// Move the panels box into a tab of the content editor
|
4175 |
-
metabox.insertAfter( '#wp-content-wrap' ).hide().addClass( 'attached-to-editor' );
|
4176 |
-
|
4177 |
-
// Switch to the Page Builder interface as soon as we load the page if there are widgets or the normal editor
|
4178 |
-
// isn't supported.
|
4179 |
-
var data = this.model.get( 'data' );
|
4180 |
-
if ( !_.isEmpty( data.widgets ) || !_.isEmpty( data.grids ) || !this.supports( 'revertToEditor' ) ) {
|
4181 |
-
this.displayAttachedBuilder( { confirm: false } );
|
4182 |
-
}
|
4183 |
-
|
4184 |
-
// We will also make this sticky if its attached to an editor.
|
4185 |
-
var stickToolbar = function () {
|
4186 |
-
var toolbar = thisView.$( '.so-builder-toolbar' );
|
4187 |
-
|
4188 |
-
if ( thisView.$el.hasClass( 'so-display-narrow' ) ) {
|
4189 |
-
// In this case, we don't want to stick the toolbar.
|
4190 |
-
toolbar.css( {
|
4191 |
-
top: 0,
|
4192 |
-
left: 0,
|
4193 |
-
width: '100%',
|
4194 |
-
position: 'absolute'
|
4195 |
-
} );
|
4196 |
-
thisView.$el.css( 'padding-top', toolbar.outerHeight() );
|
4197 |
-
return;
|
4198 |
-
}
|
4199 |
-
|
4200 |
-
var newTop = $( window ).scrollTop() - thisView.$el.offset().top;
|
4201 |
-
|
4202 |
-
if ( $( '#wpadminbar' ).css( 'position' ) === 'fixed' ) {
|
4203 |
-
newTop += $( '#wpadminbar' ).outerHeight();
|
4204 |
-
}
|
4205 |
-
|
4206 |
-
var limits = {
|
4207 |
-
top: 0,
|
4208 |
-
bottom: thisView.$el.outerHeight() - toolbar.outerHeight() + 20
|
4209 |
-
};
|
4210 |
-
|
4211 |
-
if ( newTop > limits.top && newTop < limits.bottom ) {
|
4212 |
-
if ( toolbar.css( 'position' ) !== 'fixed' ) {
|
4213 |
-
// The toolbar needs to stick to the top, over the interface
|
4214 |
-
toolbar.css( {
|
4215 |
-
top: $( '#wpadminbar' ).outerHeight(),
|
4216 |
-
left: thisView.$el.offset().left,
|
4217 |
-
width: thisView.$el.outerWidth(),
|
4218 |
-
position: 'fixed'
|
4219 |
-
} );
|
4220 |
-
}
|
4221 |
-
} else {
|
4222 |
-
// The toolbar needs to be at the top or bottom of the interface
|
4223 |
-
toolbar.css( {
|
4224 |
-
top: Math.min( Math.max( newTop, 0 ), thisView.$el.outerHeight() - toolbar.outerHeight() + 20 ),
|
4225 |
-
left: 0,
|
4226 |
-
width: '100%',
|
4227 |
-
position: 'absolute'
|
4228 |
-
} );
|
4229 |
-
}
|
4230 |
-
|
4231 |
-
thisView.$el.css( 'padding-top', toolbar.outerHeight() );
|
4232 |
-
};
|
4233 |
-
|
4234 |
-
this.on( 'builder_resize', stickToolbar, this );
|
4235 |
-
$( document ).scroll( stickToolbar );
|
4236 |
-
stickToolbar();
|
4237 |
-
|
4238 |
-
this.trigger( 'builder_attached_to_editor' );
|
4239 |
-
|
4240 |
-
return this;
|
4241 |
-
},
|
4242 |
-
|
4243 |
-
/**
|
4244 |
-
* Display the builder interface when attached to a WordPress editor
|
4245 |
-
*/
|
4246 |
-
displayAttachedBuilder: function ( options ) {
|
4247 |
-
options = _.extend( {
|
4248 |
-
confirm: true
|
4249 |
-
}, options );
|
4250 |
-
|
4251 |
-
// Switch to the Page Builder interface
|
4252 |
-
|
4253 |
-
if ( options.confirm ) {
|
4254 |
-
var editor = typeof tinyMCE !== 'undefined' ? tinyMCE.get( 'content' ) : false;
|
4255 |
-
var editorContent = ( editor && _.isFunction( editor.getContent ) ) ? editor.getContent() : $( 'textarea#content' ).val();
|
4256 |
-
|
4257 |
-
if ( editorContent !== '' && !confirm( panelsOptions.loc.confirm_use_builder ) ) {
|
4258 |
-
return false;
|
4259 |
-
}
|
4260 |
-
}
|
4261 |
-
|
4262 |
-
// Hide the standard content editor
|
4263 |
-
$( '#wp-content-wrap' ).hide();
|
4264 |
-
|
4265 |
-
|
4266 |
-
$( '#editor-expand-toggle' ).on( 'change.editor-expand', function () {
|
4267 |
-
if ( !$( this ).prop( 'checked' ) ) {
|
4268 |
-
$( '#wp-content-wrap' ).hide();
|
4269 |
-
}
|
4270 |
-
} );
|
4271 |
-
|
4272 |
-
// Show page builder and the inside div
|
4273 |
-
this.metabox.show().find( '> .inside' ).show();
|
4274 |
-
|
4275 |
-
// Triggers full refresh
|
4276 |
-
$( window ).resize();
|
4277 |
-
$( document ).scroll();
|
4278 |
-
|
4279 |
-
// Make sure the word count is visible
|
4280 |
-
this.attachedVisible = true;
|
4281 |
-
this.trigger( 'display_builder' );
|
4282 |
-
|
4283 |
-
return true;
|
4284 |
-
},
|
4285 |
-
|
4286 |
-
/**
|
4287 |
-
* Initialize the row sortables
|
4288 |
-
*/
|
4289 |
-
initSortable: function () {
|
4290 |
-
if ( !this.supports( 'moveRow' ) ) {
|
4291 |
-
return this;
|
4292 |
-
}
|
4293 |
-
|
4294 |
-
var builderView = this;
|
4295 |
-
var builderID = builderView.$el.attr( 'id' );
|
4296 |
-
|
4297 |
-
// Create the sortable for the rows
|
4298 |
-
this.rowsSortable = this.$( '.so-rows-container' ).sortable( {
|
4299 |
-
appendTo: '#wpwrap',
|
4300 |
-
items: '.so-row-container',
|
4301 |
-
handle: '.so-row-move',
|
4302 |
-
// For the block editor, where it's possible to have multiple Page Builder blocks on a page.
|
4303 |
-
// Also specify builderID when not in the block editor to prevent being able to drop rows from builder in a dialog
|
4304 |
-
// into builder on the page under the dialog.
|
4305 |
-
connectWith: '#' + builderID + '.so-rows-container,.block-editor .so-rows-container',
|
4306 |
-
axis: 'y',
|
4307 |
-
tolerance: 'pointer',
|
4308 |
-
scroll: false,
|
4309 |
-
remove: function ( e, ui ) {
|
4310 |
-
builderView.model.get( 'rows' ).remove(
|
4311 |
-
$( ui.item ).data( 'view' ).model,
|
4312 |
-
{ silent: true }
|
4313 |
-
);
|
4314 |
-
builderView.model.refreshPanelsData();
|
4315 |
-
},
|
4316 |
-
receive: function ( e, ui ) {
|
4317 |
-
builderView.model.get( 'rows' ).add(
|
4318 |
-
$( ui.item ).data( 'view' ).model,
|
4319 |
-
{ silent: true, at: $( ui.item ).index() }
|
4320 |
-
);
|
4321 |
-
builderView.model.refreshPanelsData();
|
4322 |
-
},
|
4323 |
-
stop: function ( e, ui ) {
|
4324 |
-
var $$ = $( ui.item ),
|
4325 |
-
row = $$.data( 'view' ),
|
4326 |
-
rows = builderView.model.get( 'rows' );
|
4327 |
-
|
4328 |
-
// If this hasn't already been removed and added to a different builder.
|
4329 |
-
if ( rows.get( row.model ) ) {
|
4330 |
-
builderView.addHistoryEntry( 'row_moved' );
|
4331 |
-
|
4332 |
-
rows.remove( row.model, {
|
4333 |
-
'silent': true
|
4334 |
-
} );
|
4335 |
-
rows.add( row.model, {
|
4336 |
-
'silent': true,
|
4337 |
-
'at': $$.index()
|
4338 |
-
} );
|
4339 |
-
|
4340 |
-
row.trigger( 'move', $$.index() );
|
4341 |
-
|
4342 |
-
builderView.model.refreshPanelsData();
|
4343 |
-
}
|
4344 |
-
}
|
4345 |
-
} );
|
4346 |
-
|
4347 |
-
return this;
|
4348 |
-
},
|
4349 |
-
|
4350 |
-
/**
|
4351 |
-
* Refresh the row sortable
|
4352 |
-
*/
|
4353 |
-
refreshSortable: function () {
|
4354 |
-
// Refresh the sortable to account for the new row
|
4355 |
-
if ( !_.isNull( this.rowsSortable ) ) {
|
4356 |
-
this.rowsSortable.sortable( 'refresh' );
|
4357 |
-
}
|
4358 |
-
},
|
4359 |
-
|
4360 |
-
/**
|
4361 |
-
* Set the field that's used to store the data
|
4362 |
-
* @param field
|
4363 |
-
* @param options
|
4364 |
-
*/
|
4365 |
-
setDataField: function ( field, options ) {
|
4366 |
-
options = _.extend( {
|
4367 |
-
load: true
|
4368 |
-
}, options );
|
4369 |
-
|
4370 |
-
this.dataField = field;
|
4371 |
-
this.dataField.data( 'builder', this );
|
4372 |
-
|
4373 |
-
if ( options.load && field.val() !== '' ) {
|
4374 |
-
var data = this.dataField.val();
|
4375 |
-
try {
|
4376 |
-
data = JSON.parse( data );
|
4377 |
-
}
|
4378 |
-
catch ( err ) {
|
4379 |
-
console.log( "Failed to parse Page Builder layout data from supplied data field." );
|
4380 |
-
data = {};
|
4381 |
-
}
|
4382 |
-
|
4383 |
-
this.setData( data );
|
4384 |
-
}
|
4385 |
-
|
4386 |
-
return this;
|
4387 |
-
},
|
4388 |
-
|
4389 |
-
/**
|
4390 |
-
* Set the current panels data to be used.
|
4391 |
-
*
|
4392 |
-
* @param data
|
4393 |
-
*/
|
4394 |
-
setData: function( data ) {
|
4395 |
-
this.model.loadPanelsData( data );
|
4396 |
-
this.currentData = data;
|
4397 |
-
this.toggleWelcomeDisplay();
|
4398 |
-
},
|
4399 |
-
|
4400 |
-
/**
|
4401 |
-
* Get the current panels data.
|
4402 |
-
*
|
4403 |
-
*/
|
4404 |
-
getData: function() {
|
4405 |
-
return this.model.get( 'data' );
|
4406 |
-
},
|
4407 |
-
|
4408 |
-
/**
|
4409 |
-
* Store the model data in the data html field set in this.setDataField.
|
4410 |
-
*/
|
4411 |
-
storeModelData: function () {
|
4412 |
-
var data = JSON.stringify( this.model.get( 'data' ) );
|
4413 |
-
|
4414 |
-
if ( $( this.dataField ).val() !== data ) {
|
4415 |
-
// If the data is different, set it and trigger a content_change event
|
4416 |
-
$( this.dataField ).val( data );
|
4417 |
-
$( this.dataField ).trigger( 'change' );
|
4418 |
-
this.trigger( 'content_change' );
|
4419 |
-
}
|
4420 |
-
},
|
4421 |
-
|
4422 |
-
/**
|
4423 |
-
* HAndle the visual side of adding a new row to the builder.
|
4424 |
-
*
|
4425 |
-
* @param row
|
4426 |
-
* @param collection
|
4427 |
-
* @param options
|
4428 |
-
*/
|
4429 |
-
onAddRow: function ( row, collection, options ) {
|
4430 |
-
options = _.extend( { noAnimate: false }, options );
|
4431 |
-
// Create a view for the row
|
4432 |
-
var rowView = new panels.view.row( { model: row } );
|
4433 |
-
rowView.builder = this;
|
4434 |
-
rowView.render();
|
4435 |
-
|
4436 |
-
// Attach the row elements to this builder
|
4437 |
-
if ( _.isUndefined( options.at ) || collection.length <= 1 ) {
|
4438 |
-
// Insert this at the end of the widgets container
|
4439 |
-
rowView.$el.appendTo( this.$( '.so-rows-container' ) );
|
4440 |
-
} else {
|
4441 |
-
// We need to insert this at a specific position
|
4442 |
-
rowView.$el.insertAfter(
|
4443 |
-
this.$( '.so-rows-container .so-row-container' ).eq( options.at - 1 )
|
4444 |
-
);
|
4445 |
-
}
|
4446 |
-
|
4447 |
-
if ( options.noAnimate === false ) {
|
4448 |
-
rowView.visualCreate();
|
4449 |
-
}
|
4450 |
-
|
4451 |
-
this.refreshSortable();
|
4452 |
-
rowView.resize();
|
4453 |
-
this.trigger( 'row_added' );
|
4454 |
-
},
|
4455 |
-
|
4456 |
-
/**
|
4457 |
-
* Display the dialog to add a new widget.
|
4458 |
-
*
|
4459 |
-
* @returns {boolean}
|
4460 |
-
*/
|
4461 |
-
displayAddWidgetDialog: function () {
|
4462 |
-
this.dialogs.widgets.openDialog();
|
4463 |
-
},
|
4464 |
-
|
4465 |
-
/**
|
4466 |
-
* Display the dialog to add a new row.
|
4467 |
-
*/
|
4468 |
-
displayAddRowDialog: function () {
|
4469 |
-
var row = new panels.model.row();
|
4470 |
-
var cells = new panels.collection.cells( [ { weight: 0.5 }, { weight: 0.5 } ] );
|
4471 |
-
cells.each( function ( cell ) {
|
4472 |
-
cell.row = row;
|
4473 |
-
} );
|
4474 |
-
row.set( 'cells', cells );
|
4475 |
-
row.builder = this.model;
|
4476 |
-
|
4477 |
-
this.dialogs.row.setRowModel( row );
|
4478 |
-
this.dialogs.row.openDialog();
|
4479 |
-
},
|
4480 |
-
|
4481 |
-
/**
|
4482 |
-
* Display the dialog to add prebuilt layouts.
|
4483 |
-
*
|
4484 |
-
* @returns {boolean}
|
4485 |
-
*/
|
4486 |
-
displayAddPrebuiltDialog: function () {
|
4487 |
-
this.dialogs.prebuilt.openDialog();
|
4488 |
-
},
|
4489 |
-
|
4490 |
-
/**
|
4491 |
-
* Display the history dialog.
|
4492 |
-
*
|
4493 |
-
* @returns {boolean}
|
4494 |
-
*/
|
4495 |
-
displayHistoryDialog: function () {
|
4496 |
-
this.dialogs.history.openDialog();
|
4497 |
-
},
|
4498 |
-
|
4499 |
-
/**
|
4500 |
-
* Handle pasting a row into the builder.
|
4501 |
-
*/
|
4502 |
-
pasteRowHandler: function () {
|
4503 |
-
var pastedModel = panels.helpers.clipboard.getModel( 'row-model' );
|
4504 |
-
|
4505 |
-
if ( !_.isEmpty( pastedModel ) && pastedModel instanceof panels.model.row ) {
|
4506 |
-
this.addHistoryEntry( 'row_pasted' );
|
4507 |
-
pastedModel.builder = this.model;
|
4508 |
-
this.model.get( 'rows' ).add( pastedModel, {
|
4509 |
-
at: this.model.get( 'rows' ).indexOf( this.model ) + 1
|
4510 |
-
} );
|
4511 |
-
this.model.refreshPanelsData();
|
4512 |
-
}
|
4513 |
-
},
|
4514 |
-
|
4515 |
-
/**
|
4516 |
-
* Get the model for the currently selected cell
|
4517 |
-
*/
|
4518 |
-
getActiveCell: function ( options ) {
|
4519 |
-
options = _.extend( {
|
4520 |
-
createCell: true,
|
4521 |
-
}, options );
|
4522 |
-
|
4523 |
-
if ( !this.model.get( 'rows' ).length ) {
|
4524 |
-
// There aren't any rows yet
|
4525 |
-
if ( options.createCell ) {
|
4526 |
-
// Create a row with a single cell
|
4527 |
-
this.model.addRow( {}, [ { weight: 1 } ], { noAnimate: true } );
|
4528 |
-
} else {
|
4529 |
-
return null;
|
4530 |
-
}
|
4531 |
-
}
|
4532 |
-
|
4533 |
-
// Make sure the active cell isn't empty, and it's in a row that exists
|
4534 |
-
var activeCell = this.activeCell;
|
4535 |
-
if ( _.isEmpty( activeCell ) || this.model.get( 'rows' ).indexOf( activeCell.model.row ) === -1 ) {
|
4536 |
-
return this.model.get( 'rows' ).last().get( 'cells' ).first();
|
4537 |
-
} else {
|
4538 |
-
return activeCell.model;
|
4539 |
-
}
|
4540 |
-
},
|
4541 |
-
|
4542 |
-
/**
|
4543 |
-
* Add a live editor to the builder
|
4544 |
-
*
|
4545 |
-
* @returns {panels.view.builder}
|
4546 |
-
*/
|
4547 |
-
addLiveEditor: function () {
|
4548 |
-
if ( _.isEmpty( this.config.liveEditorPreview ) ) {
|
4549 |
-
return this;
|
4550 |
-
}
|
4551 |
-
|
4552 |
-
// Create the live editor and set the builder to this.
|
4553 |
-
this.liveEditor = new panels.view.liveEditor( {
|
4554 |
-
builder: this,
|
4555 |
-
previewUrl: this.config.liveEditorPreview
|
4556 |
-
} );
|
4557 |
-
|
4558 |
-
// Display the live editor button in the toolbar
|
4559 |
-
if ( this.liveEditor.hasPreviewUrl() ) {
|
4560 |
-
this.$( '.so-builder-toolbar .so-live-editor' ).show();
|
4561 |
-
}
|
4562 |
-
|
4563 |
-
this.trigger( 'builder_live_editor_added' );
|
4564 |
-
|
4565 |
-
return this;
|
4566 |
-
},
|
4567 |
-
|
4568 |
-
/**
|
4569 |
-
* Show the current live editor
|
4570 |
-
*/
|
4571 |
-
displayLiveEditor: function () {
|
4572 |
-
if ( _.isUndefined( this.liveEditor ) ) {
|
4573 |
-
return;
|
4574 |
-
}
|
4575 |
-
|
4576 |
-
this.liveEditor.open();
|
4577 |
-
},
|
4578 |
-
|
4579 |
-
/**
|
4580 |
-
* Add the history browser.
|
4581 |
-
*
|
4582 |
-
* @return {panels.view.builder}
|
4583 |
-
*/
|
4584 |
-
addHistoryBrowser: function () {
|
4585 |
-
if ( _.isEmpty( this.config.liveEditorPreview ) ) {
|
4586 |
-
return this;
|
4587 |
-
}
|
4588 |
-
|
4589 |
-
this.dialogs.history = new panels.dialog.history();
|
4590 |
-
this.dialogs.history.builder = this;
|
4591 |
-
this.dialogs.history.entries.builder = this.model;
|
4592 |
-
|
4593 |
-
// Set the revert entry
|
4594 |
-
this.dialogs.history.setRevertEntry( this.model );
|
4595 |
-
|
4596 |
-
// Display the live editor button in the toolbar
|
4597 |
-
this.$( '.so-builder-toolbar .so-history' ).show();
|
4598 |
-
},
|
4599 |
-
|
4600 |
-
/**
|
4601 |
-
* Add an entry.
|
4602 |
-
*
|
4603 |
-
* @param text
|
4604 |
-
* @param data
|
4605 |
-
*/
|
4606 |
-
addHistoryEntry: function ( text, data ) {
|
4607 |
-
if ( _.isUndefined( data ) ) {
|
4608 |
-
data = null;
|
4609 |
-
}
|
4610 |
-
|
4611 |
-
if ( !_.isUndefined( this.dialogs.history ) ) {
|
4612 |
-
this.dialogs.history.entries.addEntry( text, data );
|
4613 |
-
}
|
4614 |
-
},
|
4615 |
-
|
4616 |
-
supports: function ( thing ) {
|
4617 |
-
|
4618 |
-
if ( thing === 'rowAction' ) {
|
4619 |
-
// Check if this supports any row action
|
4620 |
-
return this.supports( 'addRow' ) || this.supports( 'editRow' ) || this.supports( 'deleteRow' );
|
4621 |
-
} else if ( thing === 'widgetAction' ) {
|
4622 |
-
// Check if this supports any widget action
|
4623 |
-
return this.supports( 'addWidget' ) || this.supports( 'editWidget' ) || this.supports( 'deleteWidget' );
|
4624 |
-
}
|
4625 |
-
|
4626 |
-
return _.isUndefined( this.config.builderSupports[ thing ] ) ? false : this.config.builderSupports[ thing ];
|
4627 |
-
},
|
4628 |
-
|
4629 |
-
/**
|
4630 |
-
* Handle a change of the content
|
4631 |
-
*/
|
4632 |
-
handleContentChange: function () {
|
4633 |
-
|
4634 |
-
// Make sure we actually need to copy content.
|
4635 |
-
if ( panelsOptions.copy_content && this.attachedToEditor && this.$el.is( ':visible' ) ) {
|
4636 |
-
|
4637 |
-
var panelsData = this.model.getPanelsData();
|
4638 |
-
if ( !_.isEmpty( panelsData.widgets ) ) {
|
4639 |
-
// We're going to create a copy of page builder content into the post content
|
4640 |
-
$.post(
|
4641 |
-
panelsOptions.ajaxurl,
|
4642 |
-
{
|
4643 |
-
action: 'so_panels_builder_content',
|
4644 |
-
panels_data: JSON.stringify( panelsData ),
|
4645 |
-
post_id: this.config.postId
|
4646 |
-
},
|
4647 |
-
function ( content ) {
|
4648 |
-
if ( content !== '' ) {
|
4649 |
-
this.updateEditorContent( content );
|
4650 |
-
}
|
4651 |
-
}.bind( this )
|
4652 |
-
);
|
4653 |
-
}
|
4654 |
-
}
|
4655 |
-
},
|
4656 |
-
|
4657 |
-
/**
|
4658 |
-
* Update editor content with the given content.
|
4659 |
-
*
|
4660 |
-
* @param content
|
4661 |
-
*/
|
4662 |
-
updateEditorContent: function ( content ) {
|
4663 |
-
// Switch back to the standard editor
|
4664 |
-
if ( this.config.editorType !== 'tinyMCE' || typeof tinyMCE === 'undefined' || _.isNull( tinyMCE.get( "content" ) ) ) {
|
4665 |
-
var $editor = $( this.config.editorId );
|
4666 |
-
$editor.val( content ).trigger( 'change' ).trigger( 'keyup' );
|
4667 |
-
} else {
|
4668 |
-
var contentEd = tinyMCE.get( "content" );
|
4669 |
-
|
4670 |
-
contentEd.setContent( content );
|
4671 |
-
|
4672 |
-
contentEd.fire( 'change' );
|
4673 |
-
contentEd.fire( 'keyup' );
|
4674 |
-
}
|
4675 |
-
|
4676 |
-
this.triggerYoastSeoChange();
|
4677 |
-
},
|
4678 |
-
|
4679 |
-
/**
|
4680 |
-
* Trigger a change on Yoast SEO
|
4681 |
-
*/
|
4682 |
-
triggerYoastSeoChange: function () {
|
4683 |
-
if ( $( '#yoast_wpseo_focuskw_text_input' ).length ) {
|
4684 |
-
var element = document.getElementById( 'yoast_wpseo_focuskw_text_input' ), event;
|
4685 |
-
|
4686 |
-
if ( document.createEvent ) {
|
4687 |
-
event = document.createEvent( "HTMLEvents" );
|
4688 |
-
event.initEvent( "keyup", true, true );
|
4689 |
-
} else {
|
4690 |
-
event = document.createEventObject();
|
4691 |
-
event.eventType = "keyup";
|
4692 |
-
}
|
4693 |
-
|
4694 |
-
event.eventName = "keyup";
|
4695 |
-
|
4696 |
-
if ( document.createEvent ) {
|
4697 |
-
element.dispatchEvent( event );
|
4698 |
-
} else {
|
4699 |
-
element.fireEvent( "on" + event.eventType, event );
|
4700 |
-
}
|
4701 |
-
}
|
4702 |
-
},
|
4703 |
-
|
4704 |
-
/**
|
4705 |
-
* Handle displaying the builder
|
4706 |
-
*/
|
4707 |
-
handleDisplayBuilder: function () {
|
4708 |
-
var editor = typeof tinyMCE !== 'undefined' ? tinyMCE.get( 'content' ) : false;
|
4709 |
-
var editorContent = ( editor && _.isFunction( editor.getContent ) ) ? editor.getContent() : $( 'textarea#content' ).val();
|
4710 |
-
|
4711 |
-
if (
|
4712 |
-
(
|
4713 |
-
_.isEmpty( this.model.get( 'data' ) ) ||
|
4714 |
-
( _.isEmpty( this.model.get( 'data' ).widgets ) && _.isEmpty( this.model.get( 'data' ).grids ) )
|
4715 |
-
) &&
|
4716 |
-
editorContent !== ''
|
4717 |
-
) {
|
4718 |
-
var editorClass = panelsOptions.text_widget;
|
4719 |
-
// There is a small chance a theme will have removed this, so check
|
4720 |
-
if ( _.isEmpty( editorClass ) ) {
|
4721 |
-
return;
|
4722 |
-
}
|
4723 |
-
|
4724 |
-
// Create the existing page content in a single widget
|
4725 |
-
this.model.loadPanelsData( this.model.getPanelsDataFromHtml( editorContent, editorClass ) );
|
4726 |
-
this.model.trigger( 'change' );
|
4727 |
-
this.model.trigger( 'change:data' );
|
4728 |
-
}
|
4729 |
-
|
4730 |
-
$( '#post-status-info' ).addClass( 'for-siteorigin-panels' );
|
4731 |
-
},
|
4732 |
-
|
4733 |
-
handleHideBuilder: function () {
|
4734 |
-
$( '#post-status-info' ).show().removeClass( 'for-siteorigin-panels' );
|
4735 |
-
},
|
4736 |
-
|
4737 |
-
wrapEditorExpandAdjust: function () {
|
4738 |
-
try {
|
4739 |
-
var events = ( $.hasData( window ) && $._data( window ) ).events.scroll,
|
4740 |
-
event;
|
4741 |
-
|
4742 |
-
for ( var i = 0; i < events.length; i++ ) {
|
4743 |
-
if ( events[ i ].namespace === 'editor-expand' ) {
|
4744 |
-
event = events[ i ];
|
4745 |
-
|
4746 |
-
// Wrap the call
|
4747 |
-
$( window ).unbind( 'scroll', event.handler );
|
4748 |
-
$( window ).bind( 'scroll', function ( e ) {
|
4749 |
-
if ( !this.attachedVisible ) {
|
4750 |
-
event.handler( e );
|
4751 |
-
}
|
4752 |
-
}.bind( this ) );
|
4753 |
-
|
4754 |
-
break;
|
4755 |
-
}
|
4756 |
-
}
|
4757 |
-
}
|
4758 |
-
catch ( e ) {
|
4759 |
-
// We tried, we failed
|
4760 |
-
return;
|
4761 |
-
}
|
4762 |
-
},
|
4763 |
-
|
4764 |
-
/**
|
4765 |
-
* Either add or remove the narrow class
|
4766 |
-
* @returns {exports}
|
4767 |
-
*/
|
4768 |
-
handleBuilderSizing: function () {
|
4769 |
-
var width = this.$el.width();
|
4770 |
-
|
4771 |
-
if ( !width ) {
|
4772 |
-
return this;
|
4773 |
-
}
|
4774 |
-
|
4775 |
-
if ( width < 575 ) {
|
4776 |
-
this.$el.addClass( 'so-display-narrow' );
|
4777 |
-
} else {
|
4778 |
-
this.$el.removeClass( 'so-display-narrow' );
|
4779 |
-
}
|
4780 |
-
|
4781 |
-
return this;
|
4782 |
-
},
|
4783 |
-
|
4784 |
-
/**
|
4785 |
-
* Set the parent dialog for all the dialogs in this builder.
|
4786 |
-
*
|
4787 |
-
* @param text
|
4788 |
-
* @param dialog
|
4789 |
-
*/
|
4790 |
-
setDialogParents: function ( text, dialog ) {
|
4791 |
-
_.each( this.dialogs, function ( p, i, d ) {
|
4792 |
-
d[ i ].setParent( text, dialog );
|
4793 |
-
} );
|
4794 |
-
|
4795 |
-
// For any future dialogs
|
4796 |
-
this.on( 'add_dialog', function ( newDialog ) {
|
4797 |
-
newDialog.setParent( text, dialog );
|
4798 |
-
}, this );
|
4799 |
-
},
|
4800 |
-
|
4801 |
-
/**
|
4802 |
-
* This shows or hides the welcome display depending on whether there are any rows in the collection.
|
4803 |
-
*/
|
4804 |
-
toggleWelcomeDisplay: function () {
|
4805 |
-
if ( !this.model.get( 'rows' ).isEmpty() ) {
|
4806 |
-
this.$( '.so-panels-welcome-message' ).hide();
|
4807 |
-
} else {
|
4808 |
-
this.$( '.so-panels-welcome-message' ).show();
|
4809 |
-
}
|
4810 |
-
},
|
4811 |
-
|
4812 |
-
/**
|
4813 |
-
* Activate the contextual menu
|
4814 |
-
* @param e
|
4815 |
-
* @param menu
|
4816 |
-
*/
|
4817 |
-
activateContextMenu: function ( e, menu ) {
|
4818 |
-
var builder = this;
|
4819 |
-
|
4820 |
-
// Only run this if the event target is a descendant of this builder's DOM element.
|
4821 |
-
if ( $.contains( builder.$el.get( 0 ), e.target ) ) {
|
4822 |
-
// Get the element we're currently hovering over
|
4823 |
-
var over = $( [] )
|
4824 |
-
.add( builder.$( '.so-panels-welcome-message:visible' ) )
|
4825 |
-
.add( builder.$( '.so-rows-container > .so-row-container' ) )
|
4826 |
-
.add( builder.$( '.so-cells > .cell' ) )
|
4827 |
-
.add( builder.$( '.cell-wrapper > .so-widget' ) )
|
4828 |
-
.filter( function ( i ) {
|
4829 |
-
return menu.isOverEl( $( this ), e );
|
4830 |
-
} );
|
4831 |
-
|
4832 |
-
var activeView = over.last().data( 'view' );
|
4833 |
-
if ( activeView !== undefined && activeView.buildContextualMenu !== undefined ) {
|
4834 |
-
// We'll pass this to the current active view so it can populate the contextual menu
|
4835 |
-
activeView.buildContextualMenu( e, menu );
|
4836 |
-
}
|
4837 |
-
else if ( over.last().hasClass( 'so-panels-welcome-message' ) ) {
|
4838 |
-
// The user opened the contextual menu on the welcome message
|
4839 |
-
this.buildContextualMenu( e, menu );
|
4840 |
-
}
|
4841 |
-
}
|
4842 |
-
},
|
4843 |
-
|
4844 |
-
/**
|
4845 |
-
* Build the contextual menu for the main builder - before any content has been added.
|
4846 |
-
*/
|
4847 |
-
buildContextualMenu: function ( e, menu ) {
|
4848 |
-
var actions = {};
|
4849 |
-
|
4850 |
-
if ( this.supports( 'addRow' ) ) {
|
4851 |
-
actions.add_row = { title: panelsOptions.loc.contextual.add_row };
|
4852 |
-
}
|
4853 |
-
|
4854 |
-
if ( panels.helpers.clipboard.canCopyPaste() ) {
|
4855 |
-
if ( panels.helpers.clipboard.isModel( 'row-model' ) && this.supports( 'addRow' ) ) {
|
4856 |
-
actions.paste_row = { title: panelsOptions.loc.contextual.row_paste };
|
4857 |
-
}
|
4858 |
-
}
|
4859 |
-
|
4860 |
-
if ( !_.isEmpty( actions ) ) {
|
4861 |
-
menu.addSection(
|
4862 |
-
'builder-actions',
|
4863 |
-
{
|
4864 |
-
sectionTitle: panelsOptions.loc.contextual.row_actions,
|
4865 |
-
search: false,
|
4866 |
-
},
|
4867 |
-
actions,
|
4868 |
-
function ( c ) {
|
4869 |
-
switch ( c ) {
|
4870 |
-
case 'add_row':
|
4871 |
-
this.displayAddRowDialog();
|
4872 |
-
break;
|
4873 |
-
|
4874 |
-
case 'paste_row':
|
4875 |
-
this.pasteRowHandler();
|
4876 |
-
break;
|
4877 |
-
}
|
4878 |
-
}.bind( this )
|
4879 |
-
);
|
4880 |
-
}
|
4881 |
-
},
|
4882 |
-
} );
|
4883 |
-
|
4884 |
-
},{}],24:[function(require,module,exports){
|
4885 |
-
var panels = window.panels, $ = jQuery;
|
4886 |
-
|
4887 |
-
module.exports = Backbone.View.extend( {
|
4888 |
-
template: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-builder-cell' ).html() ) ),
|
4889 |
-
events: {
|
4890 |
-
'click .cell-wrapper': 'handleCellClick'
|
4891 |
-
},
|
4892 |
-
|
4893 |
-
/* The row view that this cell is a part of */
|
4894 |
-
row: null,
|
4895 |
-
widgetSortable: null,
|
4896 |
-
|
4897 |
-
initialize: function () {
|
4898 |
-
this.listenTo(this.model.get('widgets'), 'add', this.onAddWidget );
|
4899 |
-
},
|
4900 |
-
|
4901 |
-
/**
|
4902 |
-
* Render the actual cell
|
4903 |
-
*/
|
4904 |
-
render: function () {
|
4905 |
-
var templateArgs = {
|
4906 |
-
weight: this.model.get( 'weight' ),
|
4907 |
-
totalWeight: this.row.model.get('cells').totalWeight()
|
4908 |
-
};
|
4909 |
-
|
4910 |
-
this.setElement( this.template( templateArgs ) );
|
4911 |
-
this.$el.data( 'view', this );
|
4912 |
-
|
4913 |
-
// Now lets render any widgets that are currently in the row
|
4914 |
-
var thisView = this;
|
4915 |
-
this.model.get('widgets').each( function ( widget ) {
|
4916 |
-
var widgetView = new panels.view.widget( {model: widget} );
|
4917 |
-
widgetView.cell = thisView;
|
4918 |
-
widgetView.render();
|
4919 |
-
|
4920 |
-
widgetView.$el.appendTo( thisView.$( '.widgets-container' ) );
|
4921 |
-
} );
|
4922 |
-
|
4923 |
-
this.initSortable();
|
4924 |
-
this.initResizable();
|
4925 |
-
|
4926 |
-
return this;
|
4927 |
-
},
|
4928 |
-
|
4929 |
-
/**
|
4930 |
-
* Initialize the widget sortable
|
4931 |
-
*/
|
4932 |
-
initSortable: function () {
|
4933 |
-
if( ! this.row.builder.supports( 'moveWidget' ) ) {
|
4934 |
-
return this;
|
4935 |
-
}
|
4936 |
-
|
4937 |
-
var cellView = this;
|
4938 |
-
var builder = cellView.row.builder;
|
4939 |
-
|
4940 |
-
// Go up the view hierarchy until we find the ID attribute
|
4941 |
-
var builderID = builder.$el.attr( 'id' );
|
4942 |
-
var builderModel = builder.model;
|
4943 |
-
|
4944 |
-
// Create a widget sortable that's connected with all other cells
|
4945 |
-
this.widgetSortable = this.$( '.widgets-container' ).sortable( {
|
4946 |
-
placeholder: "so-widget-sortable-highlight",
|
4947 |
-
connectWith: '#' + builderID + ' .so-cells .cell .widgets-container,.block-editor .so-cells .cell .widgets-container',
|
4948 |
-
tolerance: 'pointer',
|
4949 |
-
scroll: false,
|
4950 |
-
over: function ( e, ui ) {
|
4951 |
-
// This will make all the rows in the current builder resize
|
4952 |
-
cellView.row.builder.trigger( 'widget_sortable_move' );
|
4953 |
-
},
|
4954 |
-
remove: function ( e, ui ) {
|
4955 |
-
cellView.model.get( 'widgets' ).remove(
|
4956 |
-
$( ui.item ).data( 'view' ).model,
|
4957 |
-
{ silent: true }
|
4958 |
-
);
|
4959 |
-
builderModel.refreshPanelsData();
|
4960 |
-
},
|
4961 |
-
receive: function ( e, ui ) {
|
4962 |
-
var widgetModel = $( ui.item ).data( 'view' ).model;
|
4963 |
-
widgetModel.cell = cellView.model;
|
4964 |
-
cellView.model.get( 'widgets' ).add(
|
4965 |
-
widgetModel,
|
4966 |
-
{ silent: true, at: $( ui.item ).index() }
|
4967 |
-
);
|
4968 |
-
builderModel.refreshPanelsData();
|
4969 |
-
},
|
4970 |
-
stop: function ( e, ui ) {
|
4971 |
-
var $$ = $( ui.item ),
|
4972 |
-
widget = $$.data( 'view' ),
|
4973 |
-
targetCell = $$.closest( '.cell' ).data( 'view' );
|
4974 |
-
|
4975 |
-
|
4976 |
-
// If this hasn't already been removed and added to a different builder.
|
4977 |
-
if ( cellView.model.get( 'widgets' ).get( widget.model ) ) {
|
4978 |
-
|
4979 |
-
cellView.row.builder.addHistoryEntry( 'widget_moved' );
|
4980 |
-
|
4981 |
-
// Move the model and the view to the new cell
|
4982 |
-
widget.model.moveToCell( targetCell.model, {}, $$.index() );
|
4983 |
-
widget.cell = targetCell;
|
4984 |
-
|
4985 |
-
builderModel.refreshPanelsData();
|
4986 |
-
}
|
4987 |
-
},
|
4988 |
-
helper: function ( e, el ) {
|
4989 |
-
var helper = el.clone()
|
4990 |
-
.css( {
|
4991 |
-
'width': el.outerWidth(),
|
4992 |
-
'z-index': 10000,
|
4993 |
-
'position': 'fixed'
|
4994 |
-
} )
|
4995 |
-
.addClass( 'widget-being-dragged' ).appendTo( 'body' );
|
4996 |
-
|
4997 |
-
// Center the helper to the mouse cursor.
|
4998 |
-
if ( el.outerWidth() > 720 ) {
|
4999 |
-
helper.animate( {
|
5000 |
-
'margin-left': e.pageX - el.offset().left - (
|
5001 |
-
480 / 2
|
5002 |
-
),
|
5003 |
-
'width': 480
|
5004 |
-
}, 'fast' );
|
5005 |
-
}
|
5006 |
-
|
5007 |
-
return helper;
|
5008 |
-
}
|
5009 |
-
} );
|
5010 |
-
|
5011 |
-
return this;
|
5012 |
-
},
|
5013 |
-
|
5014 |
-
/**
|
5015 |
-
* Refresh the widget sortable when a new widget is added
|
5016 |
-
*/
|
5017 |
-
refreshSortable: function () {
|
5018 |
-
if ( ! _.isNull( this.widgetSortable ) ) {
|
5019 |
-
this.widgetSortable.sortable( 'refresh' );
|
5020 |
-
}
|
5021 |
-
},
|
5022 |
-
|
5023 |
-
/**
|
5024 |
-
* This will make the cell resizble
|
5025 |
-
*/
|
5026 |
-
initResizable: function () {
|
5027 |
-
if( ! this.row.builder.supports( 'editRow' ) ) {
|
5028 |
-
return this;
|
5029 |
-
}
|
5030 |
-
|
5031 |
-
// var neighbor = this.$el.previous().data('view');
|
5032 |
-
var handle = this.$( '.resize-handle' ).css( 'position', 'absolute' );
|
5033 |
-
var container = this.row.$el;
|
5034 |
-
var cellView = this;
|
5035 |
-
|
5036 |
-
// The view of the cell to the left is stored when dragging starts.
|
5037 |
-
var previousCell;
|
5038 |
-
|
5039 |
-
handle.draggable( {
|
5040 |
-
axis: 'x',
|
5041 |
-
containment: container,
|
5042 |
-
start: function ( e, ui ) {
|
5043 |
-
// Set the containment to the cell parent
|
5044 |
-
previousCell = cellView.$el.prev().data( 'view' );
|
5045 |
-
if ( _.isUndefined( previousCell ) ) {
|
5046 |
-
return;
|
5047 |
-
}
|
5048 |
-
|
5049 |
-
// Create the clone for the current cell
|
5050 |
-
var newCellClone = cellView.$el.clone().appendTo( ui.helper ).css( {
|
5051 |
-
position: 'absolute',
|
5052 |
-
top: '0',
|
5053 |
-
width: cellView.$el.outerWidth(),
|
5054 |
-
left: 5,
|
5055 |
-
height: cellView.$el.outerHeight()
|
5056 |
-
} );
|
5057 |
-
newCellClone.find( '.resize-handle' ).remove();
|
5058 |
-
|
5059 |
-
// Create the clone for the previous cell
|
5060 |
-
var prevCellClone = previousCell.$el.clone().appendTo( ui.helper ).css( {
|
5061 |
-
position: 'absolute',
|
5062 |
-
top: '0',
|
5063 |
-
width: previousCell.$el.outerWidth(),
|
5064 |
-
right: 5,
|
5065 |
-
height: previousCell.$el.outerHeight()
|
5066 |
-
} );
|
5067 |
-
prevCellClone.find( '.resize-handle' ).remove();
|
5068 |
-
|
5069 |
-
$( this ).data( {
|
5070 |
-
'newCellClone': newCellClone,
|
5071 |
-
'prevCellClone': prevCellClone
|
5072 |
-
} );
|
5073 |
-
},
|
5074 |
-
drag: function ( e, ui ) {
|
5075 |
-
// Calculate the new cell and previous cell widths as a percent
|
5076 |
-
var containerWidth = cellView.row.$el.width() + 10;
|
5077 |
-
var ncw = cellView.model.get( 'weight' ) - (
|
5078 |
-
(
|
5079 |
-
ui.position.left + handle.outerWidth() / 2
|
5080 |
-
) / containerWidth
|
5081 |
-
);
|
5082 |
-
var pcw = previousCell.model.get( 'weight' ) + (
|
5083 |
-
(
|
5084 |
-
ui.position.left + handle.outerWidth() / 2
|
5085 |
-
) / containerWidth
|
5086 |
-
);
|
5087 |
-
|
5088 |
-
$( this ).data( 'newCellClone' ).css( 'width', containerWidth * ncw )
|
5089 |
-
.find( '.preview-cell-weight' ).html( Math.round( ncw * 1000 ) / 10 );
|
5090 |
-
|
5091 |
-
$( this ).data( 'prevCellClone' ).css( 'width', containerWidth * pcw )
|
5092 |
-
.find( '.preview-cell-weight' ).html( Math.round( pcw * 1000 ) / 10 );
|
5093 |
-
},
|
5094 |
-
stop: function ( e, ui ) {
|
5095 |
-
// Remove the clones
|
5096 |
-
$( this ).data( 'newCellClone' ).remove();
|
5097 |
-
$( this ).data( 'prevCellClone' ).remove();
|
5098 |
-
|
5099 |
-
var containerWidth = cellView.row.$el.width() + 10;
|
5100 |
-
var ncw = cellView.model.get( 'weight' ) - (
|
5101 |
-
(
|
5102 |
-
ui.position.left + handle.outerWidth() / 2
|
5103 |
-
) / containerWidth
|
5104 |
-
);
|
5105 |
-
var pcw = previousCell.model.get( 'weight' ) + (
|
5106 |
-
(
|
5107 |
-
ui.position.left + handle.outerWidth() / 2
|
5108 |
-
) / containerWidth
|
5109 |
-
);
|
5110 |
-
|
5111 |
-
if ( ncw > 0.02 && pcw > 0.02 ) {
|
5112 |
-
cellView.row.builder.addHistoryEntry( 'cell_resized' );
|
5113 |
-
cellView.model.set( 'weight', ncw );
|
5114 |
-
previousCell.model.set( 'weight', pcw );
|
5115 |
-
cellView.row.resize();
|
5116 |
-
}
|
5117 |
-
|
5118 |
-
ui.helper.css( 'left', - handle.outerWidth() / 2 );
|
5119 |
-
|
5120 |
-
// Refresh the panels data
|
5121 |
-
cellView.row.builder.model.refreshPanelsData();
|
5122 |
-
}
|
5123 |
-
} );
|
5124 |
-
|
5125 |
-
return this;
|
5126 |
-
},
|
5127 |
-
|
5128 |
-
/**
|
5129 |
-
* This is triggered when ever a widget is added to the row collection.
|
5130 |
-
*
|
5131 |
-
* @param widget
|
5132 |
-
*/
|
5133 |
-
onAddWidget: function ( widget, collection, options ) {
|
5134 |
-
options = _.extend( {noAnimate: false}, options );
|
5135 |
-
|
5136 |
-
// Create the view for the widget
|
5137 |
-
var view = new panels.view.widget( {
|
5138 |
-
model: widget
|
5139 |
-
} );
|
5140 |
-
view.cell = this;
|
5141 |
-
|
5142 |
-
if ( _.isUndefined( widget.isDuplicate ) ) {
|
5143 |
-
widget.isDuplicate = false;
|
5144 |
-
}
|
5145 |
-
|
5146 |
-
// Render and load the form if this is a duplicate
|
5147 |
-
view.render( {
|
5148 |
-
'loadForm': widget.isDuplicate
|
5149 |
-
} );
|
5150 |
-
|
5151 |
-
if ( _.isUndefined( options.at ) || collection.length <= 1 ) {
|
5152 |
-
// Insert this at the end of the widgets container
|
5153 |
-
view.$el.appendTo( this.$( '.widgets-container' ) );
|
5154 |
-
} else {
|
5155 |
-
// We need to insert this at a specific position
|
5156 |
-
view.$el.insertAfter(
|
5157 |
-
this.$( '.widgets-container .so-widget' ).eq( options.at - 1 )
|
5158 |
-
);
|
5159 |
-
}
|
5160 |
-
|
5161 |
-
if ( options.noAnimate === false ) {
|
5162 |
-
// We need an animation
|
5163 |
-
view.visualCreate();
|
5164 |
-
}
|
5165 |
-
|
5166 |
-
this.refreshSortable();
|
5167 |
-
this.row.resize();
|
5168 |
-
this.row.builder.trigger( 'widget_added', view );
|
5169 |
-
},
|
5170 |
-
|
5171 |
-
/**
|
5172 |
-
* Handle this cell being clicked on
|
5173 |
-
*
|
5174 |
-
* @param e
|
5175 |
-
* @returns {boolean}
|
5176 |
-
*/
|
5177 |
-
handleCellClick: function ( e ) {
|
5178 |
-
// Remove all existing selected cell indication for this builder
|
5179 |
-
this.row.builder.$el.find( '.so-cells .cell' ).removeClass( 'cell-selected' );
|
5180 |
-
|
5181 |
-
if( this.row.builder.activeCell === this && ! this.model.get('widgets').length ) {
|
5182 |
-
// This is a click on an empty cell
|
5183 |
-
this.row.builder.activeCell = null;
|
5184 |
-
}
|
5185 |
-
else {
|
5186 |
-
this.$el.addClass( 'cell-selected' );
|
5187 |
-
this.row.builder.activeCell = this;
|
5188 |
-
}
|
5189 |
-
},
|
5190 |
-
|
5191 |
-
/**
|
5192 |
-
* Insert a widget from the clipboard
|
5193 |
-
*/
|
5194 |
-
pasteHandler: function(){
|
5195 |
-
var pastedModel = panels.helpers.clipboard.getModel( 'widget-model' );
|
5196 |
-
if( ! _.isEmpty( pastedModel ) && pastedModel instanceof panels.model.widget ) {
|
5197 |
-
this.row.builder.addHistoryEntry( 'widget_pasted' );
|
5198 |
-
pastedModel.cell = this.model;
|
5199 |
-
this.model.get('widgets').add( pastedModel );
|
5200 |
-
this.row.builder.model.refreshPanelsData();
|
5201 |
-
}
|
5202 |
-
},
|
5203 |
-
|
5204 |
-
/**
|
5205 |
-
* Build up the contextual menu for a cell
|
5206 |
-
*
|
5207 |
-
* @param e
|
5208 |
-
* @param menu
|
5209 |
-
*/
|
5210 |
-
buildContextualMenu: function ( e, menu ) {
|
5211 |
-
var thisView = this;
|
5212 |
-
|
5213 |
-
if( ! menu.hasSection( 'add-widget-below' ) ) {
|
5214 |
-
menu.addSection(
|
5215 |
-
'add-widget-cell',
|
5216 |
-
{
|
5217 |
-
sectionTitle: panelsOptions.loc.contextual.add_widget_cell,
|
5218 |
-
searchPlaceholder: panelsOptions.loc.contextual.search_widgets,
|
5219 |
-
defaultDisplay: panelsOptions.contextual.default_widgets
|
5220 |
-
},
|
5221 |
-
panelsOptions.widgets,
|
5222 |
-
function ( c ) {
|
5223 |
-
thisView.row.builder.trigger('before_user_adds_widget')
|
5224 |
-
thisView.row.builder.addHistoryEntry( 'widget_added' );
|
5225 |
-
|
5226 |
-
var widget = new panels.model.widget( {
|
5227 |
-
class: c
|
5228 |
-
} );
|
5229 |
-
|
5230 |
-
// Add the widget to the cell model
|
5231 |
-
widget.cell = thisView.model;
|
5232 |
-
widget.cell.get('widgets').add( widget );
|
5233 |
-
|
5234 |
-
thisView.row.builder.model.refreshPanelsData();
|
5235 |
-
thisView.row.builder.trigger('after_user_adds_widget', widget);
|
5236 |
-
}
|
5237 |
-
);
|
5238 |
-
}
|
5239 |
-
|
5240 |
-
var actions = {};
|
5241 |
-
if ( this.row.builder.supports('addWidget') && panels.helpers.clipboard.isModel( 'widget-model' ) ) {
|
5242 |
-
actions.paste = {title: panelsOptions.loc.contextual.cell_paste_widget};
|
5243 |
-
}
|
5244 |
-
|
5245 |
-
if( ! _.isEmpty( actions ) ) {
|
5246 |
-
menu.addSection(
|
5247 |
-
'cell-actions',
|
5248 |
-
{
|
5249 |
-
sectionTitle: panelsOptions.loc.contextual.cell_actions,
|
5250 |
-
search: false,
|
5251 |
-
},
|
5252 |
-
actions,
|
5253 |
-
function ( c ) {
|
5254 |
-
switch ( c ) {
|
5255 |
-
case 'paste':
|
5256 |
-
this.pasteHandler();
|
5257 |
-
break;
|
5258 |
-
}
|
5259 |
-
|
5260 |
-
this.row.builder.model.refreshPanelsData();
|
5261 |
-
}.bind( this )
|
5262 |
-
);
|
5263 |
-
}
|
5264 |
-
|
5265 |
-
// Add the contextual menu for the parent row
|
5266 |
-
this.row.buildContextualMenu( e, menu );
|
5267 |
-
}
|
5268 |
-
} );
|
5269 |
-
|
5270 |
-
},{}],25:[function(require,module,exports){
|
5271 |
-
var panels = window.panels, $ = jQuery;
|
5272 |
-
|
5273 |
-
module.exports = Backbone.View.extend( {
|
5274 |
-
dialogTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-dialog' ).html() ) ),
|
5275 |
-
dialogTabTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-dialog-tab' ).html() ) ),
|
5276 |
-
|
5277 |
-
tabbed: false,
|
5278 |
-
rendered: false,
|
5279 |
-
builder: false,
|
5280 |
-
className: 'so-panels-dialog-wrapper',
|
5281 |
-
dialogClass: '',
|
5282 |
-
dialogIcon: '',
|
5283 |
-
parentDialog: false,
|
5284 |
-
dialogOpen: false,
|
5285 |
-
editableLabel: false,
|
5286 |
-
|
5287 |
-
events: {
|
5288 |
-
'click .so-close': 'closeDialog',
|
5289 |
-
'click .so-nav.so-previous': 'navToPrevious',
|
5290 |
-
'click .so-nav.so-next': 'navToNext',
|
5291 |
-
},
|
5292 |
-
|
5293 |
-
initialize: function () {
|
5294 |
-
// The first time this dialog is opened, render it
|
5295 |
-
this.once( 'open_dialog', this.render );
|
5296 |
-
this.once( 'open_dialog', this.attach );
|
5297 |
-
this.once( 'open_dialog', this.setDialogClass );
|
5298 |
-
|
5299 |
-
this.trigger( 'initialize_dialog', this );
|
5300 |
-
|
5301 |
-
if ( ! _.isUndefined( this.initializeDialog ) ) {
|
5302 |
-
this.initializeDialog();
|
5303 |
-
}
|
5304 |
-
|
5305 |
-
_.bindAll( this, 'initSidebars', 'hasSidebar', 'onResize', 'toggleLeftSideBar', 'toggleRightSideBar' );
|
5306 |
-
},
|
5307 |
-
|
5308 |
-
/**
|
5309 |
-
* Returns the next dialog in the sequence. Should be overwritten by a child dialog.
|
5310 |
-
* @returns {null}
|
5311 |
-
*/
|
5312 |
-
getNextDialog: function () {
|
5313 |
-
return null;
|
5314 |
-
},
|
5315 |
-
|
5316 |
-
/**
|
5317 |
-
* Returns the previous dialog in this sequence. Should be overwritten by child dialog.
|
5318 |
-
* @returns {null}
|
5319 |
-
*/
|
5320 |
-
getPrevDialog: function () {
|
5321 |
-
return null;
|
5322 |
-
},
|
5323 |
-
|
5324 |
-
/**
|
5325 |
-
* Adds a dialog class to uniquely identify this dialog type
|
5326 |
-
*/
|
5327 |
-
setDialogClass: function () {
|
5328 |
-
if ( this.dialogClass !== '' ) {
|
5329 |
-
this.$( '.so-panels-dialog' ).addClass( this.dialogClass );
|
5330 |
-
}
|
5331 |
-
},
|
5332 |
-
|
5333 |
-
/**
|
5334 |
-
* Set the builder that controls this dialog.
|
5335 |
-
* @param {panels.view.builder} builder
|
5336 |
-
*/
|
5337 |
-
setBuilder: function ( builder ) {
|
5338 |
-
this.builder = builder;
|
5339 |
-
|
5340 |
-
// Trigger an add dialog event on the builder so it can modify the dialog in any way
|
5341 |
-
builder.trigger( 'add_dialog', this, this.builder );
|
5342 |
-
|
5343 |
-
return this;
|
5344 |
-
},
|
5345 |
-
|
5346 |
-
/**
|
5347 |
-
* Attach the dialog to the window
|
5348 |
-
*/
|
5349 |
-
attach: function () {
|
5350 |
-
this.$el.appendTo( 'body' );
|
5351 |
-
|
5352 |
-
return this;
|
5353 |
-
},
|
5354 |
-
|
5355 |
-
/**
|
5356 |
-
* Converts an HTML representation of the dialog into arguments for a dialog box
|
5357 |
-
* @param html HTML for the dialog
|
5358 |
-
* @param args Arguments passed to the template
|
5359 |
-
* @returns {}
|
5360 |
-
*/
|
5361 |
-
parseDialogContent: function ( html, args ) {
|
5362 |
-
// Add a CID
|
5363 |
-
args = _.extend( {cid: this.cid}, args );
|
5364 |
-
|
5365 |
-
|
5366 |
-
var c = $( (
|
5367 |
-
_.template( panels.helpers.utils.processTemplate( html ) )
|
5368 |
-
)( args ) );
|
5369 |
-
var r = {
|
5370 |
-
title: c.find( '.title' ).html(),
|
5371 |
-
buttons: c.find( '.buttons' ).html(),
|
5372 |
-
content: c.find( '.content' ).html()
|
5373 |
-
};
|
5374 |
-
|
5375 |
-
if ( c.has( '.left-sidebar' ) ) {
|
5376 |
-
r.left_sidebar = c.find( '.left-sidebar' ).html();
|
5377 |
-
}
|
5378 |
-
|
5379 |
-
if ( c.has( '.right-sidebar' ) ) {
|
5380 |
-
r.right_sidebar = c.find( '.right-sidebar' ).html();
|
5381 |
-
}
|
5382 |
-
|
5383 |
-
return r;
|
5384 |
-
|
5385 |
-
},
|
5386 |
-
|
5387 |
-
/**
|
5388 |
-
* Render the dialog and initialize the tabs
|
5389 |
-
*
|
5390 |
-
* @param attributes
|
5391 |
-
* @returns {panels.view.dialog}
|
5392 |
-
*/
|
5393 |
-
renderDialog: function ( attributes ) {
|
5394 |
-
attributes = _.extend( {
|
5395 |
-
editableLabel: this.editableLabel,
|
5396 |
-
dialogIcon: this.dialogIcon,
|
5397 |
-
}, attributes );
|
5398 |
-
|
5399 |
-
this.$el.html( this.dialogTemplate( attributes ) ).hide();
|
5400 |
-
this.$el.data( 'view', this );
|
5401 |
-
this.$el.addClass( 'so-panels-dialog-wrapper' );
|
5402 |
-
|
5403 |
-
if ( this.parentDialog !== false ) {
|
5404 |
-
// Add a link to the parent dialog as a sort of crumbtrail.
|
5405 |
-
var dialogParent = $( '<h3 class="so-parent-link"></h3>' ).html( this.parentDialog.text + '<div class="so-separator"></div>' );
|
5406 |
-
dialogParent.click( function ( e ) {
|
5407 |
-
e.preventDefault();
|
5408 |
-
this.closeDialog();
|
5409 |
-
this.parentDialog.dialog.openDialog();
|
5410 |
-
}.bind(this) );
|
5411 |
-
this.$( '.so-title-bar .so-title' ).before( dialogParent );
|
5412 |
-
}
|
5413 |
-
|
5414 |
-
if( this.$( '.so-title-bar .so-title-editable' ).length ) {
|
5415 |
-
// Added here because .so-edit-title is only available after the template has been rendered.
|
5416 |
-
this.initEditableLabel();
|
5417 |
-
}
|
5418 |
-
|
5419 |
-
setTimeout( this.initSidebars, 1 );
|
5420 |
-
|
5421 |
-
return this;
|
5422 |
-
},
|
5423 |
-
|
5424 |
-
initSidebars: function () {
|
5425 |
-
var $leftButton = this.$( '.so-show-left-sidebar' ).hide();
|
5426 |
-
var $rightButton = this.$( '.so-show-right-sidebar' ).hide();
|
5427 |
-
var hasLeftSidebar = this.hasSidebar( 'left' );
|
5428 |
-
var hasRightSidebar = this.hasSidebar( 'right' );
|
5429 |
-
// Set up resize handling
|
5430 |
-
if ( hasLeftSidebar || hasRightSidebar ) {
|
5431 |
-
$( window ).on( 'resize', this.onResize );
|
5432 |
-
if ( hasLeftSidebar ) {
|
5433 |
-
$leftButton.show();
|
5434 |
-
$leftButton.on( 'click', this.toggleLeftSideBar );
|
5435 |
-
}
|
5436 |
-
if ( hasRightSidebar ) {
|
5437 |
-
$rightButton.show();
|
5438 |
-
$rightButton.on( 'click', this.toggleRightSideBar );
|
5439 |
-
}
|
5440 |
-
}
|
5441 |
-
|
5442 |
-
this.onResize();
|
5443 |
-
},
|
5444 |
-
|
5445 |
-
/**
|
5446 |
-
* Initialize the sidebar tabs
|
5447 |
-
*/
|
5448 |
-
initTabs: function () {
|
5449 |
-
var tabs = this.$( '.so-sidebar-tabs li a' );
|
5450 |
-
|
5451 |
-
if ( tabs.length === 0 ) {
|
5452 |
-
return this;
|
5453 |
-
}
|
5454 |
-
|
5455 |
-
var thisDialog = this;
|
5456 |
-
tabs.click( function ( e ) {
|
5457 |
-
e.preventDefault();
|
5458 |
-
var $$ = $( this );
|
5459 |
-
|
5460 |
-
thisDialog.$( '.so-sidebar-tabs li' ).removeClass( 'tab-active' );
|
5461 |
-
thisDialog.$( '.so-content .so-content-tabs > *' ).hide();
|
5462 |
-
|
5463 |
-
$$.parent().addClass( 'tab-active' );
|
5464 |
-
|
5465 |
-
var url = $$.attr( 'href' );
|
5466 |
-
if ( ! _.isUndefined( url ) && url.charAt( 0 ) === '#' ) {
|
5467 |
-
// Display the new tab
|
5468 |
-
var tabName = url.split( '#' )[1];
|
5469 |
-
thisDialog.$( '.so-content .so-content-tabs .tab-' + tabName ).show();
|
5470 |
-
}
|
5471 |
-
|
5472 |
-
// This lets other dialogs implement their own custom handlers
|
5473 |
-
thisDialog.trigger( 'tab_click', $$ );
|
5474 |
-
|
5475 |
-
} );
|
5476 |
-
|
5477 |
-
// Trigger a click on the first tab
|
5478 |
-
this.$( '.so-sidebar-tabs li a' ).first().click();
|
5479 |
-
return this;
|
5480 |
-
},
|
5481 |
-
|
5482 |
-
initToolbar: function () {
|
5483 |
-
// Trigger simplified click event for elements marked as toolbar buttons.
|
5484 |
-
var buttons = this.$( '.so-toolbar .so-buttons .so-toolbar-button' );
|
5485 |
-
buttons.click( function ( e ) {
|
5486 |
-
e.preventDefault();
|
5487 |
-
|
5488 |
-
this.trigger( 'button_click', $( e.currentTarget ) );
|
5489 |
-
}.bind( this ) );
|
5490 |
-
|
5491 |
-
// Handle showing and hiding the dropdown list items
|
5492 |
-
var $dropdowns = this.$( '.so-toolbar .so-buttons .so-dropdown-button' );
|
5493 |
-
$dropdowns.click( function ( e ) {
|
5494 |
-
e.preventDefault();
|
5495 |
-
var $dropdownButton = $( e.currentTarget );
|
5496 |
-
var $dropdownList = $dropdownButton.siblings( '.so-dropdown-links-wrapper' );
|
5497 |
-
if ( $dropdownList.is( '.hidden' ) ) {
|
5498 |
-
$dropdownList.removeClass( 'hidden' );
|
5499 |
-
} else {
|
5500 |
-
$dropdownList.addClass( 'hidden' );
|
5501 |
-
}
|
5502 |
-
|
5503 |
-
}.bind( this ) );
|
5504 |
-
|
5505 |
-
// Hide dropdown list on click anywhere, unless it's a dropdown option which requires confirmation in it's
|
5506 |
-
// unconfirmed state.
|
5507 |
-
$( 'html' ).click( function ( e ) {
|
5508 |
-
this.$( '.so-dropdown-links-wrapper' ).not( '.hidden' ).each( function ( index, el ) {
|
5509 |
-
var $dropdownList = $( el );
|
5510 |
-
var $trgt = $( e.target );
|
5511 |
-
if ( $trgt.length === 0 || !(
|
5512 |
-
(
|
5513 |
-
$trgt.is('.so-needs-confirm') && !$trgt.is('.so-confirmed')
|
5514 |
-
) || $trgt.is('.so-dropdown-button')
|
5515 |
-
) ) {
|
5516 |
-
$dropdownList.addClass('hidden');
|
5517 |
-
}
|
5518 |
-
} );
|
5519 |
-
}.bind( this ) );
|
5520 |
-
},
|
5521 |
-
|
5522 |
-
/**
|
5523 |
-
* Initialize the editable dialog title
|
5524 |
-
*/
|
5525 |
-
initEditableLabel: function(){
|
5526 |
-
var $editElt = this.$( '.so-title-bar .so-title-editable' );
|
5527 |
-
|
5528 |
-
$editElt.keypress( function ( event ) {
|
5529 |
-
var enterPressed = event.type === 'keypress' && event.keyCode === 13;
|
5530 |
-
if ( enterPressed ) {
|
5531 |
-
// Need to make sure tab focus is on another element, otherwise pressing enter multiple times refocuses
|
5532 |
-
// the element and allows newlines.
|
5533 |
-
var tabbables = $( ':tabbable' );
|
5534 |
-
var curTabIndex = tabbables.index( $editElt );
|
5535 |
-
tabbables.eq( curTabIndex + 1 ).focus();
|
5536 |
-
// After the above, we're somehow left with the first letter of text selected,
|
5537 |
-
// so this removes the selection.
|
5538 |
-
window.getSelection().removeAllRanges();
|
5539 |
-
}
|
5540 |
-
return !enterPressed;
|
5541 |
-
} ).blur( function () {
|
5542 |
-
var newValue = $editElt.text().replace( /^\s+|\s+$/gm, '' );
|
5543 |
-
var oldValue = $editElt.data( 'original-value' ).replace( /^\s+|\s+$/gm, '' );
|
5544 |
-
if ( newValue !== oldValue ) {
|
5545 |
-
$editElt.text( newValue );
|
5546 |
-
this.trigger( 'edit_label', newValue );
|
5547 |
-
}
|
5548 |
-
|
5549 |
-
}.bind( this ) );
|
5550 |
-
|
5551 |
-
$editElt.focus( function() {
|
5552 |
-
$editElt.data( 'original-value', $editElt.text() );
|
5553 |
-
panels.helpers.utils.selectElementContents( this );
|
5554 |
-
} );
|
5555 |
-
},
|
5556 |
-
|
5557 |
-
/**
|
5558 |
-
* Quickly setup the dialog by opening and closing it.
|
5559 |
-
*/
|
5560 |
-
setupDialog: function () {
|
5561 |
-
this.openDialog();
|
5562 |
-
this.closeDialog();
|
5563 |
-
},
|
5564 |
-
|
5565 |
-
/**
|
5566 |
-
* Refresh the next and previous buttons.
|
5567 |
-
*/
|
5568 |
-
refreshDialogNav: function () {
|
5569 |
-
this.$( '.so-title-bar .so-nav' ).show().removeClass( 'so-disabled' );
|
5570 |
-
|
5571 |
-
// Lets also hide the next and previous if we don't have a next and previous dialog
|
5572 |
-
var nextDialog = this.getNextDialog();
|
5573 |
-
var nextButton = this.$( '.so-title-bar .so-next' );
|
5574 |
-
|
5575 |
-
var prevDialog = this.getPrevDialog();
|
5576 |
-
var prevButton = this.$( '.so-title-bar .so-previous' );
|
5577 |
-
|
5578 |
-
if ( nextDialog === null ) {
|
5579 |
-
nextButton.hide();
|
5580 |
-
}
|
5581 |
-
else if ( nextDialog === false ) {
|
5582 |
-
nextButton.addClass( 'so-disabled' );
|
5583 |
-
}
|
5584 |
-
|
5585 |
-
if ( prevDialog === null ) {
|
5586 |
-
prevButton.hide();
|
5587 |
-
}
|
5588 |
-
else if ( prevDialog === false ) {
|
5589 |
-
prevButton.addClass( 'so-disabled' );
|
5590 |
-
}
|
5591 |
-
},
|
5592 |
-
|
5593 |
-
/**
|
5594 |
-
* Open the dialog
|
5595 |
-
*/
|
5596 |
-
openDialog: function ( options ) {
|
5597 |
-
options = _.extend( {
|
5598 |
-
silent: false
|
5599 |
-
}, options );
|
5600 |
-
|
5601 |
-
if ( ! options.silent ) {
|
5602 |
-
this.trigger( 'open_dialog' );
|
5603 |
-
}
|
5604 |
-
|
5605 |
-
this.dialogOpen = true;
|
5606 |
-
|
5607 |
-
this.refreshDialogNav();
|
5608 |
-
|
5609 |
-
// Stop scrolling for the main body
|
5610 |
-
panels.helpers.pageScroll.lock();
|
5611 |
-
|
5612 |
-
this.onResize();
|
5613 |
-
|
5614 |
-
this.$el.show();
|
5615 |
-
|
5616 |
-
if ( ! options.silent ) {
|
5617 |
-
// This triggers once everything is visible
|
5618 |
-
this.trigger( 'open_dialog_complete' );
|
5619 |
-
this.builder.trigger( 'open_dialog', this );
|
5620 |
-
$( document ).trigger( 'open_dialog', this );
|
5621 |
-
}
|
5622 |
-
},
|
5623 |
-
|
5624 |
-
/**
|
5625 |
-
* Close the dialog
|
5626 |
-
*
|
5627 |
-
* @param e
|
5628 |
-
* @returns {boolean}
|
5629 |
-
*/
|
5630 |
-
closeDialog: function ( options ) {
|
5631 |
-
options = _.extend( {
|
5632 |
-
silent: false
|
5633 |
-
}, options );
|
5634 |
-
|
5635 |
-
if ( ! options.silent ) {
|
5636 |
-
this.trigger( 'close_dialog' );
|
5637 |
-
}
|
5638 |
-
|
5639 |
-
this.dialogOpen = false;
|
5640 |
-
|
5641 |
-
this.$el.hide();
|
5642 |
-
panels.helpers.pageScroll.unlock();
|
5643 |
-
|
5644 |
-
if ( ! options.silent ) {
|
5645 |
-
// This triggers once everything is hidden
|
5646 |
-
this.trigger( 'close_dialog_complete' );
|
5647 |
-
this.builder.trigger( 'close_dialog', this );
|
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-save': 'closeAndSave',
|
5893 |
-
'click .live-editor-collapse': 'collapse',
|
5894 |
-
'click .live-editor-mode': 'mobileToggle'
|
5895 |
-
},
|
5896 |
-
|
5897 |
-
initialize: function ( options ) {
|
5898 |
-
options = _.extend( {
|
5899 |
-
builder: false,
|
5900 |
-
previewUrl: false,
|
5901 |
-
}, options );
|
5902 |
-
|
5903 |
-
if( _.isEmpty( options.previewUrl ) ) {
|
5904 |
-
options.previewUrl = panelsOptions.ajaxurl + "&action=so_panels_live_editor_preview";
|
5905 |
-
}
|
5906 |
-
|
5907 |
-
this.builder = options.builder;
|
5908 |
-
this.previewUrl = options.previewUrl;
|
5909 |
-
|
5910 |
-
this.listenTo( this.builder.model, 'refresh_panels_data', this.handleRefreshData );
|
5911 |
-
this.listenTo( this.builder.model, 'load_panels_data', this.handleLoadData );
|
5912 |
-
},
|
5913 |
-
|
5914 |
-
/**
|
5915 |
-
* Render the live editor
|
5916 |
-
*/
|
5917 |
-
render: function () {
|
5918 |
-
this.setElement( this.template() );
|
5919 |
-
this.$el.hide();
|
5920 |
-
|
5921 |
-
if ( $( '#submitdiv #save-post' ).length > 0 ) {
|
5922 |
-
var $saveButton = this.$el.find( '.live-editor-save' );
|
5923 |
-
$saveButton.text( $saveButton.data( 'save' ) );
|
5924 |
-
}
|
5925 |
-
|
5926 |
-
var isMouseDown = false;
|
5927 |
-
$( document )
|
5928 |
-
.mousedown( function () {
|
5929 |
-
isMouseDown = true;
|
5930 |
-
} )
|
5931 |
-
.mouseup( function () {
|
5932 |
-
isMouseDown = false;
|
5933 |
-
} );
|
5934 |
-
|
5935 |
-
// Handle highlighting the relevant widget in the live editor preview
|
5936 |
-
var liveEditorView = this;
|
5937 |
-
this.$el.on( 'mouseenter', '.so-widget-wrapper', function () {
|
5938 |
-
var $$ = $( this ),
|
5939 |
-
previewWidget = $$.data( 'live-editor-preview-widget' );
|
5940 |
-
|
5941 |
-
if ( ! isMouseDown && previewWidget !== undefined && previewWidget.length && ! liveEditorView.$( '.so-preview-overlay' ).is( ':visible' ) ) {
|
5942 |
-
liveEditorView.highlightElement( previewWidget );
|
5943 |
-
liveEditorView.scrollToElement( previewWidget );
|
5944 |
-
}
|
5945 |
-
} );
|
5946 |
-
|
5947 |
-
this.$el.on( 'mouseleave', '.so-widget-wrapper', function () {
|
5948 |
-
this.resetHighlights();
|
5949 |
-
}.bind(this) );
|
5950 |
-
|
5951 |
-
this.listenTo( this.builder, 'open_dialog', function () {
|
5952 |
-
this.resetHighlights();
|
5953 |
-
} );
|
5954 |
-
|
5955 |
-
return this;
|
5956 |
-
},
|
5957 |
-
|
5958 |
-
/**
|
5959 |
-
* Attach the live editor to the document
|
5960 |
-
*/
|
5961 |
-
attach: function () {
|
5962 |
-
this.$el.appendTo( 'body' );
|
5963 |
-
},
|
5964 |
-
|
5965 |
-
/**
|
5966 |
-
* Display the live editor
|
5967 |
-
*/
|
5968 |
-
open: function () {
|
5969 |
-
if ( this.$el.html() === '' ) {
|
5970 |
-
this.render();
|
5971 |
-
}
|
5972 |
-
if ( this.$el.closest( 'body' ).length === 0 ) {
|
5973 |
-
this.attach();
|
5974 |
-
}
|
5975 |
-
|
5976 |
-
// Disable page scrolling
|
5977 |
-
panels.helpers.pageScroll.lock();
|
5978 |
-
|
5979 |
-
if ( this.$el.is( ':visible' ) ) {
|
5980 |
-
return this;
|
5981 |
-
}
|
5982 |
-
|
5983 |
-
// Refresh the preview display
|
5984 |
-
this.$el.show();
|
5985 |
-
this.refreshPreview( this.builder.model.getPanelsData() );
|
5986 |
-
|
5987 |
-
// Move the builder view into the Live Editor
|
5988 |
-
this.originalContainer = this.builder.$el.parent();
|
5989 |
-
this.builder.$el.appendTo( this.$( '.so-live-editor-builder' ) );
|
5990 |
-
this.builder.$( '.so-tool-button.so-live-editor' ).hide();
|
5991 |
-
this.builder.trigger( 'builder_resize' );
|
5992 |
-
|
5993 |
-
|
5994 |
-
if( $('#original_post_status' ).val() === 'auto-draft' && ! this.autoSaved ) {
|
5995 |
-
// The live editor requires a saved draft post, so we'll create one for auto-draft posts
|
5996 |
-
var thisView = this;
|
5997 |
-
|
5998 |
-
if ( wp.autosave ) {
|
5999 |
-
// Set a temporary post title so the autosave triggers properly
|
6000 |
-
if( $('#title[name="post_title"]' ).val() === '' ) {
|
6001 |
-
$('#title[name="post_title"]' ).val( panelsOptions.loc.draft ).trigger('keydown');
|
6002 |
-
}
|
6003 |
-
|
6004 |
-
$( document ).one( 'heartbeat-tick.autosave', function(){
|
6005 |
-
thisView.autoSaved = true;
|
6006 |
-
thisView.refreshPreview( thisView.builder.model.getPanelsData() );
|
6007 |
-
} );
|
6008 |
-
wp.autosave.server.triggerSave();
|
6009 |
-
}
|
6010 |
-
}
|
6011 |
-
},
|
6012 |
-
|
6013 |
-
/**
|
6014 |
-
* Close the Live Editor
|
6015 |
-
*/
|
6016 |
-
close: function () {
|
6017 |
-
if ( ! this.$el.is( ':visible' ) ) {
|
6018 |
-
return this;
|
6019 |
-
}
|
6020 |
-
|
6021 |
-
this.$el.hide();
|
6022 |
-
panels.helpers.pageScroll.unlock();
|
6023 |
-
|
6024 |
-
// Move the builder back to its original container
|
6025 |
-
this.builder.$el.appendTo( this.originalContainer );
|
6026 |
-
this.builder.$( '.so-tool-button.so-live-editor' ).show();
|
6027 |
-
this.builder.trigger( 'builder_resize' );
|
6028 |
-
},
|
6029 |
-
|
6030 |
-
/**
|
6031 |
-
* Close the Live Editor and save the post.
|
6032 |
-
*/
|
6033 |
-
closeAndSave: function(){
|
6034 |
-
this.close();
|
6035 |
-
// Finds the submit input for saving without publishing draft posts.
|
6036 |
-
$('#submitdiv input[type="submit"][name="save"]').click();
|
6037 |
-
},
|
6038 |
-
|
6039 |
-
/**
|
6040 |
-
* Collapse the live editor
|
6041 |
-
*/
|
6042 |
-
collapse: function () {
|
6043 |
-
this.$el.toggleClass( 'so-collapsed' );
|
6044 |
-
},
|
6045 |
-
|
6046 |
-
/**
|
6047 |
-
* Create an overlay in the preview.
|
6048 |
-
*
|
6049 |
-
* @param over
|
6050 |
-
* @return {*|Object} The item we're hovering over.
|
6051 |
-
*/
|
6052 |
-
highlightElement: function ( over ) {
|
6053 |
-
if( ! _.isUndefined( this.resetHighlightTimeout ) ) {
|
6054 |
-
clearTimeout( this.resetHighlightTimeout );
|
6055 |
-
}
|
6056 |
-
|
6057 |
-
// Remove any old overlays
|
6058 |
-
|
6059 |
-
var body = this.previewIframe.contents().find( 'body' );
|
6060 |
-
body.find( '.panel-grid .panel-grid-cell .so-panel' )
|
6061 |
-
.filter( function () {
|
6062 |
-
// Filter to only include non nested
|
6063 |
-
return $( this ).parents( '.so-panel' ).length === 0;
|
6064 |
-
} )
|
6065 |
-
.not( over )
|
6066 |
-
.addClass( 'so-panels-faded' );
|
6067 |
-
|
6068 |
-
over.removeClass( 'so-panels-faded' ).addClass( 'so-panels-highlighted' );
|
6069 |
-
},
|
6070 |
-
|
6071 |
-
/**
|
6072 |
-
* Reset highlights in the live preview
|
6073 |
-
*/
|
6074 |
-
resetHighlights: function() {
|
6075 |
-
|
6076 |
-
var body = this.previewIframe.contents().find( 'body' );
|
6077 |
-
this.resetHighlightTimeout = setTimeout( function(){
|
6078 |
-
body.find( '.panel-grid .panel-grid-cell .so-panel' )
|
6079 |
-
.removeClass( 'so-panels-faded so-panels-highlighted' );
|
6080 |
-
}, 100 );
|
6081 |
-
},
|
6082 |
-
|
6083 |
-
/**
|
6084 |
-
* Scroll over an element in the live preview
|
6085 |
-
* @param over
|
6086 |
-
*/
|
6087 |
-
scrollToElement: function( over ) {
|
6088 |
-
var contentWindow = this.$( '.so-preview iframe' )[0].contentWindow;
|
6089 |
-
contentWindow.liveEditorScrollTo( over );
|
6090 |
-
},
|
6091 |
-
|
6092 |
-
handleRefreshData: function ( newData ) {
|
6093 |
-
if ( ! this.$el.is( ':visible' ) ) {
|
6094 |
-
return this;
|
6095 |
-
}
|
6096 |
-
|
6097 |
-
this.refreshPreview( newData );
|
6098 |
-
},
|
6099 |
-
|
6100 |
-
handleLoadData: function () {
|
6101 |
-
if ( ! this.$el.is( ':visible' ) ) {
|
6102 |
-
return this;
|
6103 |
-
}
|
6104 |
-
|
6105 |
-
this.refreshPreview( this.builder.model.getPanelsData() );
|
6106 |
-
},
|
6107 |
-
|
6108 |
-
/**
|
6109 |
-
* Refresh the Live Editor preview.
|
6110 |
-
* @returns {exports}
|
6111 |
-
*/
|
6112 |
-
refreshPreview: function ( data ) {
|
6113 |
-
var loadTimePrediction = this.loadTimes.length ?
|
6114 |
-
_.reduce( this.loadTimes, function ( memo, num ) {
|
6115 |
-
return memo + num;
|
6116 |
-
}, 0 ) / this.loadTimes.length : 1000;
|
6117 |
-
|
6118 |
-
// Store the last preview iframe position
|
6119 |
-
if( ! _.isNull( this.previewIframe ) ) {
|
6120 |
-
if ( ! this.$( '.so-preview-overlay' ).is( ':visible' ) ) {
|
6121 |
-
this.previewScrollTop = this.previewIframe.contents().scrollTop();
|
6122 |
-
}
|
6123 |
-
}
|
6124 |
-
|
6125 |
-
// Add a loading bar
|
6126 |
-
this.$( '.so-preview-overlay' ).show();
|
6127 |
-
this.$( '.so-preview-overlay .so-loading-bar' )
|
6128 |
-
.clearQueue()
|
6129 |
-
.css( 'width', '0%' )
|
6130 |
-
.animate( {width: '100%'}, parseInt( loadTimePrediction ) + 100 );
|
6131 |
-
|
6132 |
-
|
6133 |
-
this.postToIframe(
|
6134 |
-
{
|
6135 |
-
live_editor_panels_data: JSON.stringify( data ),
|
6136 |
-
live_editor_post_ID: this.builder.config.postId
|
6137 |
-
},
|
6138 |
-
this.previewUrl,
|
6139 |
-
this.$('.so-preview')
|
6140 |
-
);
|
6141 |
-
|
6142 |
-
this.previewIframe.data( 'load-start', new Date().getTime() );
|
6143 |
-
},
|
6144 |
-
|
6145 |
-
/**
|
6146 |
-
* Use a temporary form to post data to an iframe.
|
6147 |
-
*
|
6148 |
-
* @param data The data to send
|
6149 |
-
* @param url The preview URL
|
6150 |
-
* @param target The target iframe
|
6151 |
-
*/
|
6152 |
-
postToIframe: function( data, url, target ){
|
6153 |
-
// Store the old preview
|
6154 |
-
|
6155 |
-
if( ! _.isNull( this.previewIframe ) ) {
|
6156 |
-
this.previewIframe.remove();
|
6157 |
-
}
|
6158 |
-
|
6159 |
-
var iframeId = 'siteorigin-panels-live-preview-' + this.previewFrameId;
|
6160 |
-
|
6161 |
-
// Remove the old preview frame
|
6162 |
-
this.previewIframe = $('<iframe src="javascript:false;" />')
|
6163 |
-
.attr( {
|
6164 |
-
'id' : iframeId,
|
6165 |
-
'name' : iframeId,
|
6166 |
-
} )
|
6167 |
-
.appendTo( target );
|
6168 |
-
|
6169 |
-
this.setupPreviewFrame( this.previewIframe );
|
6170 |
-
|
6171 |
-
// We can use a normal POST form submit
|
6172 |
-
var tempForm = $('<form id="soPostToPreviewFrame" method="post" />')
|
6173 |
-
.attr( {
|
6174 |
-
id: iframeId,
|
6175 |
-
target: this.previewIframe.attr('id'),
|
6176 |
-
action: url
|
6177 |
-
} )
|
6178 |
-
.appendTo( 'body' );
|
6179 |
-
|
6180 |
-
$.each( data, function( name, value ){
|
6181 |
-
$('<input type="hidden" />')
|
6182 |
-
.attr( {
|
6183 |
-
name: name,
|
6184 |
-
value: value
|
6185 |
-
} )
|
6186 |
-
.appendTo( tempForm );
|
6187 |
-
} );
|
6188 |
-
|
6189 |
-
tempForm
|
6190 |
-
.submit()
|
6191 |
-
.remove();
|
6192 |
-
|
6193 |
-
this.previewFrameId++;
|
6194 |
-
|
6195 |
-
return this.previewIframe;
|
6196 |
-
},
|
6197 |
-
|
6198 |
-
/**
|
6199 |
-
* Do all the basic setup for the preview Iframe element
|
6200 |
-
* @param iframe
|
6201 |
-
*/
|
6202 |
-
setupPreviewFrame: function( iframe ){
|
6203 |
-
var thisView = this;
|
6204 |
-
iframe
|
6205 |
-
.data( 'iframeready', false )
|
6206 |
-
.on( 'iframeready', function () {
|
6207 |
-
var $$ = $( this ),
|
6208 |
-
$iframeContents = $$.contents();
|
6209 |
-
|
6210 |
-
if( $$.data( 'iframeready' ) ) {
|
6211 |
-
// Skip this if the iframeready function has already run
|
6212 |
-
return;
|
6213 |
-
}
|
6214 |
-
|
6215 |
-
$$.data( 'iframeready', true );
|
6216 |
-
|
6217 |
-
if ( $$.data( 'load-start' ) !== undefined ) {
|
6218 |
-
thisView.loadTimes.unshift( new Date().getTime() - $$.data( 'load-start' ) );
|
6219 |
-
|
6220 |
-
if ( ! _.isEmpty( thisView.loadTimes ) ) {
|
6221 |
-
thisView.loadTimes = thisView.loadTimes.slice( 0, 4 );
|
6222 |
-
}
|
6223 |
-
}
|
6224 |
-
|
6225 |
-
setTimeout( function(){
|
6226 |
-
// Scroll to the correct position
|
6227 |
-
$iframeContents.scrollTop( thisView.previewScrollTop );
|
6228 |
-
thisView.$( '.so-preview-overlay' ).hide();
|
6229 |
-
}, 100 );
|
6230 |
-
|
6231 |
-
|
6232 |
-
// Lets find all the first level grids. This is to account for the Page Builder layout widget.
|
6233 |
-
var layoutWrapper = $iframeContents.find( '#pl-' + thisView.builder.config.postId );
|
6234 |
-
layoutWrapper.find( '.panel-grid .panel-grid-cell .so-panel' )
|
6235 |
-
.filter( function () {
|
6236 |
-
// Filter to only include non nested
|
6237 |
-
return $( this ).closest( '.panel-layout' ).is( layoutWrapper );
|
6238 |
-
} )
|
6239 |
-
.each( function ( i, el ) {
|
6240 |
-
var $$ = $( el );
|
6241 |
-
var widgetEdit = thisView.$( '.so-live-editor-builder .so-widget-wrapper' ).eq( $$.data( 'index' ) );
|
6242 |
-
widgetEdit.data( 'live-editor-preview-widget', $$ );
|
6243 |
-
|
6244 |
-
$$
|
6245 |
-
.css( {
|
6246 |
-
'cursor': 'pointer'
|
6247 |
-
} )
|
6248 |
-
.mouseenter( function () {
|
6249 |
-
widgetEdit.parent().addClass( 'so-hovered' );
|
6250 |
-
thisView.highlightElement( $$ );
|
6251 |
-
} )
|
6252 |
-
.mouseleave( function () {
|
6253 |
-
widgetEdit.parent().removeClass( 'so-hovered' );
|
6254 |
-
thisView.resetHighlights();
|
6255 |
-
} )
|
6256 |
-
.click( function ( e ) {
|
6257 |
-
e.preventDefault();
|
6258 |
-
// When we click a widget, send that click to the form
|
6259 |
-
widgetEdit.find( '.title h4' ).click();
|
6260 |
-
} );
|
6261 |
-
} );
|
6262 |
-
|
6263 |
-
// Prevent default clicks inside the preview iframe
|
6264 |
-
$iframeContents.find( "a" ).css( {'pointer-events': 'none'} ).click( function ( e ) {
|
6265 |
-
e.preventDefault();
|
6266 |
-
} );
|
6267 |
-
|
6268 |
-
} )
|
6269 |
-
.on( 'load', function(){
|
6270 |
-
var $$ = $( this );
|
6271 |
-
if( ! $$.data( 'iframeready' ) ) {
|
6272 |
-
$$.trigger('iframeready');
|
6273 |
-
}
|
6274 |
-
} );
|
6275 |
-
},
|
6276 |
-
|
6277 |
-
/**
|
6278 |
-
* Return true if the live editor has a valid preview URL.
|
6279 |
-
* @return {boolean}
|
6280 |
-
*/
|
6281 |
-
hasPreviewUrl: function () {
|
6282 |
-
return this.$( 'form.live-editor-form' ).attr( 'action' ) !== '';
|
6283 |
-
},
|
6284 |
-
|
6285 |
-
/**
|
6286 |
-
* Toggle the size of the preview iframe to simulate mobile devices.
|
6287 |
-
* @param e
|
6288 |
-
*/
|
6289 |
-
mobileToggle: function( e ){
|
6290 |
-
var button = $( e.currentTarget );
|
6291 |
-
this.$('.live-editor-mode' ).not( button ).removeClass('so-active');
|
6292 |
-
button.addClass( 'so-active' );
|
6293 |
-
|
6294 |
-
this.$el
|
6295 |
-
.removeClass( 'live-editor-desktop-mode live-editor-tablet-mode live-editor-mobile-mode' )
|
6296 |
-
.addClass( 'live-editor-' + button.data( 'mode' ) + '-mode' );
|
6297 |
-
|
6298 |
-
}
|
6299 |
-
} );
|
6300 |
-
|
6301 |
-
},{}],27:[function(require,module,exports){
|
6302 |
-
var panels = window.panels, $ = jQuery;
|
6303 |
-
|
6304 |
-
module.exports = Backbone.View.extend( {
|
6305 |
-
template: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-builder-row' ).html() ) ),
|
6306 |
-
|
6307 |
-
events: {
|
6308 |
-
'click .so-row-settings': 'editSettingsHandler',
|
6309 |
-
'click .so-row-duplicate': 'duplicateHandler',
|
6310 |
-
'click .so-row-delete': 'confirmedDeleteHandler',
|
6311 |
-
'click .so-row-color': 'rowColorChangeHandler',
|
6312 |
-
},
|
6313 |
-
|
6314 |
-
builder: null,
|
6315 |
-
dialog: null,
|
6316 |
-
|
6317 |
-
/**
|
6318 |
-
* Initialize the row view
|
6319 |
-
*/
|
6320 |
-
initialize: function () {
|
6321 |
-
|
6322 |
-
var rowCells = this.model.get('cells');
|
6323 |
-
this.listenTo(rowCells, 'add', this.handleCellAdd );
|
6324 |
-
this.listenTo(rowCells, 'remove', this.handleCellRemove );
|
6325 |
-
|
6326 |
-
this.listenTo( this.model, 'reweight_cells', this.resize );
|
6327 |
-
this.listenTo( this.model, 'destroy', this.onModelDestroy );
|
6328 |
-
|
6329 |
-
var thisView = this;
|
6330 |
-
rowCells.each( function ( cell ) {
|
6331 |
-
thisView.listenTo( cell.get('widgets'), 'add', thisView.resize );
|
6332 |
-
} );
|
6333 |
-
|
6334 |
-
// When ever a new cell is added, listen to it for new widgets
|
6335 |
-
rowCells.on( 'add', function ( cell ) {
|
6336 |
-
thisView.listenTo( cell.get('widgets'), 'add', thisView.resize );
|
6337 |
-
}, this );
|
6338 |
-
|
6339 |
-
this.listenTo( this.model, 'change:label', this.onLabelChange );
|
6340 |
-
},
|
6341 |
-
|
6342 |
-
/**
|
6343 |
-
* Render the row.
|
6344 |
-
*
|
6345 |
-
* @returns {panels.view.row}
|
6346 |
-
*/
|
6347 |
-
render: function () {
|
6348 |
-
var rowColorLabel = this.model.has( 'color_label' ) ? this.model.get( 'color_label' ) : 1;
|
6349 |
-
var rowLabel = this.model.has( 'label' ) ? this.model.get( 'label' ) : '';
|
6350 |
-
this.setElement( this.template( { rowColorLabel: rowColorLabel, rowLabel: rowLabel } ) );
|
6351 |
-
this.$el.data( 'view', this );
|
6352 |
-
|
6353 |
-
// Create views for the cells in this row
|
6354 |
-
var thisView = this;
|
6355 |
-
this.model.get('cells').each( function ( cell ) {
|
6356 |
-
var cellView = new panels.view.cell( {
|
6357 |
-
model: cell
|
6358 |
-
} );
|
6359 |
-
cellView.row = thisView;
|
6360 |
-
cellView.render();
|
6361 |
-
cellView.$el.appendTo( thisView.$( '.so-cells' ) );
|
6362 |
-
} );
|
6363 |
-
|
6364 |
-
// Remove any unsupported actions
|
6365 |
-
if( ! this.builder.supports( 'rowAction' ) ) {
|
6366 |
-
this.$('.so-row-toolbar .so-dropdown-wrapper' ).remove();
|
6367 |
-
this.$el.addClass('so-row-no-actions');
|
6368 |
-
}
|
6369 |
-
else {
|
6370 |
-
if( ! this.builder.supports( 'editRow' ) ) {
|
6371 |
-
this.$('.so-row-toolbar .so-dropdown-links-wrapper .so-row-settings' ).parent().remove();
|
6372 |
-
this.$el.addClass('so-row-no-edit');
|
6373 |
-
}
|
6374 |
-
if( ! this.builder.supports( 'addRow' ) ) {
|
6375 |
-
this.$('.so-row-toolbar .so-dropdown-links-wrapper .so-row-duplicate' ).parent().remove();
|
6376 |
-
this.$el.addClass('so-row-no-duplicate');
|
6377 |
-
}
|
6378 |
-
if( ! this.builder.supports( 'deleteRow' ) ) {
|
6379 |
-
this.$('.so-row-toolbar .so-dropdown-links-wrapper .so-row-delete' ).parent().remove();
|
6380 |
-
this.$el.addClass('so-row-no-delete');
|
6381 |
-
}
|
6382 |
-
}
|
6383 |
-
if( ! this.builder.supports( 'moveRow' ) ) {
|
6384 |
-
this.$('.so-row-toolbar .so-row-move' ).remove();
|
6385 |
-
this.$el.addClass('so-row-no-move');
|
6386 |
-
}
|
6387 |
-
if( !$.trim( this.$('.so-row-toolbar').html() ).length ) {
|
6388 |
-
this.$('.so-row-toolbar' ).remove();
|
6389 |
-
}
|
6390 |
-
|
6391 |
-
// Resize the rows when ever the widget sortable moves
|
6392 |
-
this.listenTo( this.builder, 'widget_sortable_move', this.resize );
|
6393 |
-
this.listenTo( this.builder, 'builder_resize', this.resize );
|
6394 |
-
|
6395 |
-
this.resize();
|
6396 |
-
|
6397 |
-
return this;
|
6398 |
-
},
|
6399 |
-
|
6400 |
-
/**
|
6401 |
-
* Give a visual indication of the creation of this row
|
6402 |
-
*/
|
6403 |
-
visualCreate: function () {
|
6404 |
-
this.$el.hide().fadeIn( 'fast' );
|
6405 |
-
},
|
6406 |
-
|
6407 |
-
/**
|
6408 |
-
* Visually resize the row so that all cell heights are the same and the widths so that they balance to 100%
|
6409 |
-
*
|
6410 |
-
* @param e
|
6411 |
-
*/
|
6412 |
-
resize: function ( e ) {
|
6413 |
-
// Don't resize this
|
6414 |
-
if ( ! this.$el.is( ':visible' ) ) {
|
6415 |
-
return;
|
6416 |
-
}
|
6417 |
-
|
6418 |
-
// Reset everything to have an automatic height
|
6419 |
-
this.$( '.so-cells .cell-wrapper' ).css( 'min-height', 0 );
|
6420 |
-
this.$( '.so-cells .resize-handle' ).css( 'height', 0 );
|
6421 |
-
|
6422 |
-
// We'll tie the values to the row view, to prevent issue with values going to different rows
|
6423 |
-
var height = 0;
|
6424 |
-
this.$( '.so-cells .cell' ).each( function () {
|
6425 |
-
height = Math.max(
|
6426 |
-
height,
|
6427 |
-
$( this ).height()
|
6428 |
-
);
|
6429 |
-
|
6430 |
-
$( this ).css(
|
6431 |
-
'width',
|
6432 |
-
( $( this ).data( 'view' ).model.get( 'weight' ) * 100) + "%"
|
6433 |
-
);
|
6434 |
-
} );
|
6435 |
-
|
6436 |
-
// Resize all the grids and cell wrappers
|
6437 |
-
this.$( '.so-cells .cell-wrapper' ).css( 'min-height', Math.max( height, 63 ) );
|
6438 |
-
this.$( '.so-cells .resize-handle' ).css( 'height', this.$( '.so-cells .cell-wrapper' ).outerHeight() );
|
6439 |
-
},
|
6440 |
-
|
6441 |
-
/**
|
6442 |
-
* Remove the view from the dom.
|
6443 |
-
*/
|
6444 |
-
onModelDestroy: function () {
|
6445 |
-
this.remove();
|
6446 |
-
},
|
6447 |
-
|
6448 |
-
/**
|
6449 |
-
* Fade out the view and destroy the model
|
6450 |
-
*/
|
6451 |
-
visualDestroyModel: function () {
|
6452 |
-
this.builder.addHistoryEntry( 'row_deleted' );
|
6453 |
-
var thisView = this;
|
6454 |
-
this.$el.fadeOut( 'normal', function () {
|
6455 |
-
thisView.model.destroy();
|
6456 |
-
thisView.builder.model.refreshPanelsData();
|
6457 |
-
} );
|
6458 |
-
},
|
6459 |
-
|
6460 |
-
onLabelChange: function( model, text ) {
|
6461 |
-
if ( this.$('.so-row-label').length == 0 ) {
|
6462 |
-
this.$( '.so-row-toolbar' ).prepend( '<h3 class="so-row-label">' + text + '</h3>' );
|
6463 |
-
} else {
|
6464 |
-
this.$('.so-row-label').text( text );
|
6465 |
-
}
|
6466 |
-
},
|
6467 |
-
|
6468 |
-
/**
|
6469 |
-
* Duplicate this row.
|
6470 |
-
*
|
6471 |
-
* @return {boolean}
|
6472 |
-
*/
|
6473 |
-
duplicateHandler: function () {
|
6474 |
-
this.builder.addHistoryEntry( 'row_duplicated' );
|
6475 |
-
|
6476 |
-
var duplicateRow = this.model.clone( this.builder.model );
|
6477 |
-
|
6478 |
-
this.builder.model.get('rows').add( duplicateRow, {
|
6479 |
-
at: this.builder.model.get('rows').indexOf( this.model ) + 1
|
6480 |
-
} );
|
6481 |
-
|
6482 |
-
this.builder.model.refreshPanelsData();
|
6483 |
-
},
|
6484 |
-
|
6485 |
-
/**
|
6486 |
-
* Copy the row to a localStorage
|
6487 |
-
*/
|
6488 |
-
copyHandler: function(){
|
6489 |
-
panels.helpers.clipboard.setModel( this.model );
|
6490 |
-
},
|
6491 |
-
|
6492 |
-
/**
|
6493 |
-
* Create a new row and insert it
|
6494 |
-
*/
|
6495 |
-
pasteHandler: function(){
|
6496 |
-
var pastedModel = panels.helpers.clipboard.getModel( 'row-model' );
|
6497 |
-
|
6498 |
-
if( ! _.isEmpty( pastedModel ) && pastedModel instanceof panels.model.row ) {
|
6499 |
-
this.builder.addHistoryEntry( 'row_pasted' );
|
6500 |
-
pastedModel.builder = this.builder.model;
|
6501 |
-
this.builder.model.get('rows').add( pastedModel, {
|
6502 |
-
at: this.builder.model.get('rows').indexOf( this.model ) + 1
|
6503 |
-
} );
|
6504 |
-
this.builder.model.refreshPanelsData();
|
6505 |
-
}
|
6506 |
-
},
|
6507 |
-
|
6508 |
-
/**
|
6509 |
-
* Handles deleting the row with a confirmation.
|
6510 |
-
*/
|
6511 |
-
confirmedDeleteHandler: function ( e ) {
|
6512 |
-
var $$ = $( e.target );
|
6513 |
-
|
6514 |
-
// The user clicked on the dashicon
|
6515 |
-
if ( $$.hasClass( 'dashicons' ) ) {
|
6516 |
-
$$ = $$.parent();
|
6517 |
-
}
|
6518 |
-
|
6519 |
-
if ( $$.hasClass( 'so-confirmed' ) ) {
|
6520 |
-
this.visualDestroyModel();
|
6521 |
-
} else {
|
6522 |
-
var originalText = $$.html();
|
6523 |
-
|
6524 |
-
$$.addClass( 'so-confirmed' ).html(
|
6525 |
-
'<span class="dashicons dashicons-yes"></span>' + panelsOptions.loc.dropdown_confirm
|
6526 |
-
);
|
6527 |
-
|
6528 |
-
setTimeout( function () {
|
6529 |
-
$$.removeClass( 'so-confirmed' ).html( originalText );
|
6530 |
-
}, 2500 );
|
6531 |
-
}
|
6532 |
-
},
|
6533 |
-
|
6534 |
-
/**
|
6535 |
-
* Handle displaying the settings dialog
|
6536 |
-
*/
|
6537 |
-
editSettingsHandler: function () {
|
6538 |
-
if ( ! this.builder.supports( 'editRow' ) ) {
|
6539 |
-
return;
|
6540 |
-
}
|
6541 |
-
// Lets open up an instance of the settings dialog
|
6542 |
-
if ( this.dialog === null ) {
|
6543 |
-
// Create the dialog
|
6544 |
-
this.dialog = new panels.dialog.row();
|
6545 |
-
this.dialog.setBuilder( this.builder ).setRowModel( this.model );
|
6546 |
-
this.dialog.rowView = this;
|
6547 |
-
}
|
6548 |
-
|
6549 |
-
this.dialog.openDialog();
|
6550 |
-
|
6551 |
-
return this;
|
6552 |
-
},
|
6553 |
-
|
6554 |
-
/**
|
6555 |
-
* Handle deleting this entire row.
|
6556 |
-
*/
|
6557 |
-
deleteHandler: function () {
|
6558 |
-
this.model.destroy();
|
6559 |
-
return this;
|
6560 |
-
},
|
6561 |
-
|
6562 |
-
/**
|
6563 |
-
* Change the row background color.
|
6564 |
-
*/
|
6565 |
-
rowColorChangeHandler: function ( event ) {
|
6566 |
-
this.$( '.so-row-color' ).removeClass( 'so-row-color-selected' );
|
6567 |
-
var clickedColorElem = $( event.target );
|
6568 |
-
var newColorLabel = clickedColorElem.data( 'color-label' );
|
6569 |
-
var oldColorLabel = this.model.has( 'color_label' ) ? this.model.get( 'color_label' ) : 1;
|
6570 |
-
clickedColorElem.addClass( 'so-row-color-selected' );
|
6571 |
-
this.$el.removeClass( 'so-row-color-' + oldColorLabel );
|
6572 |
-
this.$el.addClass( 'so-row-color-' + newColorLabel );
|
6573 |
-
this.model.set( 'color_label', newColorLabel );
|
6574 |
-
},
|
6575 |
-
|
6576 |
-
/**
|
6577 |
-
* Handle a new cell being added to this row view. For now we'll assume the new cell is always last
|
6578 |
-
*/
|
6579 |
-
handleCellAdd: function ( cell ) {
|
6580 |
-
var cellView = new panels.view.cell( {
|
6581 |
-
model: cell
|
6582 |
-
} );
|
6583 |
-
cellView.row = this;
|
6584 |
-
cellView.render();
|
6585 |
-
cellView.$el.appendTo( this.$( '.so-cells' ) );
|
6586 |
-
},
|
6587 |
-
|
6588 |
-
/**
|
6589 |
-
* Handle a cell being removed from this row view
|
6590 |
-
*/
|
6591 |
-
handleCellRemove: function ( cell ) {
|
6592 |
-
// Find the view that ties in to the cell we're removing
|
6593 |
-
this.$( '.so-cells > .cell' ).each( function () {
|
6594 |
-
var view = $( this ).data( 'view' );
|
6595 |
-
if ( _.isUndefined( view ) ) {
|
6596 |
-
return;
|
6597 |
-
}
|
6598 |
-
|
6599 |
-
if ( view.model.cid === cell.cid ) {
|
6600 |
-
// Remove this view
|
6601 |
-
view.remove();
|
6602 |
-
}
|
6603 |
-
} );
|
6604 |
-
},
|
6605 |
-
|
6606 |
-
/**
|
6607 |
-
* Build up the contextual menu for a row
|
6608 |
-
*
|
6609 |
-
* @param e
|
6610 |
-
* @param menu
|
6611 |
-
*/
|
6612 |
-
buildContextualMenu: function ( e, menu ) {
|
6613 |
-
var options = [];
|
6614 |
-
for ( var i = 1; i < 5; i ++ ) {
|
6615 |
-
options.push( {
|
6616 |
-
title: i + ' ' + panelsOptions.loc.contextual.column
|
6617 |
-
} );
|
6618 |
-
}
|
6619 |
-
|
6620 |
-
if( this.builder.supports( 'addRow' ) ) {
|
6621 |
-
menu.addSection(
|
6622 |
-
'add-row',
|
6623 |
-
{
|
6624 |
-
sectionTitle: panelsOptions.loc.contextual.add_row,
|
6625 |
-
search: false
|
6626 |
-
},
|
6627 |
-
options,
|
6628 |
-
function ( c ) {
|
6629 |
-
this.builder.addHistoryEntry( 'row_added' );
|
6630 |
-
|
6631 |
-
var columns = Number( c ) + 1;
|
6632 |
-
var weights = [];
|
6633 |
-
for ( var i = 0; i < columns; i ++ ) {
|
6634 |
-
weights.push( {weight: 100 / columns } );
|
6635 |
-
}
|
6636 |
-
|
6637 |
-
// Create the actual row
|
6638 |
-
var newRow = new panels.model.row( {
|
6639 |
-
collection: this.collection
|
6640 |
-
} );
|
6641 |
-
|
6642 |
-
var cells = new panels.collection.cells(weights);
|
6643 |
-
cells.each(function (cell) {
|
6644 |
-
cell.row = newRow;
|
6645 |
-
});
|
6646 |
-
newRow.setCells(cells);
|
6647 |
-
newRow.builder = this.builder.model;
|
6648 |
-
|
6649 |
-
this.builder.model.get('rows').add( newRow, {
|
6650 |
-
at: this.builder.model.get('rows').indexOf( this.model ) + 1
|
6651 |
-
} );
|
6652 |
-
|
6653 |
-
this.builder.model.refreshPanelsData();
|
6654 |
-
}.bind( this )
|
6655 |
-
);
|
6656 |
-
}
|
6657 |
-
|
6658 |
-
var actions = {};
|
6659 |
-
|
6660 |
-
if( this.builder.supports( 'editRow' ) ) {
|
6661 |
-
actions.edit = { title: panelsOptions.loc.contextual.row_edit };
|
6662 |
-
}
|
6663 |
-
|
6664 |
-
// Copy and paste functions
|
6665 |
-
if ( panels.helpers.clipboard.canCopyPaste() ) {
|
6666 |
-
actions.copy = { title: panelsOptions.loc.contextual.row_copy };
|
6667 |
-
if ( this.builder.supports( 'addRow' ) && panels.helpers.clipboard.isModel( 'row-model' ) ) {
|
6668 |
-
actions.paste = { title: panelsOptions.loc.contextual.row_paste };
|
6669 |
-
}
|
6670 |
-
}
|
6671 |
-
|
6672 |
-
if( this.builder.supports( 'addRow' ) ) {
|
6673 |
-
actions.duplicate = { title: panelsOptions.loc.contextual.row_duplicate };
|
6674 |
-
}
|
6675 |
-
|
6676 |
-
if( this.builder.supports( 'deleteRow' ) ) {
|
6677 |
-
actions.delete = { title: panelsOptions.loc.contextual.row_delete, confirm: true };
|
6678 |
-
}
|
6679 |
-
|
6680 |
-
if( ! _.isEmpty( actions ) ) {
|
6681 |
-
menu.addSection(
|
6682 |
-
'row-actions',
|
6683 |
-
{
|
6684 |
-
sectionTitle: panelsOptions.loc.contextual.row_actions,
|
6685 |
-
search: false,
|
6686 |
-
},
|
6687 |
-
actions,
|
6688 |
-
function ( c ) {
|
6689 |
-
switch ( c ) {
|
6690 |
-
case 'edit':
|
6691 |
-
this.editSettingsHandler();
|
6692 |
-
break;
|
6693 |
-
case 'copy':
|
6694 |
-
this.copyHandler();
|
6695 |
-
break;
|
6696 |
-
case 'paste':
|
6697 |
-
this.pasteHandler();
|
6698 |
-
break;
|
6699 |
-
case 'duplicate':
|
6700 |
-
this.duplicateHandler();
|
6701 |
-
break;
|
6702 |
-
case 'delete':
|
6703 |
-
this.visualDestroyModel();
|
6704 |
-
break;
|
6705 |
-
}
|
6706 |
-
}.bind( this )
|
6707 |
-
);
|
6708 |
-
}
|
6709 |
-
},
|
6710 |
-
} );
|
6711 |
-
|
6712 |
-
},{}],28:[function(require,module,exports){
|
6713 |
-
var panels = window.panels, $ = jQuery;
|
6714 |
-
|
6715 |
-
module.exports = Backbone.View.extend( {
|
6716 |
-
|
6717 |
-
stylesLoaded: false,
|
6718 |
-
|
6719 |
-
initialize: function () {
|
6720 |
-
|
6721 |
-
},
|
6722 |
-
|
6723 |
-
/**
|
6724 |
-
* Render the visual styles object.
|
6725 |
-
*
|
6726 |
-
* @param stylesType
|
6727 |
-
* @param postId
|
6728 |
-
* @param args
|
6729 |
-
*/
|
6730 |
-
render: function ( stylesType, postId, args ) {
|
6731 |
-
if ( _.isUndefined( stylesType ) ) {
|
6732 |
-
return;
|
6733 |
-
}
|
6734 |
-
|
6735 |
-
// Add in the default args
|
6736 |
-
args = _.extend( {
|
6737 |
-
builderType: '',
|
6738 |
-
dialog: null
|
6739 |
-
}, args );
|
6740 |
-
|
6741 |
-
this.$el.addClass( 'so-visual-styles so-' + stylesType + '-styles so-panels-loading' );
|
6742 |
-
|
6743 |
-
var postArgs = {
|
6744 |
-
builderType: args.builderType
|
6745 |
-
};
|
6746 |
-
|
6747 |
-
if ( stylesType === 'cell') {
|
6748 |
-
postArgs.index = args.index;
|
6749 |
-
}
|
6750 |
-
|
6751 |
-
// Load the form
|
6752 |
-
$.post(
|
6753 |
-
panelsOptions.ajaxurl,
|
6754 |
-
{
|
6755 |
-
action: 'so_panels_style_form',
|
6756 |
-
type: stylesType,
|
6757 |
-
style: this.model.get( 'style' ),
|
6758 |
-
args: JSON.stringify( postArgs ),
|
6759 |
-
postId: postId
|
6760 |
-
},
|
6761 |
-
null,
|
6762 |
-
'html'
|
6763 |
-
).done( function ( response ) {
|
6764 |
-
this.$el.html( response );
|
6765 |
-
this.setupFields();
|
6766 |
-
this.stylesLoaded = true;
|
6767 |
-
this.trigger( 'styles_loaded', !_.isEmpty( response ) );
|
6768 |
-
if ( !_.isNull( args.dialog ) ) {
|
6769 |
-
args.dialog.trigger( 'styles_loaded', !_.isEmpty( response ) );
|
6770 |
-
}
|
6771 |
-
}.bind( this ) )
|
6772 |
-
.fail( function ( error ) {
|
6773 |
-
var html;
|
6774 |
-
if ( error && error.responseText ) {
|
6775 |
-
html = error.responseText;
|
6776 |
-
} else {
|
6777 |
-
html = panelsOptions.forms.loadingFailed;
|
6778 |
-
}
|
6779 |
-
|
6780 |
-
this.$el.html( html );
|
6781 |
-
}.bind( this ) )
|
6782 |
-
.always( function () {
|
6783 |
-
this.$el.removeClass( 'so-panels-loading' );
|
6784 |
-
}.bind( this ) );
|
6785 |
-
|
6786 |
-
return this;
|
6787 |
-
},
|
6788 |
-
|
6789 |
-
/**
|
6790 |
-
* Attach the style view to the DOM.
|
6791 |
-
*
|
6792 |
-
* @param wrapper
|
6793 |
-
*/
|
6794 |
-
attach: function ( wrapper ) {
|
6795 |
-
wrapper.append( this.$el );
|
6796 |
-
},
|
6797 |
-
|
6798 |
-
/**
|
6799 |
-
* Detach the styles view from the DOM
|
6800 |
-
*/
|
6801 |
-
detach: function () {
|
6802 |
-
this.$el.detach();
|
6803 |
-
},
|
6804 |
-
|
6805 |
-
/**
|
6806 |
-
* Setup all the fields
|
6807 |
-
*/
|
6808 |
-
setupFields: function () {
|
6809 |
-
|
6810 |
-
// Set up the sections as collapsible
|
6811 |
-
this.$( '.style-section-wrapper' ).each( function () {
|
6812 |
-
var $s = $( this );
|
6813 |
-
|
6814 |
-
$s.find( '.style-section-head' ).click( function ( e ) {
|
6815 |
-
e.preventDefault();
|
6816 |
-
$s.find( '.style-section-fields' ).slideToggle( 'fast' );
|
6817 |
-
} );
|
6818 |
-
} );
|
6819 |
-
|
6820 |
-
// Set up the color fields
|
6821 |
-
if ( ! _.isUndefined( $.fn.wpColorPicker ) ) {
|
6822 |
-
if ( _.isObject( panelsOptions.wpColorPickerOptions.palettes ) && ! $.isArray( panelsOptions.wpColorPickerOptions.palettes ) ) {
|
6823 |
-
panelsOptions.wpColorPickerOptions.palettes = $.map( panelsOptions.wpColorPickerOptions.palettes, function ( el ) {
|
6824 |
-
return el;
|
6825 |
-
} );
|
6826 |
-
}
|
6827 |
-
this.$( '.so-wp-color-field' ).wpColorPicker( panelsOptions.wpColorPickerOptions );
|
6828 |
-
}
|
6829 |
-
|
6830 |
-
// Set up the image select fields
|
6831 |
-
this.$( '.style-field-image' ).each( function () {
|
6832 |
-
var frame = null;
|
6833 |
-
var $s = $( this );
|
6834 |
-
|
6835 |
-
$s.find( '.so-image-selector' ).click( function ( e ) {
|
6836 |
-
e.preventDefault();
|
6837 |
-
|
6838 |
-
if ( frame === null ) {
|
6839 |
-
// Create the media frame.
|
6840 |
-
frame = wp.media( {
|
6841 |
-
// Set the title of the modal.
|
6842 |
-
title: 'choose',
|
6843 |
-
|
6844 |
-
// Tell the modal to show only images.
|
6845 |
-
library: {
|
6846 |
-
type: 'image'
|
6847 |
-
},
|
6848 |
-
|
6849 |
-
// Customize the submit button.
|
6850 |
-
button: {
|
6851 |
-
// Set the text of the button.
|
6852 |
-
text: 'Done',
|
6853 |
-
close: true
|
6854 |
-
}
|
6855 |
-
} );
|
6856 |
-
|
6857 |
-
frame.on( 'select', function () {
|
6858 |
-
var attachment = frame.state().get( 'selection' ).first().attributes;
|
6859 |
-
|
6860 |
-
var url = attachment.url;
|
6861 |
-
if ( ! _.isUndefined( attachment.sizes ) ) {
|
6862 |
-
try {
|
6863 |
-
url = attachment.sizes.thumbnail.url;
|
6864 |
-
}
|
6865 |
-
catch ( e ) {
|
6866 |
-
// We'll use the full image instead
|
6867 |
-
url = attachment.sizes.full.url;
|
6868 |
-
}
|
6869 |
-
}
|
6870 |
-
$s.find( '.current-image' ).css( 'background-image', 'url(' + url + ')' );
|
6871 |
-
|
6872 |
-
// Store the ID
|
6873 |
-
$s.find( '.so-image-selector > input' ).val( attachment.id );
|
6874 |
-
|
6875 |
-
$s.find( '.remove-image' ).removeClass( 'hidden' );
|
6876 |
-
} );
|
6877 |
-
}
|
6878 |
-
|
6879 |
-
frame.open();
|
6880 |
-
|
6881 |
-
} );
|
6882 |
-
|
6883 |
-
// Handle clicking on remove
|
6884 |
-
$s.find( '.remove-image' ).click( function ( e ) {
|
6885 |
-
e.preventDefault();
|
6886 |
-
$s.find( '.current-image' ).css( 'background-image', 'none' );
|
6887 |
-
$s.find( '.so-image-selector > input' ).val( '' );
|
6888 |
-
$s.find( '.remove-image' ).addClass( 'hidden' );
|
6889 |
-
} );
|
6890 |
-
} );
|
6891 |
-
|
6892 |
-
// Set up all the measurement fields
|
6893 |
-
this.$( '.style-field-measurement' ).each( function () {
|
6894 |
-
var $$ = $( this );
|
6895 |
-
|
6896 |
-
var text = $$.find( 'input[type="text"]' );
|
6897 |
-
var unit = $$.find( 'select' );
|
6898 |
-
var hidden = $$.find( 'input[type="hidden"]' );
|
6899 |
-
|
6900 |
-
text.focus( function(){
|
6901 |
-
$(this).select();
|
6902 |
-
} );
|
6903 |
-
|
6904 |
-
/**
|
6905 |
-
* Load value into the visible input fields.
|
6906 |
-
* @param value
|
6907 |
-
*/
|
6908 |
-
var loadValue = function( value ) {
|
6909 |
-
if( value === '' ) {
|
6910 |
-
return;
|
6911 |
-
}
|
6912 |
-
|
6913 |
-
var re = /(?:([0-9\.,\-]+)(.*))+/;
|
6914 |
-
var valueList = hidden.val().split( ' ' );
|
6915 |
-
var valueListValue = [];
|
6916 |
-
for ( var i in valueList ) {
|
6917 |
-
var match = re.exec( valueList[i] );
|
6918 |
-
if ( ! _.isNull( match ) && ! _.isUndefined( match[1] ) && ! _.isUndefined( match[2] ) ) {
|
6919 |
-
valueListValue.push( match[1] );
|
6920 |
-
unit.val( match[2] );
|
6921 |
-
}
|
6922 |
-
}
|
6923 |
-
|
6924 |
-
if( text.length === 1 ) {
|
6925 |
-
// This is a single input text field
|
6926 |
-
text.val( valueListValue.join( ' ' ) );
|
6927 |
-
}
|
6928 |
-
else {
|
6929 |
-
// We're dealing with a multiple field
|
6930 |
-
if( valueListValue.length === 1 ) {
|
6931 |
-
valueListValue = [ valueListValue[0], valueListValue[0], valueListValue[0], valueListValue[0] ];
|
6932 |
-
}
|
6933 |
-
else if( valueListValue.length === 2 ) {
|
6934 |
-
valueListValue = [ valueListValue[0], valueListValue[1], valueListValue[0], valueListValue[1] ];
|
6935 |
-
}
|
6936 |
-
else if( valueListValue.length === 3 ) {
|
6937 |
-
valueListValue = [ valueListValue[0], valueListValue[1], valueListValue[2], valueListValue[1] ];
|
6938 |
-
}
|
6939 |
-
|
6940 |
-
// Store this in the visible fields
|
6941 |
-
text.each( function( i, el ) {
|
6942 |
-
$( el ).val( valueListValue[i] );
|
6943 |
-
} );
|
6944 |
-
}
|
6945 |
-
};
|
6946 |
-
loadValue( hidden.val() );
|
6947 |
-
|
6948 |
-
/**
|
6949 |
-
* Set value of the hidden field based on inputs
|
6950 |
-
*/
|
6951 |
-
var setValue = function( e ){
|
6952 |
-
var i;
|
6953 |
-
|
6954 |
-
if( text.length === 1 ) {
|
6955 |
-
// We're dealing with a single measurement
|
6956 |
-
var fullString = text
|
6957 |
-
.val()
|
6958 |
-
.split( ' ' )
|
6959 |
-
.filter( function ( value ) {
|
6960 |
-
return value !== '';
|
6961 |
-
} )
|
6962 |
-
.map( function ( value ) {
|
6963 |
-
return value + unit.val();
|
6964 |
-
} )
|
6965 |
-
.join( ' ' );
|
6966 |
-
hidden.val( fullString );
|
6967 |
-
}
|
6968 |
-
else {
|
6969 |
-
var target = $( e.target ),
|
6970 |
-
valueList = [],
|
6971 |
-
emptyIndex = [],
|
6972 |
-
fullIndex = [];
|
6973 |
-
|
6974 |
-
text.each( function( i, el ) {
|
6975 |
-
var value = $( el ).val( ) !== '' ? parseFloat( $( el ).val( ) ) : null;
|
6976 |
-
valueList.push( value );
|
6977 |
-
|
6978 |
-
if( value === null ) {
|
6979 |
-
emptyIndex.push( i );
|
6980 |
-
}
|
6981 |
-
else {
|
6982 |
-
fullIndex.push( i );
|
6983 |
-
}
|
6984 |
-
} );
|
6985 |
-
|
6986 |
-
if( emptyIndex.length === 3 && fullIndex[0] === text.index( target ) ) {
|
6987 |
-
text.val( target.val() );
|
6988 |
-
valueList = [ target.val(), target.val(), target.val(), target.val() ];
|
6989 |
-
}
|
6990 |
-
|
6991 |
-
if( JSON.stringify( valueList ) === JSON.stringify( [ null, null, null, null ] ) ) {
|
6992 |
-
hidden.val('');
|
6993 |
-
}
|
6994 |
-
else {
|
6995 |
-
hidden.val( valueList.map( function( k ){
|
6996 |
-
return ( k === null ? 0 : k ) + unit.val();
|
6997 |
-
} ).join( ' ' ) );
|
6998 |
-
}
|
6999 |
-
}
|
7000 |
-
};
|
7001 |
-
|
7002 |
-
// Set the value when ever anything changes
|
7003 |
-
text.change( setValue );
|
7004 |
-
unit.change( setValue );
|
7005 |
-
} );
|
7006 |
-
}
|
7007 |
-
|
7008 |
-
} );
|
7009 |
-
|
7010 |
-
},{}],29:[function(require,module,exports){
|
7011 |
-
var panels = window.panels, $ = jQuery;
|
7012 |
-
|
7013 |
-
module.exports = Backbone.View.extend( {
|
7014 |
-
template: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-builder-widget' ).html() ) ),
|
7015 |
-
|
7016 |
-
// The cell view that this widget belongs to
|
7017 |
-
cell: null,
|
7018 |
-
|
7019 |
-
// The edit dialog
|
7020 |
-
dialog: null,
|
7021 |
-
|
7022 |
-
events: {
|
7023 |
-
'click .widget-edit': 'editHandler',
|
7024 |
-
'click .title h4': 'editHandler',
|
7025 |
-
'click .actions .widget-duplicate': 'duplicateHandler',
|
7026 |
-
'click .actions .widget-delete': 'deleteHandler'
|
7027 |
-
},
|
7028 |
-
|
7029 |
-
/**
|
7030 |
-
* Initialize the widget
|
7031 |
-
*/
|
7032 |
-
initialize: function () {
|
7033 |
-
this.listenTo(this.model, 'destroy', this.onModelDestroy);
|
7034 |
-
this.listenTo(this.model, 'change:values', this.onModelChange);
|
7035 |
-
this.listenTo(this.model, 'change:label', this.onLabelChange);
|
7036 |
-
},
|
7037 |
-
|
7038 |
-
/**
|
7039 |
-
* Render the widget
|
7040 |
-
*/
|
7041 |
-
render: function ( options ) {
|
7042 |
-
options = _.extend( {'loadForm': false}, options );
|
7043 |
-
|
7044 |
-
this.setElement( this.template( {
|
7045 |
-
title: this.model.getWidgetField( 'title' ),
|
7046 |
-
description: this.model.getTitle(),
|
7047 |
-
widget_class: this.model.attributes.class
|
7048 |
-
} ) );
|
7049 |
-
|
7050 |
-
this.$el.data( 'view', this );
|
7051 |
-
|
7052 |
-
// Remove any unsupported actions
|
7053 |
-
if( ! this.cell.row.builder.supports( 'editWidget' ) || this.model.get( 'read_only' ) ) {
|
7054 |
-
this.$( '.actions .widget-edit' ).remove();
|
7055 |
-
this.$el.addClass('so-widget-no-edit');
|
7056 |
-
}
|
7057 |
-
if( ! this.cell.row.builder.supports( 'addWidget' ) ) {
|
7058 |
-
this.$( '.actions .widget-duplicate' ).remove();
|
7059 |
-
this.$el.addClass('so-widget-no-duplicate');
|
7060 |
-
}
|
7061 |
-
if( ! this.cell.row.builder.supports( 'deleteWidget' ) ) {
|
7062 |
-
this.$( '.actions .widget-delete' ).remove();
|
7063 |
-
this.$el.addClass('so-widget-no-delete');
|
7064 |
-
}
|
7065 |
-
if( ! this.cell.row.builder.supports( 'moveWidget' ) ) {
|
7066 |
-
this.$el.addClass('so-widget-no-move');
|
7067 |
-
}
|
7068 |
-
if( !$.trim( this.$('.actions').html() ).length ) {
|
7069 |
-
this.$( '.actions' ).remove();
|
7070 |
-
}
|
7071 |
-
|
7072 |
-
if( this.model.get( 'read_only' ) ) {
|
7073 |
-
this.$el.addClass('so-widget-read-only');
|
7074 |
-
}
|
7075 |
-
|
7076 |
-
if ( _.size( this.model.get( 'values' ) ) === 0 || options.loadForm ) {
|
7077 |
-
// If this widget doesn't have a value, create a form and save it
|
7078 |
-
var dialog = this.getEditDialog();
|
7079 |
-
|
7080 |
-
// Save the widget as soon as the form is loaded
|
7081 |
-
dialog.once( 'form_loaded', dialog.saveWidget, dialog );
|
7082 |
-
|
7083 |
-
// Setup the dialog to load the form
|
7084 |
-
dialog.setupDialog();
|
7085 |
-
}
|
7086 |
-
|
7087 |
-
// Add the global builder listeners
|
7088 |
-
this.listenTo(this.cell.row.builder, 'after_user_adds_widget', this.afterUserAddsWidgetHandler);
|
7089 |
-
|
7090 |
-
return this;
|
7091 |
-
},
|
7092 |
-
|
7093 |
-
/**
|
7094 |
-
* Display an animation that implies creation using a visual animation
|
7095 |
-
*/
|
7096 |
-
visualCreate: function () {
|
7097 |
-
this.$el.hide().fadeIn( 'fast' );
|
7098 |
-
},
|
7099 |
-
|
7100 |
-
/**
|
7101 |
-
* Get the dialog view of the form that edits this widget
|
7102 |
-
*
|
7103 |
-
* @returns {null}
|
7104 |
-
*/
|
7105 |
-
getEditDialog: function () {
|
7106 |
-
if ( this.dialog === null ) {
|
7107 |
-
this.dialog = new panels.dialog.widget( {
|
7108 |
-
model: this.model
|
7109 |
-
} );
|
7110 |
-
this.dialog.setBuilder( this.cell.row.builder );
|
7111 |
-
|
7112 |
-
// Store the widget view
|
7113 |
-
this.dialog.widgetView = this;
|
7114 |
-
}
|
7115 |
-
return this.dialog;
|
7116 |
-
},
|
7117 |
-
|
7118 |
-
/**
|
7119 |
-
* Handle clicking on edit widget.
|
7120 |
-
*/
|
7121 |
-
editHandler: function () {
|
7122 |
-
// Create a new dialog for editing this
|
7123 |
-
if ( ! this.cell.row.builder.supports( 'editWidget' ) || this.model.get( 'read_only' ) ) {
|
7124 |
-
return this;
|
7125 |
-
}
|
7126 |
-
|
7127 |
-
this.getEditDialog().openDialog();
|
7128 |
-
return this;
|
7129 |
-
},
|
7130 |
-
|
7131 |
-
/**
|
7132 |
-
* Handle clicking on duplicate.
|
7133 |
-
*
|
7134 |
-
* @returns {boolean}
|
7135 |
-
*/
|
7136 |
-
duplicateHandler: function () {
|
7137 |
-
// Add the history entry
|
7138 |
-
this.cell.row.builder.addHistoryEntry( 'widget_duplicated' );
|
7139 |
-
|
7140 |
-
// Create the new widget and connect it to the widget collection for the current row
|
7141 |
-
var newWidget = this.model.clone( this.model.cell );
|
7142 |
-
|
7143 |
-
this.cell.model.get('widgets').add( newWidget, {
|
7144 |
-
// Add this after the existing model
|
7145 |
-
at: this.model.collection.indexOf( this.model ) + 1
|
7146 |
-
} );
|
7147 |
-
|
7148 |
-
this.cell.row.builder.model.refreshPanelsData();
|
7149 |
-
return this;
|
7150 |
-
},
|
7151 |
-
|
7152 |
-
/**
|
7153 |
-
* Copy the row to a cookie based clipboard
|
7154 |
-
*/
|
7155 |
-
copyHandler: function(){
|
7156 |
-
panels.helpers.clipboard.setModel( this.model );
|
7157 |
-
},
|
7158 |
-
|
7159 |
-
/**
|
7160 |
-
* Handle clicking on delete.
|
7161 |
-
*
|
7162 |
-
* @returns {boolean}
|
7163 |
-
*/
|
7164 |
-
deleteHandler: function () {
|
7165 |
-
this.visualDestroyModel();
|
7166 |
-
return this;
|
7167 |
-
},
|
7168 |
-
|
7169 |
-
onModelChange: function () {
|
7170 |
-
// Update the description when ever the model changes
|
7171 |
-
this.$( '.description' ).html( this.model.getTitle() );
|
7172 |
-
},
|
7173 |
-
|
7174 |
-
onLabelChange: function( model ) {
|
7175 |
-
this.$( '.title > h4' ).text( model.getWidgetField( 'title' ) );
|
7176 |
-
},
|
7177 |
-
|
7178 |
-
/**
|
7179 |
-
* When the model is destroyed, fade it out
|
7180 |
-
*/
|
7181 |
-
onModelDestroy: function () {
|
7182 |
-
this.remove();
|
7183 |
-
},
|
7184 |
-
|
7185 |
-
/**
|
7186 |
-
* Visually destroy a model
|
7187 |
-
*/
|
7188 |
-
visualDestroyModel: function () {
|
7189 |
-
// Add the history entry
|
7190 |
-
this.cell.row.builder.addHistoryEntry( 'widget_deleted' );
|
7191 |
-
|
7192 |
-
this.$el.fadeOut( 'fast', function () {
|
7193 |
-
this.cell.row.resize();
|
7194 |
-
this.model.destroy();
|
7195 |
-
this.cell.row.builder.model.refreshPanelsData();
|
7196 |
-
this.remove();
|
7197 |
-
}.bind(this) );
|
7198 |
-
|
7199 |
-
return this;
|
7200 |
-
},
|
7201 |
-
|
7202 |
-
/**
|
7203 |
-
* Build up the contextual menu for a widget
|
7204 |
-
*
|
7205 |
-
* @param e
|
7206 |
-
* @param menu
|
7207 |
-
*/
|
7208 |
-
buildContextualMenu: function ( e, menu ) {
|
7209 |
-
if( this.cell.row.builder.supports( 'addWidget' ) ) {
|
7210 |
-
menu.addSection(
|
7211 |
-
'add-widget-below',
|
7212 |
-
{
|
7213 |
-
sectionTitle: panelsOptions.loc.contextual.add_widget_below,
|
7214 |
-
searchPlaceholder: panelsOptions.loc.contextual.search_widgets,
|
7215 |
-
defaultDisplay: panelsOptions.contextual.default_widgets
|
7216 |
-
},
|
7217 |
-
panelsOptions.widgets,
|
7218 |
-
function ( c ) {
|
7219 |
-
this.cell.row.builder.trigger('before_user_adds_widget');
|
7220 |
-
this.cell.row.builder.addHistoryEntry( 'widget_added' );
|
7221 |
-
|
7222 |
-
var widget = new panels.model.widget( {
|
7223 |
-
class: c
|
7224 |
-
} );
|
7225 |
-
widget.cell = this.cell.model;
|
7226 |
-
|
7227 |
-
// Insert the new widget below
|
7228 |
-
this.cell.model.get('widgets').add( widget, {
|
7229 |
-
// Add this after the existing model
|
7230 |
-
at: this.model.collection.indexOf( this.model ) + 1
|
7231 |
-
} );
|
7232 |
-
|
7233 |
-
this.cell.row.builder.model.refreshPanelsData();
|
7234 |
-
|
7235 |
-
this.cell.row.builder.trigger('after_user_adds_widget', widget);
|
7236 |
-
}.bind( this )
|
7237 |
-
);
|
7238 |
-
}
|
7239 |
-
|
7240 |
-
var actions = {};
|
7241 |
-
|
7242 |
-
if( this.cell.row.builder.supports( 'editWidget' ) && ! this.model.get( 'read_only' ) ) {
|
7243 |
-
actions.edit = { title: panelsOptions.loc.contextual.widget_edit };
|
7244 |
-
}
|
7245 |
-
|
7246 |
-
// Copy and paste functions
|
7247 |
-
if ( panels.helpers.clipboard.canCopyPaste() ) {
|
7248 |
-
actions.copy = {title: panelsOptions.loc.contextual.widget_copy};
|
7249 |
-
}
|
7250 |
-
|
7251 |
-
if( this.cell.row.builder.supports( 'addWidget' ) ) {
|
7252 |
-
actions.duplicate = { title: panelsOptions.loc.contextual.widget_duplicate };
|
7253 |
-
}
|
7254 |
-
|
7255 |
-
if( this.cell.row.builder.supports( 'deleteWidget' ) ) {
|
7256 |
-
actions.delete = { title: panelsOptions.loc.contextual.widget_delete, confirm: true };
|
7257 |
-
}
|
7258 |
-
|
7259 |
-
if( ! _.isEmpty( actions ) ) {
|
7260 |
-
menu.addSection(
|
7261 |
-
'widget-actions',
|
7262 |
-
{
|
7263 |
-
sectionTitle: panelsOptions.loc.contextual.widget_actions,
|
7264 |
-
search: false,
|
7265 |
-
},
|
7266 |
-
actions,
|
7267 |
-
function ( c ) {
|
7268 |
-
switch ( c ) {
|
7269 |
-
case 'edit':
|
7270 |
-
this.editHandler();
|
7271 |
-
break;
|
7272 |
-
case 'copy':
|
7273 |
-
this.copyHandler();
|
7274 |
-
break;
|
7275 |
-
case 'duplicate':
|
7276 |
-
this.duplicateHandler();
|
7277 |
-
break;
|
7278 |
-
case 'delete':
|
7279 |
-
this.visualDestroyModel();
|
7280 |
-
break;
|
7281 |
-
}
|
7282 |
-
}.bind( this )
|
7283 |
-
);
|
7284 |
-
}
|
7285 |
-
|
7286 |
-
// Lets also add the contextual menu for the entire row
|
7287 |
-
this.cell.buildContextualMenu( e, menu );
|
7288 |
-
},
|
7289 |
-
|
7290 |
-
/**
|
7291 |
-
* Handler for any action after the user adds a new widget.
|
7292 |
-
* @param widget
|
7293 |
-
*/
|
7294 |
-
afterUserAddsWidgetHandler: function( widget ) {
|
7295 |
-
if( this.model === widget && panelsOptions.instant_open ) {
|
7296 |
-
setTimeout(this.editHandler.bind(this), 350);
|
7297 |
-
}
|
7298 |
-
}
|
7299 |
-
|
7300 |
-
} );
|
7301 |
-
|
7302 |
Â
},{}],30:[function(require,module,exports){
|
7303 |
Â
var $ = jQuery;
|
7304 |
Â
|
@@ -7405,47 +7407,47 @@ var mediaWidget = {
|
|
7405 |
Â
module.exports = mediaWidget;
|
7406 |
Â
|
7407 |
Â
},{}],33:[function(require,module,exports){
|
7408 |
-
var $ = jQuery;
|
7409 |
-
|
7410 |
-
var textWidget = {
|
7411 |
-
addWidget: function( idBase, widgetContainer, widgetId ) {
|
7412 |
-
var component = wp.textWidgets;
|
7413 |
-
|
7414 |
-
var options = {};
|
7415 |
-
var visualField = widgetContainer.find( '.visual' );
|
7416 |
-
// 'visual' field and syncContainer were introduced together in 4.8.1
|
7417 |
-
if ( visualField.length > 0 ) {
|
7418 |
-
// If 'visual' field has no value it's a legacy text widget.
|
7419 |
-
if ( ! visualField.val() ) {
|
7420 |
-
return null;
|
7421 |
-
}
|
7422 |
-
|
7423 |
-
var fieldContainer = $( '<div></div>' );
|
7424 |
-
var syncContainer = widgetContainer.find( '.widget-content:first' );
|
7425 |
-
syncContainer.before( fieldContainer );
|
7426 |
-
|
7427 |
-
options = {
|
7428 |
-
el: fieldContainer,
|
7429 |
-
syncContainer: syncContainer,
|
7430 |
-
};
|
7431 |
-
} else {
|
7432 |
-
options = { el: widgetContainer };
|
7433 |
-
}
|
7434 |
-
|
7435 |
-
var widgetControl = new component.TextWidgetControl( options );
|
7436 |
-
var wpEditor = wp.oldEditor ? wp.oldEditor : wp.editor;
|
7437 |
-
if ( wpEditor && wpEditor.hasOwnProperty( 'autop' ) ) {
|
7438 |
-
wp.editor.autop = wpEditor.autop;
|
7439 |
-
wp.editor.removep = wpEditor.removep;
|
7440 |
-
wp.editor.initialize = wpEditor.initialize
|
7441 |
-
}
|
7442 |
-
|
7443 |
-
widgetControl.initializeEditor();
|
7444 |
-
|
7445 |
-
return widgetControl;
|
7446 |
-
}
|
7447 |
-
};
|
7448 |
-
|
7449 |
-
module.exports = textWidget;
|
7450 |
Â
|
7451 |
Â
},{}]},{},[16]);
|
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.openSelectedCellStyles();
|
846 |
+
}, this);
|
847 |
Â
|
848 |
+
// This is the default row layout
|
849 |
+
this.row = {
|
850 |
+
cells: new panels.collection.cells([{weight: 0.5}, {weight: 0.5}]),
|
851 |
+
style: {}
|
852 |
+
};
|
853 |
+
|
854 |
+
// Refresh panels data after both dialog form components are loaded
|
855 |
+
this.dialogFormsLoaded = 0;
|
856 |
+
var thisView = this;
|
857 |
+
this.on('form_loaded styles_loaded', function () {
|
858 |
+
this.dialogFormsLoaded++;
|
859 |
+
if (this.dialogFormsLoaded === 2) {
|
860 |
+
thisView.updateModel({
|
861 |
+
refreshArgs: {
|
862 |
+
silent: true
|
863 |
+
}
|
864 |
+
});
|
865 |
+
}
|
866 |
+
});
|
867 |
+
|
868 |
+
this.on('close_dialog', this.closeHandler);
|
869 |
+
|
870 |
+
this.on( 'edit_label', function ( text ) {
|
871 |
+
// If text is set to default values, just clear it.
|
872 |
+
if ( text === panelsOptions.loc.row.add || text === panelsOptions.loc.row.edit ) {
|
873 |
+
text = '';
|
874 |
+
}
|
875 |
+
this.model.set( 'label', text );
|
876 |
+
if ( _.isEmpty( text ) ) {
|
877 |
+
var title = this.dialogType === 'create' ? panelsOptions.loc.row.add : panelsOptions.loc.row.edit;
|
878 |
+
this.$( '.so-title').text( title );
|
879 |
+
}
|
880 |
+
}.bind( this ) );
|
881 |
+
},
|
882 |
Â
|
883 |
Â
/**
|
Â
|
|
884 |
Â
*
|
885 |
+
* @param dialogType Either "edit" or "create"
|
Â
|
|
Â
|
|
886 |
Â
*/
|
887 |
+
setRowDialogType: function (dialogType) {
|
888 |
+
this.dialogType = dialogType;
|
889 |
+
},
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
890 |
Â
|
891 |
+
/**
|
892 |
+
* Render the new row dialog
|
893 |
+
*/
|
894 |
+
render: function () {
|
895 |
+
var title = this.dialogType === 'create' ? panelsOptions.loc.row.add : panelsOptions.loc.row.edit;
|
896 |
+
this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-row' ).html(), {
|
897 |
+
title: title,
|
898 |
+
dialogType: this.dialogType
|
899 |
+
} ) );
|
900 |
Â
|
901 |
+
var titleElt = this.$( '.so-title' );
|
Â
|
|
902 |
Â
|
903 |
+
if ( this.model.has( 'label' ) && ! _.isEmpty( this.model.get( 'label' ) ) ) {
|
904 |
+
titleElt.text( this.model.get( 'label' ) );
|
905 |
+
}
|
906 |
+
this.$( '.so-edit-title' ).val( titleElt.text() );
|
907 |
Â
|
908 |
+
if (!this.builder.supports('addRow')) {
|
909 |
+
this.$('.so-buttons .so-duplicate').remove();
|
910 |
+
}
|
911 |
+
if (!this.builder.supports('deleteRow')) {
|
912 |
+
this.$('.so-buttons .so-delete').remove();
|
913 |
+
}
|
914 |
+
|
915 |
+
if (!_.isUndefined(this.model)) {
|
916 |
+
// Set the initial value of the
|
917 |
+
this.$( 'input[name="cells"].so-row-field' ).val( this.model.get( 'cells' ).length );
|
918 |
+
if ( this.model.has( 'ratio' ) ) {
|
919 |
+
this.$( 'select[name="ratio"].so-row-field' ).val( this.model.get( 'ratio' ) );
|
920 |
Â
}
|
921 |
+
if ( this.model.has( 'ratio_direction' ) ) {
|
922 |
+
this.$( 'select[name="ratio_direction"].so-row-field' ).val( this.model.get( 'ratio_direction' ) );
|
923 |
+
}
|
924 |
+
}
|
925 |
Â
|
926 |
+
this.$('input.so-row-field').keyup(function () {
|
927 |
+
$(this).trigger('change');
|
928 |
+
});
|
Â
|
|
Â
|
|
Â
|
|
929 |
Â
|
930 |
+
return this;
|
931 |
+
},
|
932 |
+
|
933 |
+
renderStyles: function () {
|
934 |
+
if ( this.styles ) {
|
935 |
+
this.styles.off( 'styles_loaded' );
|
936 |
+
this.styles.remove();
|
937 |
+
}
|
938 |
+
|
939 |
+
// Now we need to attach the style window
|
940 |
+
this.styles = new panels.view.styles();
|
941 |
+
this.styles.model = this.model;
|
942 |
+
this.styles.render('row', this.builder.config.postId, {
|
943 |
+
builderType: this.builder.config.builderType,
|
944 |
+
dialog: this
|
945 |
+
});
|
946 |
+
|
947 |
+
var $rightSidebar = this.$('.so-sidebar.so-right-sidebar');
|
948 |
+
this.styles.attach( $rightSidebar );
|
949 |
+
|
950 |
+
// Handle the loading class
|
951 |
+
this.styles.on('styles_loaded', function (hasStyles) {
|
952 |
+
if ( ! hasStyles ) {
|
953 |
+
// If we don't have styles remove the view.
|
954 |
+
this.styles.remove();
|
955 |
+
|
956 |
+
// If the sidebar is empty, hide it.
|
957 |
+
if ( $rightSidebar.children().length === 0 ) {
|
958 |
+
$rightSidebar.closest('.so-panels-dialog').removeClass('so-panels-dialog-has-right-sidebar');
|
959 |
+
$rightSidebar.hide();
|
960 |
+
}
|
961 |
Â
}
|
962 |
+
}, this);
|
963 |
+
},
|
964 |
Â
|
965 |
+
/**
|
966 |
+
* Set the row model we'll be using for this dialog.
|
967 |
+
*
|
968 |
+
* @param model
|
969 |
+
*/
|
970 |
+
setRowModel: function (model) {
|
971 |
+
this.model = model;
|
972 |
Â
|
973 |
+
if (_.isEmpty(this.model)) {
|
974 |
+
return this;
|
975 |
+
}
|
976 |
Â
|
977 |
+
// Set the rows to be a copy of the model
|
978 |
+
this.row = {
|
979 |
+
cells: this.model.get('cells').clone(),
|
980 |
+
style: {},
|
981 |
+
ratio: this.model.get('ratio'),
|
982 |
+
ratio_direction: this.model.get('ratio_direction'),
|
983 |
+
};
|
984 |
Â
|
985 |
+
// Set the initial value of the cell field.
|
986 |
+
this.$( 'input[name="cells"].so-row-field' ).val( this.model.get( 'cells' ).length );
|
987 |
+
if ( this.model.has( 'ratio' ) ) {
|
988 |
+
this.$( 'select[name="ratio"].so-row-field' ).val( this.model.get( 'ratio' ) );
|
989 |
+
}
|
990 |
+
if ( this.model.has( 'ratio_direction' ) ) {
|
991 |
+
this.$( 'select[name="ratio_direction"].so-row-field' ).val( this.model.get( 'ratio_direction' ) );
|
992 |
+
}
|
993 |
Â
|
994 |
+
this.clearCellStylesCache();
|
Â
|
|
Â
|
|
995 |
Â
|
996 |
+
return this;
|
997 |
+
},
|
998 |
+
|
999 |
+
/**
|
1000 |
+
* Regenerate the row preview and resizing interface.
|
1001 |
+
*/
|
1002 |
+
regenerateRowPreview: function () {
|
1003 |
+
var thisDialog = this;
|
1004 |
+
var rowPreview = this.$('.row-preview');
|
1005 |
Â
|
1006 |
+
// If no selected cell, select the first cell.
|
1007 |
+
var selectedIndex = this.getSelectedCellIndex();
|
1008 |
Â
|
1009 |
+
rowPreview.empty();
|
1010 |
+
|
1011 |
+
var timeout;
|
1012 |
+
|
1013 |
+
// Represent the cells
|
1014 |
+
this.row.cells.each(function (cellModel, i) {
|
1015 |
+
var newCell = $(this.cellPreviewTemplate({weight: cellModel.get('weight')}));
|
1016 |
+
rowPreview.append(newCell);
|
1017 |
+
|
1018 |
+
if(i == selectedIndex) {
|
1019 |
+
newCell.find('.preview-cell-in').addClass('cell-selected');
|
1020 |
Â
}
|
1021 |
Â
|
1022 |
+
var prevCell = newCell.prev();
|
1023 |
+
var handle;
|
1024 |
+
|
1025 |
+
if (prevCell.length) {
|
1026 |
+
handle = $('<div class="resize-handle"></div>');
|
1027 |
+
handle
|
1028 |
+
.appendTo(newCell)
|
1029 |
+
.dblclick(function () {
|
1030 |
+
var prevCellModel = thisDialog.row.cells.at(i - 1);
|
1031 |
+
var t = cellModel.get('weight') + prevCellModel.get('weight');
|
1032 |
+
cellModel.set('weight', t / 2);
|
1033 |
+
prevCellModel.set('weight', t / 2);
|
1034 |
+
thisDialog.scaleRowWidths();
|
1035 |
+
});
|
1036 |
+
|
1037 |
+
handle.draggable({
|
1038 |
+
axis: 'x',
|
1039 |
+
containment: rowPreview,
|
1040 |
+
start: function (e, ui) {
|
1041 |
+
|
1042 |
+
// Create the clone for the current cell
|
1043 |
+
var newCellClone = newCell.clone().appendTo(ui.helper).css({
|
1044 |
+
position: 'absolute',
|
1045 |
+
top: '0',
|
1046 |
+
width: newCell.outerWidth(),
|
1047 |
+
left: 6,
|
1048 |
+
height: newCell.outerHeight()
|
1049 |
+
});
|
1050 |
+
newCellClone.find('.resize-handle').remove();
|
1051 |
+
|
1052 |
+
// Create the clone for the previous cell
|
1053 |
+
var prevCellClone = prevCell.clone().appendTo(ui.helper).css({
|
1054 |
+
position: 'absolute',
|
1055 |
+
top: '0',
|
1056 |
+
width: prevCell.outerWidth(),
|
1057 |
+
right: 6,
|
1058 |
+
height: prevCell.outerHeight()
|
1059 |
+
});
|
1060 |
+
prevCellClone.find('.resize-handle').remove();
|
1061 |
+
|
1062 |
+
$(this).data({
|
1063 |
+
'newCellClone': newCellClone,
|
1064 |
+
'prevCellClone': prevCellClone
|
1065 |
+
});
|
1066 |
+
|
1067 |
+
// Hide the
|
1068 |
+
newCell.find('> .preview-cell-in').css('visibility', 'hidden');
|
1069 |
+
prevCell.find('> .preview-cell-in').css('visibility', 'hidden');
|
1070 |
+
},
|
1071 |
+
drag: function (e, ui) {
|
1072 |
+
// Calculate the new cell and previous cell widths as a percent
|
1073 |
+
var cellWeight = thisDialog.row.cells.at(i).get('weight');
|
1074 |
+
var prevCellWeight = thisDialog.row.cells.at(i - 1).get('weight');
|
1075 |
+
var ncw = cellWeight - (
|
1076 |
+
(
|
1077 |
+
ui.position.left + 6
|
1078 |
+
) / rowPreview.width()
|
1079 |
+
);
|
1080 |
+
var pcw = prevCellWeight + (
|
1081 |
+
(
|
1082 |
+
ui.position.left + 6
|
1083 |
+
) / rowPreview.width()
|
1084 |
+
);
|
1085 |
+
|
1086 |
+
var helperLeft = ui.helper.offset().left - rowPreview.offset().left - 6;
|
1087 |
+
|
1088 |
+
$(this).data('newCellClone').css('width', rowPreview.width() * ncw)
|
1089 |
+
.find('.preview-cell-weight').html(Math.round(ncw * 1000) / 10);
|
1090 |
+
|
1091 |
+
$(this).data('prevCellClone').css('width', rowPreview.width() * pcw)
|
1092 |
+
.find('.preview-cell-weight').html(Math.round(pcw * 1000) / 10);
|
1093 |
+
},
|
1094 |
+
stop: function (e, ui) {
|
1095 |
+
// Remove the clones
|
1096 |
+
$(this).data('newCellClone').remove();
|
1097 |
+
$(this).data('prevCellClone').remove();
|
1098 |
+
|
1099 |
+
// Reshow the main cells
|
1100 |
+
newCell.find('.preview-cell-in').css('visibility', 'visible');
|
1101 |
+
prevCell.find('.preview-cell-in').css('visibility', 'visible');
|
1102 |
+
|
1103 |
+
// Calculate the new cell weights
|
1104 |
+
var offset = ui.position.left + 6;
|
1105 |
+
var percent = offset / rowPreview.width();
|
1106 |
+
|
1107 |
+
// Ignore this if any of the cells are below 2% in width.
|
1108 |
+
var cellModel = thisDialog.row.cells.at(i);
|
1109 |
+
var prevCellModel = thisDialog.row.cells.at(i - 1);
|
1110 |
+
if (cellModel.get('weight') - percent > 0.02 && prevCellModel.get('weight') + percent > 0.02) {
|
1111 |
+
cellModel.set('weight', cellModel.get('weight') - percent);
|
1112 |
+
prevCellModel.set('weight', prevCellModel.get('weight') + percent);
|
1113 |
+
}
|
1114 |
Â
|
1115 |
+
thisDialog.scaleRowWidths();
|
1116 |
+
ui.helper.css('left', -6);
|
1117 |
+
}
|
1118 |
+
});
|
1119 |
+
}
|
1120 |
Â
|
1121 |
+
newCell.click(function (event) {
|
Â
|
|
Â
|
|
Â
|
|
1122 |
Â
|
1123 |
+
if ( ! ( $(event.target).is('.preview-cell') || $(event.target).is('.preview-cell-in') ) ) {
|
1124 |
+
return;
|
1125 |
Â
}
|
1126 |
Â
|
1127 |
+
var cell = $(event.target);
|
1128 |
+
cell.closest('.row-preview').find('.preview-cell .preview-cell-in').removeClass('cell-selected');
|
1129 |
+
cell.addClass('cell-selected');
|
1130 |
+
|
1131 |
+
this.openSelectedCellStyles();
|
1132 |
+
|
1133 |
+
}.bind(this));
|
1134 |
+
|
1135 |
+
// Make this row weight click editable
|
1136 |
+
newCell.find('.preview-cell-weight').click(function (ci) {
|
1137 |
+
|
1138 |
+
// Disable the draggable while entering values
|
1139 |
+
thisDialog.$('.resize-handle').css('pointer-event', 'none').draggable('disable');
|
1140 |
+
|
1141 |
+
rowPreview.find('.preview-cell-weight').each(function () {
|
1142 |
+
var $$ = jQuery(this).hide();
|
1143 |
+
$('<input type="text" class="preview-cell-weight-input no-user-interacted" />')
|
1144 |
+
.val(parseFloat($$.html())).insertAfter($$)
|
1145 |
+
.focus(function () {
|
1146 |
+
clearTimeout(timeout);
|
1147 |
+
})
|
1148 |
+
.keyup(function (e) {
|
1149 |
+
if (e.keyCode !== 9) {
|
1150 |
+
// Only register the interaction if the user didn't press tab
|
1151 |
+
$(this).removeClass('no-user-interacted');
|
1152 |
+
}
|
1153 |
+
|
1154 |
+
// Enter is clicked
|
1155 |
+
if (e.keyCode === 13) {
|
1156 |
+
e.preventDefault();
|
1157 |
+
$(this).blur();
|
1158 |
+
}
|
1159 |
+
})
|
1160 |
+
.keydown(function (e) {
|
1161 |
+
if (e.keyCode === 9) {
|
1162 |
+
e.preventDefault();
|
1163 |
+
|
1164 |
+
// Tab will always cycle around the row inputs
|
1165 |
+
var inputs = rowPreview.find('.preview-cell-weight-input');
|
1166 |
+
var i = inputs.index($(this));
|
1167 |
+
if (i === inputs.length - 1) {
|
1168 |
+
inputs.eq(0).focus().select();
|
1169 |
+
} else {
|
1170 |
+
inputs.eq(i + 1).focus().select();
|
1171 |
+
}
|
1172 |
+
}
|
1173 |
+
})
|
1174 |
+
.blur(function () {
|
1175 |
+
rowPreview.find('.preview-cell-weight-input').each(function (i, el) {
|
1176 |
+
if (isNaN(parseFloat($(el).val()))) {
|
1177 |
+
$(el).val(Math.floor(thisDialog.row.cells.at(i).get('weight') * 1000) / 10);
|
1178 |
+
}
|
1179 |
+
});
|
1180 |
+
|
1181 |
+
timeout = setTimeout(function () {
|
1182 |
+
// If there are no weight inputs, then skip this
|
1183 |
+
if (rowPreview.find('.preview-cell-weight-input').length === 0) {
|
1184 |
+
return false;
|
1185 |
+
}
|
1186 |
+
|
1187 |
+
// Go through all the inputs
|
1188 |
+
var rowWeights = [],
|
1189 |
+
rowChanged = [],
|
1190 |
+
changedSum = 0,
|
1191 |
+
unchangedSum = 0;
|
1192 |
+
|
1193 |
+
rowPreview.find('.preview-cell-weight-input').each(function (i, el) {
|
1194 |
+
var val = parseFloat($(el).val());
|
1195 |
+
if (isNaN(val)) {
|
1196 |
+
val = 1 / thisDialog.row.cells.length;
|
1197 |
+
} else {
|
1198 |
+
val = Math.round(val * 10) / 1000;
|
1199 |
+
}
|
1200 |
+
|
1201 |
+
// Check within 3 decimal points
|
1202 |
+
var changed = !$(el).hasClass('no-user-interacted');
|
1203 |
+
|
1204 |
+
rowWeights.push(val);
|
1205 |
+
rowChanged.push(changed);
|
1206 |
+
|
1207 |
+
if (changed) {
|
1208 |
+
changedSum += val;
|
1209 |
+
} else {
|
1210 |
+
unchangedSum += val;
|
1211 |
+
}
|
1212 |
+
});
|
1213 |
+
|
1214 |
+
if (changedSum > 0 && unchangedSum > 0 && (
|
1215 |
+
1 - changedSum
|
1216 |
+
) > 0) {
|
1217 |
+
// Balance out the unchanged rows to occupy the weight left over by the changed sum
|
1218 |
+
for (var i = 0; i < rowWeights.length; i++) {
|
1219 |
+
if (!rowChanged[i]) {
|
1220 |
+
rowWeights[i] = (
|
1221 |
+
rowWeights[i] / unchangedSum
|
1222 |
+
) * (
|
1223 |
+
1 - changedSum
|
1224 |
+
);
|
1225 |
+
}
|
1226 |
+
}
|
1227 |
+
}
|
1228 |
+
|
1229 |
+
// Last check to ensure total weight is 1
|
1230 |
+
var sum = _.reduce(rowWeights, function (memo, num) {
|
1231 |
+
return memo + num;
|
1232 |
+
});
|
1233 |
+
rowWeights = rowWeights.map(function (w) {
|
1234 |
+
return w / sum;
|
1235 |
+
});
|
1236 |
+
|
1237 |
+
// Set the new cell weights and regenerate the preview.
|
1238 |
+
if (Math.min.apply(Math, rowWeights) > 0.01) {
|
1239 |
+
thisDialog.row.cells.each(function (cell, i) {
|
1240 |
+
cell.set('weight', rowWeights[i]);
|
1241 |
+
});
|
1242 |
+
}
|
1243 |
+
|
1244 |
+
// Now lets animate the cells into their new widths
|
1245 |
+
rowPreview.find('.preview-cell').each(function (i, el) {
|
1246 |
+
var cellWeight = thisDialog.row.cells.at(i).get('weight');
|
1247 |
+
$(el).animate({'width': Math.round(cellWeight * 1000) / 10 + "%"}, 250);
|
1248 |
+
$(el).find('.preview-cell-weight-input').val(Math.round(cellWeight * 1000) / 10);
|
1249 |
+
});
|
1250 |
+
|
1251 |
+
// So the draggable handle is not hidden.
|
1252 |
+
rowPreview.find('.preview-cell').css('overflow', 'visible');
|
1253 |
+
setTimeout(thisDialog.regenerateRowPreview.bind(thisDialog), 260);
|
1254 |
+
|
1255 |
+
}, 100);
|
1256 |
+
})
|
1257 |
+
.click(function () {
|
1258 |
+
$(this).select();
|
1259 |
+
});
|
1260 |
+
});
|
1261 |
+
|
1262 |
+
$(this).siblings('.preview-cell-weight-input').select();
|
1263 |
+
|
1264 |
+
});
|
1265 |
+
|
1266 |
+
}, this);
|
1267 |
+
|
1268 |
+
this.trigger('form_loaded', this);
|
1269 |
+
},
|
1270 |
+
|
1271 |
+
getSelectedCellIndex: function() {
|
1272 |
+
var selectedIndex = -1;
|
1273 |
+
this.$('.preview-cell .preview-cell-in').each(function(index, el) {
|
1274 |
+
if($(el).is('.cell-selected')) {
|
1275 |
+
selectedIndex = index;
|
1276 |
+
}
|
1277 |
+
});
|
1278 |
+
return selectedIndex;
|
1279 |
+
},
|
1280 |
+
|
1281 |
+
openSelectedCellStyles: function() {
|
1282 |
+
if (!_.isUndefined(this.cellStyles)) {
|
1283 |
+
if (this.cellStyles.stylesLoaded) {
|
1284 |
+
var style = {};
|
1285 |
+
try {
|
1286 |
+
style = this.getFormValues('.so-sidebar .so-visual-styles.so-cell-styles').style;
|
1287 |
Â
}
|
1288 |
+
catch (err) {
|
1289 |
+
console.log('Error retrieving cell styles - ' + err.message);
|
1290 |
Â
}
|
1291 |
Â
|
1292 |
+
this.cellStyles.model.set('style', style);
|
1293 |
+
}
|
1294 |
+
this.cellStyles.detach();
|
1295 |
+
}
|
1296 |
Â
|
1297 |
+
this.cellStyles = this.getSelectedCellStyles();
|
Â
|
|
Â
|
|
1298 |
Â
|
1299 |
+
if ( this.cellStyles ) {
|
1300 |
+
var $rightSidebar = this.$( '.so-sidebar.so-right-sidebar' );
|
1301 |
+
this.cellStyles.attach( $rightSidebar );
|
1302 |
+
this.cellStyles.on( 'styles_loaded', function ( hasStyles ) {
|
1303 |
+
if ( hasStyles ) {
|
1304 |
+
$rightSidebar.closest('.so-panels-dialog').addClass('so-panels-dialog-has-right-sidebar');
|
1305 |
+
$rightSidebar.show();
|
1306 |
+
}
|
1307 |
+
} );
|
1308 |
Â
}
|
1309 |
+
},
|
Â
|
|
1310 |
Â
|
1311 |
+
getSelectedCellStyles: function () {
|
1312 |
+
var cellIndex = this.getSelectedCellIndex();
|
1313 |
+
if ( cellIndex > -1 ) {
|
1314 |
+
var cellStyles = this.cellStylesCache[cellIndex];
|
1315 |
+
if ( !cellStyles ) {
|
1316 |
+
cellStyles = new panels.view.styles();
|
1317 |
+
cellStyles.model = this.row.cells.at( cellIndex );
|
1318 |
+
cellStyles.render( 'cell', this.builder.config.postId, {
|
1319 |
+
builderType: this.builder.config.builderType,
|
1320 |
+
dialog: this,
|
1321 |
+
index: cellIndex,
|
1322 |
+
} );
|
1323 |
+
this.cellStylesCache[cellIndex] = cellStyles;
|
1324 |
+
}
|
1325 |
Â
}
|
1326 |
+
|
1327 |
+
return cellStyles;
|
1328 |
+
},
|
1329 |
+
|
1330 |
+
clearCellStylesCache: function () {
|
1331 |
+
// Call remove() on all cell styles to remove data, event listeners etc.
|
1332 |
+
this.cellStylesCache.forEach(function (cellStyles) {
|
1333 |
+
cellStyles.remove();
|
1334 |
+
cellStyles.off( 'styles_loaded' );
|
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, key ) {
|
1951 |
+
$( this.dialogTabTemplate( {'title': tab.title, 'tab': key} ) ).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 |
+
// Trigger an event before the panels setup to allow adding listeners for various builder events which are
|
2600 |
+
// triggered during initial setup.
|
2601 |
+
$(document).trigger('before_panels_setup', builderView);
|
2602 |
+
|
2603 |
+
// Set up the builder view
|
2604 |
+
builderView
|
2605 |
+
.render()
|
2606 |
+
.attach( {
|
2607 |
+
container: container
|
2608 |
+
} )
|
2609 |
+
.setDataField( field )
|
2610 |
+
.attachToEditor();
|
2611 |
+
|
2612 |
+
// When the form is submitted, update the panels data
|
2613 |
+
form.submit( function () {
|
2614 |
+
// Refresh the data
|
2615 |
+
builderModel.refreshPanelsData();
|
2616 |
+
} );
|
2617 |
+
|
2618 |
+
container.removeClass( 'so-panels-loading' );
|
2619 |
+
|
2620 |
+
// Trigger a global jQuery event after we've setup the builder view. Everything is accessible form there
|
2621 |
+
$( document ).trigger( 'panels_setup', builderView, window.panels );
|
2622 |
+
}
|
2623 |
+
|
2624 |
+
// Setup new widgets when they're added in the standard widget interface
|
2625 |
+
$( document ).on( 'widget-added', function ( e, widget ) {
|
2626 |
+
$( widget ).find( '.siteorigin-page-builder-widget' ).soPanelsSetupBuilderWidget();
|
2627 |
+
} );
|
2628 |
+
|
2629 |
+
// Setup existing widgets on the page (for the widgets interface)
|
2630 |
+
if ( ! $( 'body' ).hasClass( 'wp-customizer' ) ) {
|
2631 |
+
$( function () {
|
2632 |
+
$( '.siteorigin-page-builder-widget' ).soPanelsSetupBuilderWidget();
|
2633 |
+
} );
|
2634 |
+
}
|
2635 |
+
|
2636 |
+
// A global escape handler
|
2637 |
+
$(window).on('keyup', function(e){
|
2638 |
+
// [Esc] to close
|
2639 |
+
if ( e.which === 27 ) {
|
2640 |
+
// Trigger a click on the last visible Page Builder window
|
2641 |
+
$( '.so-panels-dialog-wrapper, .so-panels-live-editor' ).filter(':visible')
|
2642 |
+
.last().find('.so-title-bar .so-close, .live-editor-close').click();
|
2643 |
+
}
|
2644 |
+
});
|
2645 |
+
} );
|
2646 |
+
|
2647 |
+
},{"./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){
|
2648 |
+
module.exports = Backbone.Model.extend({
|
2649 |
+
layoutPosition: {
|
2650 |
+
BEFORE: 'before',
|
2651 |
+
AFTER: 'after',
|
2652 |
+
REPLACE: 'replace',
|
2653 |
+
},
|
2654 |
+
|
2655 |
+
rows: {},
|
2656 |
+
|
2657 |
+
defaults: {
|
2658 |
+
'data': {
|
2659 |
+
'widgets': [],
|
2660 |
+
'grids': [],
|
2661 |
+
'grid_cells': []
|
2662 |
+
}
|
2663 |
+
},
|
2664 |
+
|
2665 |
+
initialize: function () {
|
2666 |
+
// These are the main rows in the interface
|
2667 |
+
this.set( 'rows', new panels.collection.rows() );
|
2668 |
+
},
|
2669 |
+
|
2670 |
+
/**
|
2671 |
+
* Add a new row to this builder.
|
2672 |
+
*
|
2673 |
+
* @param attrs
|
2674 |
+
* @param cells
|
2675 |
+
* @param options
|
2676 |
+
*/
|
2677 |
+
addRow: function (attrs, cells, options) {
|
2678 |
+
options = _.extend({
|
2679 |
+
noAnimate: false
|
2680 |
+
}, options);
|
2681 |
+
|
2682 |
+
var cellCollection = new panels.collection.cells(cells);
|
2683 |
+
|
2684 |
+
attrs = _.extend({
|
2685 |
+
collection: this.get('rows'),
|
2686 |
+
cells: cellCollection,
|
2687 |
+
}, attrs);
|
2688 |
+
|
2689 |
+
// Create the actual row
|
2690 |
+
var row = new panels.model.row(attrs);
|
2691 |
+
row.builder = this;
|
2692 |
+
|
2693 |
+
this.get('rows').add( row, options );
|
2694 |
+
|
2695 |
+
return row;
|
2696 |
+
},
|
2697 |
+
|
2698 |
+
/**
|
2699 |
+
* Load the panels data into the builder
|
2700 |
+
*
|
2701 |
+
* @param data Object the layout and widgets data to load.
|
2702 |
+
* @param position string Where to place the new layout. Allowed options are 'before', 'after'. Anything else will
|
2703 |
+
* cause the new layout to replace the old one.
|
2704 |
+
*/
|
2705 |
+
loadPanelsData: function ( data, position ) {
|
2706 |
+
try {
|
2707 |
+
if ( position === this.layoutPosition.BEFORE ) {
|
2708 |
+
data = this.concatPanelsData( data, this.getPanelsData() );
|
2709 |
+
} else if ( position === this.layoutPosition.AFTER ) {
|
2710 |
+
data = this.concatPanelsData( this.getPanelsData(), data );
|
2711 |
+
}
|
2712 |
+
|
2713 |
+
// Start by destroying any rows that currently exist. This will in turn destroy cells, widgets and all the associated views
|
2714 |
+
this.emptyRows();
|
2715 |
+
|
2716 |
+
// This will empty out the current rows and reload the builder data.
|
2717 |
+
this.set( 'data', JSON.parse( JSON.stringify( data ) ), {silent: true} );
|
2718 |
+
|
2719 |
+
var cit = 0;
|
2720 |
+
var rows = [];
|
2721 |
+
|
2722 |
+
if ( _.isUndefined( data.grid_cells ) ) {
|
2723 |
+
this.trigger( 'load_panels_data' );
|
2724 |
+
return;
|
2725 |
+
}
|
2726 |
+
|
2727 |
+
var gi;
|
2728 |
+
for ( var ci = 0; ci < data.grid_cells.length; ci ++ ) {
|
2729 |
+
gi = parseInt( data.grid_cells[ci].grid );
|
2730 |
+
if ( _.isUndefined( rows[gi] ) ) {
|
2731 |
+
rows[gi] = [];
|
2732 |
+
}
|
2733 |
+
|
2734 |
+
rows[gi].push( data.grid_cells[ci] );
|
2735 |
+
}
|
2736 |
+
|
2737 |
+
var builderModel = this;
|
2738 |
+
_.each( rows, function ( row, i ) {
|
2739 |
+
var rowAttrs = {};
|
2740 |
+
|
2741 |
+
if ( ! _.isUndefined( data.grids[i].style ) ) {
|
2742 |
+
rowAttrs.style = data.grids[i].style;
|
2743 |
+
}
|
2744 |
+
|
2745 |
+
if ( ! _.isUndefined( data.grids[i].ratio) ) {
|
2746 |
+
rowAttrs.ratio = data.grids[i].ratio;
|
2747 |
+
}
|
2748 |
+
|
2749 |
+
if ( ! _.isUndefined( data.grids[i].ratio_direction) ) {
|
2750 |
+
rowAttrs.ratio_direction = data.grids[i].ratio_direction
|
2751 |
+
}
|
2752 |
+
|
2753 |
+
if ( ! _.isUndefined( data.grids[i].color_label) ) {
|
2754 |
+
rowAttrs.color_label = data.grids[i].color_label;
|
2755 |
+
}
|
2756 |
+
|
2757 |
+
if ( ! _.isUndefined( data.grids[i].label) ) {
|
2758 |
+
rowAttrs.label = data.grids[i].label;
|
2759 |
+
}
|
2760 |
+
// This will create and add the row model and its cells
|
2761 |
+
builderModel.addRow(rowAttrs, row, {noAnimate: true} );
|
2762 |
+
} );
|
2763 |
+
|
2764 |
+
|
2765 |
+
if ( _.isUndefined( data.widgets ) ) {
|
2766 |
+
return;
|
2767 |
+
}
|
2768 |
+
|
2769 |
+
// Add the widgets
|
2770 |
+
_.each( data.widgets, function ( widgetData ) {
|
2771 |
+
var panels_info = null;
|
2772 |
+
if ( ! _.isUndefined( widgetData.panels_info ) ) {
|
2773 |
+
panels_info = widgetData.panels_info;
|
2774 |
+
delete widgetData.panels_info;
|
2775 |
+
} else {
|
2776 |
+
panels_info = widgetData.info;
|
2777 |
+
delete widgetData.info;
|
2778 |
+
}
|
2779 |
+
|
2780 |
+
var row = builderModel.get('rows').at( parseInt( panels_info.grid ) );
|
2781 |
+
var cell = row.get('cells').at( parseInt( panels_info.cell ) );
|
2782 |
+
|
2783 |
+
var newWidget = new panels.model.widget( {
|
2784 |
+
class: panels_info.class,
|
2785 |
+
values: widgetData
|
2786 |
+
} );
|
2787 |
+
|
2788 |
+
if ( ! _.isUndefined( panels_info.style ) ) {
|
2789 |
+
newWidget.set( 'style', panels_info.style );
|
2790 |
+
}
|
2791 |
+
|
2792 |
+
if ( ! _.isUndefined( panels_info.read_only ) ) {
|
2793 |
+
newWidget.set( 'read_only', panels_info.read_only );
|
2794 |
+
}
|
2795 |
+
if ( ! _.isUndefined( panels_info.widget_id ) ) {
|
2796 |
+
newWidget.set( 'widget_id', panels_info.widget_id );
|
2797 |
+
}
|
2798 |
+
else {
|
2799 |
+
newWidget.set( 'widget_id', panels.helpers.utils.generateUUID() );
|
2800 |
+
}
|
2801 |
+
|
2802 |
+
if ( ! _.isUndefined( panels_info.label ) ) {
|
2803 |
+
newWidget.set( 'label', panels_info.label );
|
2804 |
+
}
|
2805 |
+
|
2806 |
+
newWidget.cell = cell;
|
2807 |
+
cell.get('widgets').add( newWidget, { noAnimate: true } );
|
2808 |
+
} );
|
2809 |
+
|
2810 |
+
this.trigger( 'load_panels_data' );
|
2811 |
+
}
|
2812 |
+
catch ( err ) {
|
2813 |
+
console.log( 'Error loading data: ' + err.message );
|
2814 |
+
|
2815 |
+
}
|
2816 |
+
},
|
2817 |
+
|
2818 |
+
/**
|
2819 |
+
* Concatenate the second set of Page Builder data to the first. There is some validation of input, but for the most
|
2820 |
+
* part it's up to the caller to ensure the Page Builder data is well formed.
|
2821 |
+
*/
|
2822 |
+
concatPanelsData: function ( panelsDataA, panelsDataB ) {
|
2823 |
+
|
2824 |
+
if ( _.isUndefined( panelsDataB ) || _.isUndefined( panelsDataB.grids ) || _.isEmpty( panelsDataB.grids ) ||
|
2825 |
+
_.isUndefined( panelsDataB.grid_cells ) || _.isEmpty( panelsDataB.grid_cells ) ) {
|
2826 |
+
return panelsDataA;
|
2827 |
+
}
|
2828 |
+
|
2829 |
+
if ( _.isUndefined( panelsDataA ) || _.isUndefined( panelsDataA.grids ) || _.isEmpty( panelsDataA.grids ) ) {
|
2830 |
+
return panelsDataB;
|
2831 |
+
}
|
2832 |
+
|
2833 |
+
var gridsBOffset = panelsDataA.grids.length;
|
2834 |
+
var widgetsBOffset = ! _.isUndefined( panelsDataA.widgets ) ? panelsDataA.widgets.length : 0;
|
2835 |
+
var newPanelsData = {grids: [], 'grid_cells': [], 'widgets': []};
|
2836 |
+
|
2837 |
+
// Concatenate grids (rows)
|
2838 |
+
newPanelsData.grids = panelsDataA.grids.concat( panelsDataB.grids );
|
2839 |
+
|
2840 |
+
// Create a copy of panelsDataA grid_cells and widgets
|
2841 |
+
if ( ! _.isUndefined( panelsDataA.grid_cells ) ) {
|
2842 |
+
newPanelsData.grid_cells = panelsDataA.grid_cells.slice();
|
2843 |
+
}
|
2844 |
+
if ( ! _.isUndefined( panelsDataA.widgets ) ) {
|
2845 |
+
newPanelsData.widgets = panelsDataA.widgets.slice();
|
2846 |
+
}
|
2847 |
+
|
2848 |
+
var i;
|
2849 |
+
// Concatenate grid cells (row columns)
|
2850 |
+
for ( i = 0; i < panelsDataB.grid_cells.length; i ++ ) {
|
2851 |
+
var gridCellB = panelsDataB.grid_cells[i];
|
2852 |
+
gridCellB.grid = parseInt( gridCellB.grid ) + gridsBOffset;
|
2853 |
+
newPanelsData.grid_cells.push( gridCellB );
|
2854 |
+
}
|
2855 |
+
|
2856 |
+
// Concatenate widgets
|
2857 |
+
if ( ! _.isUndefined( panelsDataB.widgets ) ) {
|
2858 |
+
for ( i = 0; i < panelsDataB.widgets.length; i ++ ) {
|
2859 |
+
var widgetB = panelsDataB.widgets[i];
|
2860 |
+
widgetB.panels_info.grid = parseInt( widgetB.panels_info.grid ) + gridsBOffset;
|
2861 |
+
widgetB.panels_info.id = parseInt( widgetB.panels_info.id ) + widgetsBOffset;
|
2862 |
+
newPanelsData.widgets.push( widgetB );
|
2863 |
+
}
|
2864 |
+
}
|
2865 |
+
|
2866 |
+
return newPanelsData;
|
2867 |
+
},
|
2868 |
+
|
2869 |
+
/**
|
2870 |
+
* Convert the content of the builder into a object that represents the page builder data
|
2871 |
+
*/
|
2872 |
+
getPanelsData: function () {
|
2873 |
+
|
2874 |
+
var builder = this;
|
2875 |
+
|
2876 |
+
var data = {
|
2877 |
+
'widgets': [],
|
2878 |
+
'grids': [],
|
2879 |
+
'grid_cells': []
|
2880 |
+
};
|
2881 |
+
var widgetId = 0;
|
2882 |
+
|
2883 |
+
this.get('rows').each( function ( row, ri ) {
|
2884 |
+
|
2885 |
+
row.get('cells').each( function ( cell, ci ) {
|
2886 |
+
|
2887 |
+
cell.get('widgets').each( function ( widget, wi ) {
|
2888 |
+
// Add the data for the widget, including the panels_info field.
|
2889 |
+
var panels_info = {
|
2890 |
+
class: widget.get( 'class' ),
|
2891 |
+
raw: widget.get( 'raw' ),
|
2892 |
+
grid: ri,
|
2893 |
+
cell: ci,
|
2894 |
+
// Strictly this should be an index
|
2895 |
+
id: widgetId ++,
|
2896 |
+
widget_id: widget.get( 'widget_id' ),
|
2897 |
+
style: widget.get( 'style' ),
|
2898 |
+
label: widget.get( 'label' ),
|
2899 |
+
};
|
2900 |
+
|
2901 |
+
if( _.isEmpty( panels_info.widget_id ) ) {
|
2902 |
+
panels_info.widget_id = panels.helpers.utils.generateUUID();
|
2903 |
+
}
|
2904 |
+
|
2905 |
+
var values = _.extend( _.clone( widget.get( 'values' ) ), {
|
2906 |
+
panels_info: panels_info
|
2907 |
+
} );
|
2908 |
+
data.widgets.push( values );
|
2909 |
+
} );
|
2910 |
+
|
2911 |
+
// Add the cell info
|
2912 |
+
data.grid_cells.push( {
|
2913 |
+
grid: ri,
|
2914 |
+
index: ci,
|
2915 |
+
weight: cell.get( 'weight' ),
|
2916 |
+
style: cell.get( 'style' ),
|
2917 |
+
} );
|
2918 |
+
|
2919 |
+
} );
|
2920 |
+
|
2921 |
+
data.grids.push( {
|
2922 |
+
cells: row.get('cells').length,
|
2923 |
+
style: row.get( 'style' ),
|
2924 |
+
ratio: row.get('ratio'),
|
2925 |
+
ratio_direction: row.get('ratio_direction'),
|
2926 |
+
color_label: row.get( 'color_label' ),
|
2927 |
+
label: row.get( 'label' ),
|
2928 |
+
} );
|
2929 |
+
|
2930 |
+
} );
|
2931 |
+
|
2932 |
+
return data;
|
2933 |
+
|
2934 |
+
},
|
2935 |
+
|
2936 |
+
/**
|
2937 |
+
* This will check all the current entries and refresh the panels data
|
2938 |
+
*/
|
2939 |
+
refreshPanelsData: function ( args ) {
|
2940 |
+
args = _.extend( {
|
2941 |
+
silent: false
|
2942 |
+
}, args );
|
2943 |
+
|
2944 |
+
var oldData = this.get( 'data' );
|
2945 |
+
var newData = this.getPanelsData();
|
2946 |
+
this.set( 'data', newData, {silent: true} );
|
2947 |
+
|
2948 |
+
if ( ! args.silent && JSON.stringify( newData ) !== JSON.stringify( oldData ) ) {
|
2949 |
+
// The default change event doesn't trigger on deep changes, so we'll trigger our own
|
2950 |
+
this.trigger( 'change' );
|
2951 |
+
this.trigger( 'change:data' );
|
2952 |
+
this.trigger( 'refresh_panels_data', newData, args );
|
2953 |
+
}
|
2954 |
+
},
|
2955 |
+
|
2956 |
+
/**
|
2957 |
+
* Empty all the rows and the cells/widgets they contain.
|
2958 |
+
*/
|
2959 |
+
emptyRows: function () {
|
2960 |
+
_.invoke( this.get('rows').toArray(), 'destroy' );
|
2961 |
+
this.get('rows').reset();
|
2962 |
+
|
2963 |
+
return this;
|
2964 |
+
},
|
2965 |
+
|
2966 |
+
isValidLayoutPosition: function ( position ) {
|
2967 |
+
return position === this.layoutPosition.BEFORE ||
|
2968 |
+
position === this.layoutPosition.AFTER ||
|
2969 |
+
position === this.layoutPosition.REPLACE;
|
2970 |
+
},
|
2971 |
+
|
2972 |
+
/**
|
2973 |
+
* Convert HTML into Panels Data
|
2974 |
+
* @param html
|
2975 |
+
*/
|
2976 |
+
getPanelsDataFromHtml: function( html, editorClass ){
|
2977 |
+
var thisModel = this;
|
2978 |
+
var $html = jQuery( '<div id="wrapper">' + html + '</div>' );
|
2979 |
+
|
2980 |
+
if( $html.find('.panel-layout .panel-grid').length ) {
|
2981 |
+
// This looks like Page Builder html, lets try parse it
|
2982 |
+
var panels_data = {
|
2983 |
+
grids: [],
|
2984 |
+
grid_cells: [],
|
2985 |
+
widgets: [],
|
2986 |
+
};
|
2987 |
+
|
2988 |
+
// The Regex object that'll match SiteOrigin widgets
|
2989 |
+
var re = new RegExp( panelsOptions.siteoriginWidgetRegex , "i" );
|
2990 |
+
var decodeEntities = (function() {
|
2991 |
+
// this prevents any overhead from creating the object each time
|
2992 |
+
var element = document.createElement('div');
|
2993 |
+
|
2994 |
+
function decodeHTMLEntities (str) {
|
2995 |
+
if(str && typeof str === 'string') {
|
2996 |
+
// strip script/html tags
|
2997 |
+
str = str.replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, '');
|
2998 |
+
str = str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, '');
|
2999 |
+
element.innerHTML = str;
|
3000 |
+
str = element.textContent;
|
3001 |
+
element.textContent = '';
|
3002 |
+
}
|
3003 |
+
|
3004 |
+
return str;
|
3005 |
+
}
|
3006 |
+
|
3007 |
+
return decodeHTMLEntities;
|
3008 |
+
})();
|
3009 |
+
|
3010 |
+
// Remove all wrapping divs from a widget to get its html
|
3011 |
+
var getTextWidgetContents = function( $el ){
|
3012 |
+
var $divs = $el.find( 'div' );
|
3013 |
+
if( ! $divs.length ) {
|
3014 |
+
return $el.html();
|
3015 |
+
}
|
3016 |
+
|
3017 |
+
var i;
|
3018 |
+
for( i = 0; i < $divs.length - 1; i++ ) {
|
3019 |
+
if( jQuery.trim( $divs.eq(i).text() ) != jQuery.trim( $divs.eq(i+1).text() ) ) {
|
3020 |
+
break;
|
3021 |
+
}
|
3022 |
+
}
|
3023 |
+
|
3024 |
+
var title = $divs.eq( i ).find( '.widget-title:header' ),
|
3025 |
+
titleText = '';
|
3026 |
+
|
3027 |
+
if( title.length ) {
|
3028 |
+
titleText = title.html();
|
3029 |
+
title.remove();
|
3030 |
+
}
|
3031 |
+
|
3032 |
+
return {
|
3033 |
+
title: titleText,
|
3034 |
+
text: $divs.eq(i).html(),
|
3035 |
+
};
|
3036 |
+
};
|
3037 |
+
|
3038 |
+
var $layout = $html.find( '.panel-layout' ).eq(0);
|
3039 |
+
var filterNestedLayout = function( i, el ){
|
3040 |
+
return jQuery( el ).closest( '.panel-layout' ).is( $layout );
|
3041 |
+
};
|
3042 |
+
|
3043 |
+
$html.find('> .panel-layout > .panel-grid').filter( filterNestedLayout ).each( function( ri, el ){
|
3044 |
+
var $row = jQuery( el ),
|
3045 |
+
$cells = $row.find( '.panel-grid-cell' ).filter( filterNestedLayout );
|
3046 |
+
|
3047 |
+
panels_data.grids.push( {
|
3048 |
+
cells: $cells.length,
|
3049 |
+
style: $row.data( 'style' ),
|
3050 |
+
ratio: $row.data( 'ratio' ),
|
3051 |
+
ratio_direction: $row.data( 'ratio-direction' ),
|
3052 |
+
color_label: $row.data( 'color-label' ),
|
3053 |
+
label: $row.data( 'label' ),
|
3054 |
+
} );
|
3055 |
+
|
3056 |
+
$cells.each( function( ci, el ){
|
3057 |
+
var $cell = jQuery( el ),
|
3058 |
+
$widgets = $cell.find( '.so-panel' ).filter( filterNestedLayout );
|
3059 |
+
|
3060 |
+
panels_data.grid_cells.push( {
|
3061 |
+
grid: ri,
|
3062 |
+
weight: ! _.isUndefined( $cell.data( 'weight' ) ) ? parseFloat( $cell.data( 'weight' ) ) : 1,
|
3063 |
+
style: $cell.data( 'style' ),
|
3064 |
+
} );
|
3065 |
+
|
3066 |
+
$widgets.each( function( wi, el ){
|
3067 |
+
var $widget = jQuery(el),
|
3068 |
+
widgetContent = $widget.find('.panel-widget-style').length ? $widget.find('.panel-widget-style').html() : $widget.html(),
|
3069 |
+
panels_info = {
|
3070 |
+
grid: ri,
|
3071 |
+
cell: ci,
|
3072 |
+
style: $widget.data( 'style' ),
|
3073 |
+
raw: false,
|
3074 |
+
label: $widget.data( 'label' )
|
3075 |
+
};
|
3076 |
+
|
3077 |
+
widgetContent = widgetContent.trim();
|
3078 |
+
|
3079 |
+
// Check if this is a SiteOrigin Widget
|
3080 |
+
var match = re.exec( widgetContent );
|
3081 |
+
if( ! _.isNull( match ) && widgetContent.replace( re, '' ).trim() === '' ) {
|
3082 |
+
try {
|
3083 |
+
var classMatch = /class="(.*?)"/.exec( match[3] ),
|
3084 |
+
dataInput = jQuery( match[5] ),
|
3085 |
+
data = JSON.parse( decodeEntities( dataInput.val( ) ) ),
|
3086 |
+
newWidget = data.instance;
|
3087 |
+
|
3088 |
+
panels_info.class = classMatch[1].replace( /\\\\+/g, '\\' );
|
3089 |
+
panels_info.raw = false;
|
3090 |
+
|
3091 |
+
newWidget.panels_info = panels_info;
|
3092 |
+
panels_data.widgets.push( newWidget );
|
3093 |
+
}
|
3094 |
+
catch ( err ) {
|
3095 |
+
// There was a problem, so treat this as a standard editor widget
|
3096 |
+
panels_info.class = editorClass;
|
3097 |
+
panels_data.widgets.push( _.extend( getTextWidgetContents( $widget ), {
|
3098 |
+
filter: "1",
|
3099 |
+
type: "visual",
|
3100 |
+
panels_info: panels_info
|
3101 |
+
} ) );
|
3102 |
+
}
|
3103 |
+
|
3104 |
+
// Continue
|
3105 |
+
return true;
|
3106 |
+
}
|
3107 |
Â
else if( widgetContent.indexOf( 'panel-layout' ) !== -1 ) {
|
3108 |
Â
// Check if this is a layout widget
|
3109 |
Â
var $widgetContent = jQuery( '<div>' + widgetContent + '</div>' );
|
3115 |
Â
panels_info: panels_info
|
3116 |
Â
} );
|
3117 |
Â
|
3118 |
+
// continue
|
3119 |
+
return true;
|
3120 |
+
}
|
3121 |
+
}
|
3122 |
+
|
3123 |
+
// This is a standard editor class widget
|
3124 |
+
panels_info.class = editorClass;
|
3125 |
+
panels_data.widgets.push( _.extend( getTextWidgetContents( $widget ), {
|
3126 |
+
filter: "1",
|
3127 |
+
type: "visual",
|
3128 |
+
panels_info: panels_info
|
3129 |
+
} ) );
|
3130 |
+
return true;
|
3131 |
+
} );
|
3132 |
+
} );
|
3133 |
+
} );
|
3134 |
+
|
3135 |
+
// Remove all the Page Builder content
|
3136 |
+
$html.find('.panel-layout').remove();
|
3137 |
+
$html.find('style[data-panels-style-for-post]').remove();
|
3138 |
+
|
3139 |
+
// If there's anything left, add it to an editor widget at the end of panels_data
|
3140 |
+
if( $html.html().replace(/^\s+|\s+$/gm,'').length ) {
|
3141 |
+
panels_data.grids.push( {
|
3142 |
+
cells: 1,
|
3143 |
+
style: {},
|
3144 |
+
} );
|
3145 |
+
panels_data.grid_cells.push( {
|
3146 |
+
grid: panels_data.grids.length - 1,
|
3147 |
+
weight: 1,
|
3148 |
+
} );
|
3149 |
+
panels_data.widgets.push( {
|
3150 |
+
filter: "1",
|
3151 |
+
text: $html.html().replace(/^\s+|\s+$/gm,''),
|
3152 |
+
title: "",
|
3153 |
+
type: "visual",
|
3154 |
+
panels_info: {
|
3155 |
+
class: editorClass,
|
3156 |
+
raw: false,
|
3157 |
+
grid: panels_data.grids.length - 1,
|
3158 |
+
cell: 0
|
3159 |
+
}
|
3160 |
+
} );
|
3161 |
+
}
|
3162 |
+
|
3163 |
+
return panels_data;
|
3164 |
+
}
|
3165 |
+
else {
|
3166 |
+
// This is probably just old school post content
|
3167 |
+
return {
|
3168 |
+
grid_cells: [ { grid: 0, weight: 1 } ],
|
3169 |
+
grids: [ { cells: 1 } ],
|
3170 |
+
widgets: [
|
3171 |
+
{
|
3172 |
+
filter: "1",
|
3173 |
+
text: html,
|
3174 |
+
title: "",
|
3175 |
+
type: "visual",
|
3176 |
+
panels_info: {
|
3177 |
+
class: editorClass,
|
3178 |
+
raw: false,
|
3179 |
+
grid: 0,
|
3180 |
+
cell: 0
|
3181 |
+
}
|
3182 |
+
}
|
3183 |
+
]
|
3184 |
+
};
|
3185 |
+
}
|
3186 |
+
}
|
3187 |
+
} );
|
3188 |
+
|
3189 |
+
},{}],18:[function(require,module,exports){
|
3190 |
+
module.exports = Backbone.Model.extend( {
|
3191 |
+
/* A collection of widgets */
|
3192 |
+
widgets: {},
|
3193 |
+
|
3194 |
+
/* The row this model belongs to */
|
3195 |
+
row: null,
|
3196 |
+
|
3197 |
+
defaults: {
|
3198 |
+
weight: 0,
|
3199 |
+
style: {}
|
3200 |
+
},
|
3201 |
+
|
3202 |
+
indexes: null,
|
3203 |
+
|
3204 |
+
/**
|
3205 |
+
* Set up the cell model
|
3206 |
+
*/
|
3207 |
+
initialize: function () {
|
3208 |
+
this.set( 'widgets', new panels.collection.widgets() );
|
3209 |
+
this.on( 'destroy', this.onDestroy, this );
|
3210 |
+
},
|
3211 |
+
|
3212 |
+
/**
|
3213 |
+
* Triggered when we destroy a cell
|
3214 |
+
*/
|
3215 |
+
onDestroy: function () {
|
3216 |
+
// Destroy all the widgets
|
3217 |
+
_.invoke( this.get('widgets').toArray(), 'destroy' );
|
3218 |
+
this.get('widgets').reset();
|
3219 |
+
},
|
3220 |
+
|
3221 |
+
/**
|
3222 |
+
* Create a clone of the cell, along with all its widgets
|
3223 |
+
*/
|
3224 |
+
clone: function ( row, cloneOptions ) {
|
3225 |
+
if ( _.isUndefined( row ) ) {
|
3226 |
+
row = this.row;
|
3227 |
+
}
|
3228 |
+
cloneOptions = _.extend( {cloneWidgets: true}, cloneOptions );
|
3229 |
+
|
3230 |
+
var clone = new this.constructor( this.attributes );
|
3231 |
+
clone.set( 'collection', row.get('cells'), {silent: true} );
|
3232 |
+
clone.row = row;
|
3233 |
+
|
3234 |
+
if ( cloneOptions.cloneWidgets ) {
|
3235 |
+
// Now we're going add all the widgets that belong to this, to the clone
|
3236 |
+
this.get('widgets').each( function ( widget ) {
|
3237 |
+
clone.get('widgets').add( widget.clone( clone, cloneOptions ), {silent: true} );
|
3238 |
+
} );
|
3239 |
+
}
|
3240 |
+
|
3241 |
+
return clone;
|
3242 |
+
}
|
3243 |
+
|
3244 |
+
} );
|
3245 |
+
|
3246 |
+
},{}],19:[function(require,module,exports){
|
3247 |
+
module.exports = Backbone.Model.extend( {
|
3248 |
+
defaults: {
|
3249 |
+
text: '',
|
3250 |
+
data: '',
|
3251 |
+
time: null,
|
3252 |
+
count: 1
|
3253 |
+
}
|
3254 |
+
} );
|
3255 |
+
|
3256 |
+
},{}],20:[function(require,module,exports){
|
3257 |
+
module.exports = Backbone.Model.extend( {
|
3258 |
+
/* The builder model */
|
3259 |
+
builder: null,
|
3260 |
+
|
3261 |
+
defaults: {
|
3262 |
+
style: {}
|
3263 |
+
},
|
3264 |
+
|
3265 |
+
indexes: null,
|
3266 |
+
|
3267 |
+
/**
|
3268 |
+
* Initialize the row model
|
3269 |
+
*/
|
3270 |
+
initialize: function () {
|
3271 |
+
if ( _.isEmpty(this.get('cells') ) ) {
|
3272 |
+
this.set('cells', new panels.collection.cells());
|
3273 |
+
}
|
3274 |
+
else {
|
3275 |
+
// Make sure that the cells have this row set as their parent
|
3276 |
+
this.get('cells').each( function( cell ){
|
3277 |
+
cell.row = this;
|
3278 |
+
}.bind( this ) );
|
3279 |
+
}
|
3280 |
+
this.on( 'destroy', this.onDestroy, this );
|
3281 |
+
},
|
3282 |
+
|
3283 |
+
/**
|
3284 |
+
* Add cells to the model row
|
3285 |
+
*
|
3286 |
+
* @param newCells the updated collection of cell models
|
3287 |
+
*/
|
3288 |
+
setCells: function ( newCells ) {
|
3289 |
+
var currentCells = this.get('cells') || new panels.collection.cells();
|
3290 |
+
var cellsToRemove = [];
|
3291 |
+
|
3292 |
+
currentCells.each(function (cell, i) {
|
3293 |
+
var newCell = newCells.at(i);
|
3294 |
+
if(newCell) {
|
3295 |
+
cell.set('weight', newCell.get('weight'));
|
3296 |
+
} else {
|
3297 |
+
var newParentCell = currentCells.at( newCells.length - 1 );
|
3298 |
+
|
3299 |
+
// First move all the widgets to the new cell
|
3300 |
+
var widgetsToMove = cell.get('widgets').models.slice();
|
3301 |
+
for ( var j = 0; j < widgetsToMove.length; j++ ) {
|
3302 |
+
widgetsToMove[j].moveToCell( newParentCell, { silent: false } );
|
3303 |
+
}
|
3304 |
+
|
3305 |
+
cellsToRemove.push(cell);
|
3306 |
+
}
|
3307 |
+
});
|
3308 |
+
|
3309 |
+
_.each(cellsToRemove, function(cell) {
|
3310 |
+
currentCells.remove(cell);
|
3311 |
+
});
|
3312 |
+
|
3313 |
+
if( newCells.length > currentCells.length) {
|
3314 |
+
_.each(newCells.slice(currentCells.length, newCells.length), function (newCell) {
|
3315 |
+
// TODO: make sure row and collection is set correctly when cell is created then we can just add new cells
|
3316 |
+
newCell.set({collection: currentCells});
|
3317 |
+
newCell.row = this;
|
3318 |
+
currentCells.add(newCell);
|
3319 |
+
}.bind(this));
|
3320 |
+
}
|
3321 |
+
|
3322 |
+
// Rescale the cells when we add or remove
|
3323 |
+
this.reweightCells();
|
3324 |
+
},
|
3325 |
+
|
3326 |
+
/**
|
3327 |
+
* Make sure that all the cell weights add up to 1
|
3328 |
+
*/
|
3329 |
+
reweightCells: function () {
|
3330 |
+
var totalWeight = 0;
|
3331 |
+
var cells = this.get('cells');
|
3332 |
+
cells.each( function ( cell ) {
|
3333 |
+
totalWeight += cell.get( 'weight' );
|
3334 |
+
} );
|
3335 |
+
|
3336 |
+
cells.each( function ( cell ) {
|
3337 |
+
cell.set( 'weight', cell.get( 'weight' ) / totalWeight );
|
3338 |
+
} );
|
3339 |
+
|
3340 |
+
// This is for the row view to hook into and resize
|
3341 |
+
this.trigger( 'reweight_cells' );
|
3342 |
+
},
|
3343 |
+
|
3344 |
+
/**
|
3345 |
+
* Triggered when the model is destroyed
|
3346 |
+
*/
|
3347 |
+
onDestroy: function () {
|
3348 |
+
// Also destroy all the cells
|
3349 |
+
_.invoke( this.get('cells').toArray(), 'destroy' );
|
3350 |
+
this.get('cells').reset();
|
3351 |
+
},
|
3352 |
+
|
3353 |
+
/**
|
3354 |
+
* Create a clone of the row, along with all its cells
|
3355 |
+
*
|
3356 |
+
* @param {panels.model.builder} builder The builder model to attach this to.
|
3357 |
+
*
|
3358 |
+
* @return {panels.model.row} The cloned row.
|
3359 |
+
*/
|
3360 |
+
clone: function ( builder ) {
|
3361 |
+
if ( _.isUndefined( builder ) ) {
|
3362 |
+
builder = this.builder;
|
3363 |
+
}
|
3364 |
+
|
3365 |
+
var clone = new this.constructor( this.attributes );
|
3366 |
+
clone.set( 'collection', builder.get('rows'), {silent: true} );
|
3367 |
+
clone.builder = builder;
|
3368 |
+
|
3369 |
+
var cellClones = new panels.collection.cells();
|
3370 |
+
this.get('cells').each( function ( cell ) {
|
3371 |
+
cellClones.add( cell.clone( clone ), {silent: true} );
|
3372 |
+
} );
|
3373 |
+
|
3374 |
+
clone.set( 'cells', cellClones );
|
3375 |
+
|
3376 |
+
return clone;
|
3377 |
+
}
|
3378 |
+
} );
|
3379 |
+
|
3380 |
+
},{}],21:[function(require,module,exports){
|
3381 |
+
/**
|
3382 |
+
* Model for an instance of a widget
|
3383 |
+
*/
|
3384 |
+
module.exports = Backbone.Model.extend( {
|
3385 |
+
|
3386 |
+
cell: null,
|
3387 |
+
|
3388 |
+
defaults: {
|
3389 |
+
// The PHP Class of the widget
|
3390 |
+
class: null,
|
3391 |
+
|
3392 |
+
// Is this class missing? Missing widgets are a special case.
|
3393 |
+
missing: false,
|
3394 |
+
|
3395 |
+
// The values of the widget
|
3396 |
+
values: {},
|
3397 |
+
|
3398 |
+
// Have the current values been passed through the widgets update function
|
3399 |
+
raw: false,
|
3400 |
+
|
3401 |
+
// Visual style fields
|
3402 |
+
style: {},
|
3403 |
+
|
3404 |
+
read_only: false,
|
3405 |
+
widget_id: '',
|
3406 |
+
},
|
3407 |
+
|
3408 |
+
indexes: null,
|
3409 |
+
|
3410 |
+
initialize: function () {
|
3411 |
+
var widgetClass = this.get( 'class' );
|
3412 |
+
if ( _.isUndefined( panelsOptions.widgets[widgetClass] ) || ! panelsOptions.widgets[widgetClass].installed ) {
|
3413 |
+
this.set( 'missing', true );
|
3414 |
+
}
|
3415 |
+
},
|
3416 |
+
|
3417 |
+
/**
|
3418 |
+
* @param field
|
3419 |
+
* @returns {*}
|
3420 |
+
*/
|
3421 |
+
getWidgetField: function ( field ) {
|
3422 |
+
if ( _.isUndefined( panelsOptions.widgets[this.get( 'class' )] ) ) {
|
3423 |
+
if ( field === 'title' || field === 'description' ) {
|
3424 |
+
return panelsOptions.loc.missing_widget[field];
|
3425 |
+
} else {
|
3426 |
+
return '';
|
3427 |
+
}
|
3428 |
+
} else if ( this.has( 'label' ) && ! _.isEmpty( this.get( 'label' ) ) ) {
|
3429 |
+
// Use the label instead of the actual widget title
|
3430 |
+
return this.get( 'label' );
|
3431 |
+
} else {
|
3432 |
+
return panelsOptions.widgets[ this.get( 'class' ) ][ field ];
|
3433 |
+
}
|
3434 |
+
},
|
3435 |
+
|
3436 |
+
/**
|
3437 |
+
* Move this widget model to a new cell. Called by the views.
|
3438 |
+
*
|
3439 |
+
* @param panels.model.cell newCell
|
3440 |
+
* @param object options The options passed to the
|
3441 |
+
*
|
3442 |
+
* @return boolean Indicating if the widget was moved into a different cell
|
3443 |
+
*/
|
3444 |
+
moveToCell: function ( newCell, options, at ) {
|
3445 |
+
options = _.extend( {
|
3446 |
+
silent: true,
|
3447 |
+
}, options );
|
3448 |
+
|
3449 |
+
this.cell = newCell;
|
3450 |
+
this.collection.remove( this, options );
|
3451 |
+
newCell.get('widgets').add( this, _.extend( {
|
3452 |
+
at: at
|
3453 |
+
}, options ) );
|
3454 |
+
|
3455 |
+
// This should be used by views to reposition everything.
|
3456 |
+
this.trigger( 'move_to_cell', newCell, at );
|
3457 |
+
|
3458 |
+
return this;
|
3459 |
+
},
|
3460 |
+
|
3461 |
+
/**
|
3462 |
+
* This is basically a wrapper for set that checks if we need to trigger a change
|
3463 |
+
*/
|
3464 |
+
setValues: function ( values ) {
|
3465 |
+
var hasChanged = false;
|
3466 |
+
if ( JSON.stringify( values ) !== JSON.stringify( this.get( 'values' ) ) ) {
|
3467 |
+
hasChanged = true;
|
3468 |
+
}
|
3469 |
+
|
3470 |
+
this.set( 'values', values, {silent: true} );
|
3471 |
+
|
3472 |
+
if ( hasChanged ) {
|
3473 |
+
// We'll trigger our own change events.
|
3474 |
+
// NB: Must include the model being changed (i.e. `this`) as a workaround for a bug in Backbone 1.2.3
|
3475 |
+
this.trigger( 'change', this );
|
3476 |
+
this.trigger( 'change:values' );
|
3477 |
+
}
|
3478 |
+
},
|
3479 |
+
|
3480 |
+
/**
|
3481 |
+
* Create a clone of this widget attached to the given cell.
|
3482 |
+
*
|
3483 |
+
* @param {panels.model.cell} cell The cell model we're attaching this widget clone to.
|
3484 |
+
* @returns {panels.model.widget}
|
3485 |
+
*/
|
3486 |
+
clone: function ( cell, options ) {
|
3487 |
+
if ( _.isUndefined( cell ) ) {
|
3488 |
+
cell = this.cell;
|
3489 |
+
}
|
3490 |
+
|
3491 |
+
var clone = new this.constructor( this.attributes );
|
3492 |
+
|
3493 |
+
// Create a deep clone of the original values
|
3494 |
+
var cloneValues = JSON.parse( JSON.stringify( this.get( 'values' ) ) );
|
3495 |
+
|
3496 |
+
// We want to exclude any fields that start with _ from the clone. Assuming these are internal.
|
3497 |
+
var cleanClone = function ( vals ) {
|
3498 |
+
_.each( vals, function ( el, i ) {
|
3499 |
+
if ( _.isString( i ) && i[0] === '_' ) {
|
3500 |
+
delete vals[i];
|
3501 |
+
}
|
3502 |
+
else if ( _.isObject( vals[i] ) ) {
|
3503 |
+
cleanClone( vals[i] );
|
3504 |
+
}
|
3505 |
+
} );
|
3506 |
+
|
3507 |
+
return vals;
|
3508 |
+
};
|
3509 |
+
cloneValues = cleanClone( cloneValues );
|
3510 |
+
|
3511 |
+
if ( this.get( 'class' ) === "SiteOrigin_Panels_Widgets_Layout" ) {
|
3512 |
+
// Special case of this being a layout widget, it needs a new ID
|
3513 |
+
cloneValues.builder_id = Math.random().toString( 36 ).substr( 2 );
|
3514 |
+
}
|
3515 |
+
|
3516 |
+
clone.set( 'widget_id', '' );
|
3517 |
+
clone.set( 'values', cloneValues, {silent: true} );
|
3518 |
+
clone.set( 'collection', cell.get('widgets'), {silent: true} );
|
3519 |
+
clone.cell = cell;
|
3520 |
+
|
3521 |
+
// This is used to force a form reload later on
|
3522 |
+
clone.isDuplicate = true;
|
3523 |
+
|
3524 |
+
return clone;
|
3525 |
+
},
|
3526 |
+
|
3527 |
+
/**
|
3528 |
+
* Gets the value that makes most sense as the title.
|
3529 |
+
*/
|
3530 |
+
getTitle: function () {
|
3531 |
+
var widgetData = panelsOptions.widgets[this.get( 'class' )];
|
3532 |
+
|
3533 |
+
if ( _.isUndefined( widgetData ) ) {
|
3534 |
+
return this.get( 'class' ).replace( /_/g, ' ' );
|
3535 |
+
}
|
3536 |
+
else if ( ! _.isUndefined( widgetData.panels_title ) ) {
|
3537 |
+
// This means that the widget has told us which field it wants us to use as a title
|
3538 |
+
if ( widgetData.panels_title === false ) {
|
3539 |
+
return panelsOptions.widgets[this.get( 'class' )].description;
|
3540 |
+
}
|
3541 |
+
}
|
3542 |
+
|
3543 |
+
var values = this.get( 'values' );
|
3544 |
+
|
3545 |
+
// Create a list of fields to check for a title
|
3546 |
+
var titleFields = ['title', 'text'];
|
3547 |
+
|
3548 |
+
for ( var k in values ) {
|
3549 |
+
if(k.charAt(0) === '_' || k === 'so_sidebar_emulator_id' || k === 'option_name'){
|
3550 |
+
// Skip Widgets Bundle supporting fields
|
3551 |
+
continue;
|
3552 |
+
}
|
3553 |
+
if ( values.hasOwnProperty( k ) ) {
|
3554 |
+
titleFields.push( k );
|
3555 |
+
}
|
3556 |
+
}
|
3557 |
+
|
3558 |
+
titleFields = _.uniq( titleFields );
|
3559 |
+
|
3560 |
+
for ( var i in titleFields ) {
|
3561 |
+
if (
|
3562 |
+
! _.isUndefined( values[titleFields[i]] ) &&
|
3563 |
+
_.isString( values[titleFields[i]] ) &&
|
3564 |
+
values[titleFields[i]] !== '' &&
|
3565 |
+
values[titleFields[i]] !== 'on' &&
|
3566 |
+
titleFields[i][0] !== '_' && ! jQuery.isNumeric( values[titleFields[i]] )
|
3567 |
+
) {
|
3568 |
+
var title = values[titleFields[i]];
|
3569 |
+
title = title.replace( /<\/?[^>]+(>|$)/g, "" );
|
3570 |
+
var parts = title.split( " " );
|
3571 |
+
parts = parts.slice( 0, 20 );
|
3572 |
+
return parts.join( ' ' );
|
3573 |
+
}
|
3574 |
+
}
|
3575 |
+
|
3576 |
+
// If we still have nothing, then just return the widget description
|
3577 |
+
return this.getWidgetField( 'description' );
|
3578 |
+
}
|
3579 |
+
|
3580 |
+
} );
|
3581 |
+
|
3582 |
+
},{}],22:[function(require,module,exports){
|
3583 |
+
var panels = window.panels, $ = jQuery;
|
3584 |
+
|
3585 |
+
module.exports = Backbone.View.extend( {
|
3586 |
+
wrapperTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-context-menu' ).html() ) ),
|
3587 |
+
sectionTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-context-menu-section' ).html() ) ),
|
3588 |
+
|
3589 |
+
contexts: [],
|
3590 |
+
active: false,
|
3591 |
+
|
3592 |
+
events: {
|
3593 |
+
'keyup .so-search-wrapper input': 'searchKeyUp'
|
3594 |
+
},
|
3595 |
+
|
3596 |
+
/**
|
3597 |
+
* Intialize the context menu
|
3598 |
+
*/
|
3599 |
+
initialize: function () {
|
3600 |
+
this.listenContextMenu();
|
3601 |
+
this.render();
|
3602 |
+
this.attach();
|
3603 |
+
},
|
3604 |
+
|
3605 |
+
/**
|
3606 |
+
* Listen for the right click context menu
|
3607 |
+
*/
|
3608 |
+
listenContextMenu: function () {
|
3609 |
+
var thisView = this;
|
3610 |
+
|
3611 |
+
$( window ).on( 'contextmenu', function ( e ) {
|
3612 |
+
if ( thisView.active && ! thisView.isOverEl( thisView.$el, e ) ) {
|
3613 |
+
thisView.closeMenu();
|
3614 |
+
thisView.active = false;
|
3615 |
+
e.preventDefault();
|
3616 |
+
return false;
|
3617 |
+
}
|
3618 |
+
|
3619 |
+
if ( thisView.active ) {
|
3620 |
+
// Lets not double up on the context menu
|
3621 |
+
return true;
|
3622 |
+
}
|
3623 |
+
|
3624 |
+
// Other components should listen to activate_context
|
3625 |
+
thisView.active = false;
|
3626 |
+
thisView.trigger( 'activate_context', e, thisView );
|
3627 |
+
|
3628 |
+
if ( thisView.active ) {
|
3629 |
+
// We don't want the default event to happen.
|
3630 |
+
e.preventDefault();
|
3631 |
+
|
3632 |
+
thisView.openMenu( {
|
3633 |
+
left: e.pageX,
|
3634 |
+
top: e.pageY
|
3635 |
+
} );
|
3636 |
+
}
|
3637 |
+
} );
|
3638 |
+
},
|
3639 |
+
|
3640 |
+
render: function () {
|
3641 |
+
this.setElement( this.wrapperTemplate() );
|
3642 |
+
},
|
3643 |
+
|
3644 |
+
attach: function () {
|
3645 |
+
this.$el.appendTo( 'body' );
|
3646 |
+
},
|
3647 |
+
|
3648 |
+
/**
|
3649 |
+
* Display the actual context menu.
|
3650 |
+
*
|
3651 |
+
* @param position
|
3652 |
+
*/
|
3653 |
+
openMenu: function ( position ) {
|
3654 |
+
this.trigger( 'open_menu' );
|
3655 |
+
|
3656 |
+
// Start listening for situations when we should close the menu
|
3657 |
+
$( window ).on( 'keyup', {menu: this}, this.keyboardListen );
|
3658 |
+
$( window ).on( 'click', {menu: this}, this.clickOutsideListen );
|
3659 |
+
|
3660 |
+
// Set the maximum height of the menu
|
3661 |
+
this.$el.css( 'max-height', $( window ).height() - 20 );
|
3662 |
+
|
3663 |
+
// Correct the left position
|
3664 |
+
if ( position.left + this.$el.outerWidth() + 10 >= $( window ).width() ) {
|
3665 |
+
position.left = $( window ).width() - this.$el.outerWidth() - 10;
|
3666 |
+
}
|
3667 |
+
if ( position.left <= 0 ) {
|
3668 |
+
position.left = 10;
|
3669 |
+
}
|
3670 |
+
|
3671 |
+
// Check top position
|
3672 |
+
if ( position.top + this.$el.outerHeight() - $( window ).scrollTop() + 10 >= $( window ).height() ) {
|
3673 |
+
position.top = $( window ).height() + $( window ).scrollTop() - this.$el.outerHeight() - 10;
|
3674 |
+
}
|
3675 |
+
if ( position.left <= 0 ) {
|
3676 |
+
position.left = 10;
|
3677 |
+
}
|
3678 |
+
|
3679 |
+
// position the contextual menu
|
3680 |
+
this.$el.css( {
|
3681 |
+
left: position.left + 1,
|
3682 |
+
top: position.top + 1
|
3683 |
+
} ).show();
|
3684 |
+
this.$( '.so-search-wrapper input' ).focus();
|
3685 |
+
},
|
3686 |
+
|
3687 |
+
closeMenu: function () {
|
3688 |
+
this.trigger( 'close_menu' );
|
3689 |
+
|
3690 |
+
// Stop listening for situations when we should close the menu
|
3691 |
+
$( window ).off( 'keyup', this.keyboardListen );
|
3692 |
+
$( window ).off( 'click', this.clickOutsideListen );
|
3693 |
+
|
3694 |
+
this.active = false;
|
3695 |
+
this.$el.empty().hide();
|
3696 |
+
},
|
3697 |
+
|
3698 |
+
/**
|
3699 |
+
* Keyboard events handler
|
3700 |
+
*/
|
3701 |
+
keyboardListen: function ( e ) {
|
3702 |
+
var menu = e.data.menu;
|
3703 |
+
|
3704 |
+
switch ( e.which ) {
|
3705 |
+
case 27:
|
3706 |
+
menu.closeMenu();
|
3707 |
+
break;
|
3708 |
+
}
|
3709 |
+
},
|
3710 |
+
|
3711 |
+
/**
|
3712 |
+
* Listen for a click outside the menu to close it.
|
3713 |
+
* @param e
|
3714 |
+
*/
|
3715 |
+
clickOutsideListen: function ( e ) {
|
3716 |
+
var menu = e.data.menu;
|
3717 |
+
if ( e.which !== 3 && menu.$el.is( ':visible' ) && ! menu.isOverEl( menu.$el, e ) ) {
|
3718 |
+
menu.closeMenu();
|
3719 |
+
}
|
3720 |
+
},
|
3721 |
+
|
3722 |
+
/**
|
3723 |
+
* Add a new section to the contextual menu.
|
3724 |
+
*
|
3725 |
+
* @param settings
|
3726 |
+
* @param items
|
3727 |
+
* @param callback
|
3728 |
+
*/
|
3729 |
+
addSection: function ( id, settings, items, callback ) {
|
3730 |
+
var thisView = this;
|
3731 |
+
settings = _.extend( {
|
3732 |
+
display: 5,
|
3733 |
+
defaultDisplay: false,
|
3734 |
+
search: true,
|
3735 |
+
|
3736 |
+
// All the labels
|
3737 |
+
sectionTitle: '',
|
3738 |
+
searchPlaceholder: '',
|
3739 |
+
|
3740 |
+
// This is the key to be used in items for the title. Makes it easier to list objects
|
3741 |
+
titleKey: 'title'
|
3742 |
+
}, settings );
|
3743 |
+
|
3744 |
+
// Create the new section
|
3745 |
+
var section = $( this.sectionTemplate( {
|
3746 |
+
settings: settings,
|
3747 |
+
items: items
|
3748 |
+
} ) ).attr( 'id', 'panels-menu-section-' + id );
|
3749 |
+
this.$el.append( section );
|
3750 |
+
|
3751 |
+
section.find( '.so-item:not(.so-confirm)' ).click( function () {
|
3752 |
+
var $$ = $( this );
|
3753 |
+
callback( $$.data( 'key' ) );
|
3754 |
+
thisView.closeMenu();
|
3755 |
+
} );
|
3756 |
+
|
3757 |
+
section.find( '.so-item.so-confirm' ).click( function () {
|
3758 |
+
var $$ = $( this );
|
3759 |
+
|
3760 |
+
if ( $$.hasClass( 'so-confirming' ) ) {
|
3761 |
+
callback( $$.data( 'key' ) );
|
3762 |
+
thisView.closeMenu();
|
3763 |
+
return;
|
3764 |
+
}
|
3765 |
+
|
3766 |
+
$$
|
3767 |
+
.data( 'original-text', $$.html() )
|
3768 |
+
.addClass( 'so-confirming' )
|
3769 |
+
.html( '<span class="dashicons dashicons-yes"></span> ' + panelsOptions.loc.dropdown_confirm );
|
3770 |
+
|
3771 |
+
setTimeout( function () {
|
3772 |
+
$$.removeClass( 'so-confirming' );
|
3773 |
+
$$.html( $$.data( 'original-text' ) );
|
3774 |
+
}, 2500 );
|
3775 |
+
} );
|
3776 |
+
|
3777 |
+
section.data( 'settings', settings ).find( '.so-search-wrapper input' ).trigger( 'keyup' );
|
3778 |
+
|
3779 |
+
this.active = true;
|
3780 |
+
},
|
3781 |
+
|
3782 |
+
/**
|
3783 |
+
* Check if a section exists in the current menu.
|
3784 |
+
*
|
3785 |
+
* @param id
|
3786 |
+
* @returns {boolean}
|
3787 |
+
*/
|
3788 |
+
hasSection: function( id ){
|
3789 |
+
return this.$el.find( '#panels-menu-section-' + id ).length > 0;
|
3790 |
+
},
|
3791 |
+
|
3792 |
+
/**
|
3793 |
+
* Handle searching inside a section.
|
3794 |
+
*
|
3795 |
+
* @param e
|
3796 |
+
* @returns {boolean}
|
3797 |
+
*/
|
3798 |
+
searchKeyUp: function ( e ) {
|
3799 |
+
var
|
3800 |
+
$$ = $( e.currentTarget ),
|
3801 |
+
section = $$.closest( '.so-section' ),
|
3802 |
+
settings = section.data( 'settings' );
|
3803 |
+
|
3804 |
+
if ( e.which === 38 || e.which === 40 ) {
|
3805 |
+
// First, lets check if this is an up, down or enter press
|
3806 |
+
var
|
3807 |
+
items = section.find( 'ul li:visible' ),
|
3808 |
+
activeItem = items.filter( '.so-active' ).eq( 0 );
|
3809 |
+
|
3810 |
+
if ( activeItem.length ) {
|
3811 |
+
items.removeClass( 'so-active' );
|
3812 |
+
|
3813 |
+
var activeIndex = items.index( activeItem );
|
3814 |
+
|
3815 |
+
if ( e.which === 38 ) {
|
3816 |
+
if ( activeIndex - 1 < 0 ) {
|
3817 |
+
activeItem = items.last();
|
3818 |
+
} else {
|
3819 |
+
activeItem = items.eq( activeIndex - 1 );
|
3820 |
+
}
|
3821 |
+
}
|
3822 |
+
else if ( e.which === 40 ) {
|
3823 |
+
if ( activeIndex + 1 >= items.length ) {
|
3824 |
+
activeItem = items.first();
|
3825 |
+
} else {
|
3826 |
+
activeItem = items.eq( activeIndex + 1 );
|
3827 |
+
}
|
3828 |
+
}
|
3829 |
+
}
|
3830 |
+
else if ( e.which === 38 ) {
|
3831 |
+
activeItem = items.last();
|
3832 |
+
}
|
3833 |
+
else if ( e.which === 40 ) {
|
3834 |
+
activeItem = items.first();
|
3835 |
+
}
|
3836 |
+
|
3837 |
+
activeItem.addClass( 'so-active' );
|
3838 |
+
return false;
|
3839 |
+
}
|
3840 |
+
if ( e.which === 13 ) {
|
3841 |
+
if ( section.find( 'ul li:visible' ).length === 1 ) {
|
3842 |
+
// We'll treat a single visible item as active when enter is clicked
|
3843 |
+
section.find( 'ul li:visible' ).trigger( 'click' );
|
3844 |
+
return false;
|
3845 |
+
}
|
3846 |
+
section.find( 'ul li.so-active:visible' ).trigger( 'click' );
|
3847 |
+
return false;
|
3848 |
+
}
|
3849 |
+
|
3850 |
+
if ( $$.val() === '' ) {
|
3851 |
+
// We'll display the defaultDisplay items
|
3852 |
+
if ( settings.defaultDisplay ) {
|
3853 |
+
section.find( '.so-item' ).hide();
|
3854 |
+
for ( var i = 0; i < settings.defaultDisplay.length; i ++ ) {
|
3855 |
+
section.find( '.so-item[data-key="' + settings.defaultDisplay[i] + '"]' ).show();
|
3856 |
+
}
|
3857 |
+
} else {
|
3858 |
+
// We'll just display all the items
|
3859 |
+
section.find( '.so-item' ).show();
|
3860 |
+
}
|
3861 |
+
} else {
|
3862 |
+
section.find( '.so-item' ).hide().each( function () {
|
3863 |
+
var item = $( this );
|
3864 |
+
if ( item.html().toLowerCase().indexOf( $$.val().toLowerCase() ) !== - 1 ) {
|
3865 |
+
item.show();
|
3866 |
+
}
|
3867 |
+
} );
|
3868 |
+
}
|
3869 |
+
|
3870 |
+
// Now, we'll only show the first settings.display visible items
|
3871 |
+
section.find( '.so-item:visible:gt(' + (
|
3872 |
+
settings.display - 1
|
3873 |
+
) + ')' ).hide();
|
3874 |
+
|
3875 |
+
|
3876 |
+
if ( section.find( '.so-item:visible' ).length === 0 && $$.val() !== '' ) {
|
3877 |
+
section.find( '.so-no-results' ).show();
|
3878 |
+
} else {
|
3879 |
+
section.find( '.so-no-results' ).hide();
|
3880 |
+
}
|
3881 |
+
},
|
3882 |
+
|
3883 |
+
/**
|
3884 |
+
* Check if the given mouse event is over the element
|
3885 |
+
* @param el
|
3886 |
+
* @param event
|
3887 |
+
*/
|
3888 |
+
isOverEl: function ( el, event ) {
|
3889 |
+
var elPos = [
|
3890 |
+
[el.offset().left, el.offset().top],
|
3891 |
+
[el.offset().left + el.outerWidth(), el.offset().top + el.outerHeight()]
|
3892 |
+
];
|
3893 |
+
|
3894 |
+
// Return if this event is over the given element
|
3895 |
+
return (
|
3896 |
+
event.pageX >= elPos[0][0] && event.pageX <= elPos[1][0] &&
|
3897 |
+
event.pageY >= elPos[0][1] && event.pageY <= elPos[1][1]
|
3898 |
+
);
|
3899 |
+
}
|
3900 |
+
|
3901 |
+
} );
|
3902 |
+
|
3903 |
+
},{}],23:[function(require,module,exports){
|
3904 |
+
var panels = window.panels, $ = jQuery;
|
3905 |
+
|
3906 |
+
module.exports = Backbone.View.extend( {
|
3907 |
+
|
3908 |
+
// Config options
|
3909 |
+
config: {},
|
3910 |
+
|
3911 |
+
template: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-builder' ).html() ) ),
|
3912 |
+
dialogs: {},
|
3913 |
+
rowsSortable: null,
|
3914 |
+
dataField: false,
|
3915 |
+
currentData: '',
|
3916 |
+
|
3917 |
+
attachedToEditor: false,
|
3918 |
+
attachedVisible: false,
|
3919 |
+
liveEditor: undefined,
|
3920 |
+
menu: false,
|
3921 |
+
|
3922 |
+
activeCell: null,
|
3923 |
+
|
3924 |
+
events: {
|
3925 |
+
'click .so-tool-button.so-widget-add': 'displayAddWidgetDialog',
|
3926 |
+
'click .so-tool-button.so-row-add': 'displayAddRowDialog',
|
3927 |
+
'click .so-tool-button.so-prebuilt-add': 'displayAddPrebuiltDialog',
|
3928 |
+
'click .so-tool-button.so-history': 'displayHistoryDialog',
|
3929 |
+
'click .so-tool-button.so-live-editor': 'displayLiveEditor'
|
3930 |
+
},
|
3931 |
+
|
3932 |
+
/* A row collection */
|
3933 |
+
rows: null,
|
3934 |
+
|
3935 |
+
/**
|
3936 |
+
* Initialize the builder
|
3937 |
+
*/
|
3938 |
+
initialize: function ( options ) {
|
3939 |
+
var builder = this;
|
3940 |
+
|
3941 |
+
this.config = _.extend( {
|
3942 |
+
loadLiveEditor: false,
|
3943 |
+
builderSupports: {}
|
3944 |
+
}, options.config );
|
3945 |
+
|
3946 |
+
// These are the actions that a user can perform in the builder
|
3947 |
+
this.config.builderSupports = _.extend( {
|
3948 |
+
addRow: true,
|
3949 |
+
editRow: true,
|
3950 |
+
deleteRow: true,
|
3951 |
+
moveRow: true,
|
3952 |
+
addWidget: true,
|
3953 |
+
editWidget: true,
|
3954 |
+
deleteWidget: true,
|
3955 |
+
moveWidget: true,
|
3956 |
+
prebuilt: true,
|
3957 |
+
history: true,
|
3958 |
+
liveEditor: true,
|
3959 |
+
revertToEditor: true
|
3960 |
+
}, this.config.builderSupports );
|
3961 |
+
|
3962 |
+
// Automatically load the live editor as soon as it's ready
|
3963 |
+
if ( options.config.loadLiveEditor ) {
|
3964 |
+
this.on( 'builder_live_editor_added', function () {
|
3965 |
+
this.displayLiveEditor();
|
3966 |
+
} );
|
3967 |
+
}
|
3968 |
+
|
3969 |
+
// Now lets create all the dialog boxes that the main builder interface uses
|
3970 |
+
this.dialogs = {
|
3971 |
+
widgets: new panels.dialog.widgets(),
|
3972 |
+
row: new panels.dialog.row(),
|
3973 |
+
prebuilt: new panels.dialog.prebuilt()
|
3974 |
+
};
|
3975 |
+
|
3976 |
+
// Set the builder for each dialog and render it.
|
3977 |
+
_.each( this.dialogs, function ( p, i, d ) {
|
3978 |
+
d[ i ].setBuilder( builder );
|
3979 |
+
} );
|
3980 |
+
|
3981 |
+
this.dialogs.row.setRowDialogType( 'create' );
|
3982 |
+
|
3983 |
+
// This handles a new row being added to the collection - we'll display it in the interface
|
3984 |
+
this.listenTo( this.model.get( 'rows' ), 'add', this.onAddRow );
|
3985 |
+
|
3986 |
+
// Reflow the entire builder when ever the
|
3987 |
+
$( window ).resize( function ( e ) {
|
3988 |
+
if ( e.target === window ) {
|
3989 |
+
builder.trigger( 'builder_resize' );
|
3990 |
+
}
|
3991 |
+
} );
|
3992 |
+
|
3993 |
+
// When the data changes in the model, store it in the field
|
3994 |
+
this.listenTo( this.model, 'change:data load_panels_data', this.storeModelData );
|
3995 |
+
this.listenTo( this.model, 'change:data load_panels_data', this.toggleWelcomeDisplay );
|
3996 |
+
|
3997 |
+
// Handle a content change
|
3998 |
+
this.on( 'content_change', this.handleContentChange, this );
|
3999 |
+
this.on( 'display_builder', this.handleDisplayBuilder, this );
|
4000 |
+
this.on( 'hide_builder', this.handleHideBuilder, this );
|
4001 |
+
this.on( 'builder_rendered builder_resize', this.handleBuilderSizing, this );
|
4002 |
+
|
4003 |
+
this.on( 'display_builder', this.wrapEditorExpandAdjust, this );
|
4004 |
+
|
4005 |
+
// Create the context menu for this builder
|
4006 |
+
this.menu = new panels.utils.menu( {} );
|
4007 |
+
this.listenTo( this.menu, 'activate_context', this.activateContextMenu )
|
4008 |
+
|
4009 |
+
if ( this.config.loadOnAttach ) {
|
4010 |
+
this.on( 'builder_attached_to_editor', function () {
|
4011 |
+
this.displayAttachedBuilder( { confirm: false } );
|
4012 |
+
}, this );
|
4013 |
+
}
|
4014 |
+
|
4015 |
+
return this;
|
4016 |
+
},
|
4017 |
+
|
4018 |
+
/**
|
4019 |
+
* Render the builder interface.
|
4020 |
+
*
|
4021 |
+
* @return {panels.view.builder}
|
4022 |
+
*/
|
4023 |
+
render: function () {
|
4024 |
+
// this.$el.html( this.template() );
|
4025 |
+
this.setElement( this.template() );
|
4026 |
+
this.$el
|
4027 |
+
.attr( 'id', 'siteorigin-panels-builder-' + this.cid )
|
4028 |
+
.addClass( 'so-builder-container' );
|
4029 |
+
|
4030 |
+
this.trigger( 'builder_rendered' );
|
4031 |
+
|
4032 |
+
return this;
|
4033 |
+
},
|
4034 |
+
|
4035 |
+
/**
|
4036 |
+
* Attach the builder to the given container
|
4037 |
+
*
|
4038 |
+
* @param container
|
4039 |
+
* @returns {panels.view.builder}
|
4040 |
+
*/
|
4041 |
+
attach: function ( options ) {
|
4042 |
+
|
4043 |
+
options = _.extend( {
|
4044 |
+
container: false,
|
4045 |
+
dialog: false
|
4046 |
+
}, options );
|
4047 |
+
|
4048 |
+
if ( options.dialog ) {
|
4049 |
+
// We're going to add this to a dialog
|
4050 |
+
this.dialog = new panels.dialog.builder();
|
4051 |
+
this.dialog.builder = this;
|
4052 |
+
} else {
|
4053 |
+
// Attach this in the standard way
|
4054 |
+
this.$el.appendTo( options.container );
|
4055 |
+
this.metabox = options.container.closest( '.postbox' );
|
4056 |
+
this.initSortable();
|
4057 |
+
this.trigger( 'attached_to_container', options.container );
|
4058 |
+
}
|
4059 |
+
|
4060 |
+
this.trigger( 'builder_attached' );
|
4061 |
+
|
4062 |
+
// Add support for components we have
|
4063 |
+
|
4064 |
+
if ( this.supports( 'liveEditor' ) ) {
|
4065 |
+
this.addLiveEditor();
|
4066 |
+
}
|
4067 |
+
if ( this.supports( 'history' ) ) {
|
4068 |
+
this.addHistoryBrowser();
|
4069 |
+
}
|
4070 |
+
|
4071 |
+
// Hide toolbar buttons we don't support
|
4072 |
+
var toolbar = this.$( '.so-builder-toolbar' );
|
4073 |
+
var welcomeMessageContainer = this.$( '.so-panels-welcome-message' );
|
4074 |
+
var welcomeMessage = panelsOptions.loc.welcomeMessage;
|
4075 |
+
|
4076 |
+
var supportedItems = [];
|
4077 |
+
|
4078 |
+
if ( !this.supports( 'addWidget' ) ) {
|
4079 |
+
toolbar.find( '.so-widget-add' ).hide();
|
4080 |
+
} else {
|
4081 |
+
supportedItems.push( welcomeMessage.addWidgetButton );
|
4082 |
+
}
|
4083 |
+
if ( !this.supports( 'addRow' ) ) {
|
4084 |
+
toolbar.find( '.so-row-add' ).hide();
|
4085 |
+
} else {
|
4086 |
+
supportedItems.push( welcomeMessage.addRowButton );
|
4087 |
+
}
|
4088 |
+
if ( !this.supports( 'prebuilt' ) ) {
|
4089 |
+
toolbar.find( '.so-prebuilt-add' ).hide();
|
4090 |
+
} else {
|
4091 |
+
supportedItems.push( welcomeMessage.addPrebuiltButton );
|
4092 |
+
}
|
4093 |
+
|
4094 |
+
var msg = '';
|
4095 |
+
if ( supportedItems.length === 3 ) {
|
4096 |
+
msg = welcomeMessage.threeEnabled;
|
4097 |
+
} else if ( supportedItems.length === 2 ) {
|
4098 |
+
msg = welcomeMessage.twoEnabled;
|
4099 |
+
} else if ( supportedItems.length === 1 ) {
|
4100 |
+
msg = welcomeMessage.oneEnabled;
|
4101 |
+
} else if ( supportedItems.length === 0 ) {
|
4102 |
+
msg = welcomeMessage.addingDisabled;
|
4103 |
+
}
|
4104 |
+
|
4105 |
+
var resTemplate = _.template( panels.helpers.utils.processTemplate( msg ) );
|
4106 |
+
var msgHTML = resTemplate( { items: supportedItems } ) + ' ' + welcomeMessage.docsMessage;
|
4107 |
+
welcomeMessageContainer.find( '.so-message-wrapper' ).html( msgHTML );
|
4108 |
+
|
4109 |
+
return this;
|
4110 |
+
},
|
4111 |
+
|
4112 |
+
/**
|
4113 |
+
* This will move the Page Builder meta box into the editor if we're in the post/page edit interface.
|
4114 |
+
*
|
4115 |
+
* @returns {panels.view.builder}
|
4116 |
+
*/
|
4117 |
+
attachToEditor: function () {
|
4118 |
+
if ( this.config.editorType !== 'tinyMCE' ) {
|
4119 |
+
return this;
|
4120 |
+
}
|
4121 |
+
|
4122 |
+
this.attachedToEditor = true;
|
4123 |
+
var metabox = this.metabox;
|
4124 |
+
var thisView = this;
|
4125 |
+
|
4126 |
+
// Handle switching between the page builder and other tabs
|
4127 |
+
$( '#wp-content-wrap .wp-editor-tabs' )
|
4128 |
+
.find( '.wp-switch-editor' )
|
4129 |
+
.click( function ( e ) {
|
4130 |
+
e.preventDefault();
|
4131 |
+
$( '#wp-content-editor-container' ).show();
|
4132 |
+
|
4133 |
+
// metabox.hide();
|
4134 |
+
$( '#wp-content-wrap' ).removeClass( 'panels-active' );
|
4135 |
+
$( '#content-resize-handle' ).show();
|
4136 |
+
|
4137 |
+
// Make sure the word count is visible
|
4138 |
+
thisView.trigger( 'hide_builder' );
|
4139 |
+
} ).end()
|
4140 |
+
.append(
|
4141 |
+
$( '<button type="button" id="content-panels" class="hide-if-no-js wp-switch-editor switch-panels">' + metabox.find( '.hndle span' ).html() + '</button>' )
|
4142 |
+
.click( function ( e ) {
|
4143 |
+
if ( thisView.displayAttachedBuilder( { confirm: true } ) ) {
|
4144 |
+
e.preventDefault();
|
4145 |
+
}
|
4146 |
+
} )
|
4147 |
+
);
|
4148 |
+
|
4149 |
+
// Switch back to the standard editor
|
4150 |
+
if ( this.supports( 'revertToEditor' ) ) {
|
4151 |
+
metabox.find( '.so-switch-to-standard' ).click( function ( e ) {
|
4152 |
+
e.preventDefault();
|
4153 |
+
|
4154 |
+
if ( !confirm( panelsOptions.loc.confirm_stop_builder ) ) {
|
4155 |
+
return;
|
4156 |
+
}
|
4157 |
+
|
4158 |
+
// User is switching to the standard visual editor
|
4159 |
+
thisView.addHistoryEntry( 'back_to_editor' );
|
4160 |
+
thisView.model.loadPanelsData( false );
|
4161 |
+
|
4162 |
+
// Switch back to the standard editor
|
4163 |
+
$( '#wp-content-wrap' ).show();
|
4164 |
+
metabox.hide();
|
4165 |
+
|
4166 |
+
// Resize to trigger reflow of WordPress editor stuff
|
4167 |
+
$( window ).resize();
|
4168 |
+
|
4169 |
+
thisView.attachedVisible = false;
|
4170 |
+
thisView.trigger( 'hide_builder' );
|
4171 |
+
} ).show();
|
4172 |
+
}
|
4173 |
+
|
4174 |
+
// Move the panels box into a tab of the content editor
|
4175 |
+
metabox.insertAfter( '#wp-content-wrap' ).hide().addClass( 'attached-to-editor' );
|
4176 |
+
|
4177 |
+
// Switch to the Page Builder interface as soon as we load the page if there are widgets or the normal editor
|
4178 |
+
// isn't supported.
|
4179 |
+
var data = this.model.get( 'data' );
|
4180 |
+
if ( !_.isEmpty( data.widgets ) || !_.isEmpty( data.grids ) || !this.supports( 'revertToEditor' ) ) {
|
4181 |
+
this.displayAttachedBuilder( { confirm: false } );
|
4182 |
+
}
|
4183 |
+
|
4184 |
+
// We will also make this sticky if its attached to an editor.
|
4185 |
+
var stickToolbar = function () {
|
4186 |
+
var toolbar = thisView.$( '.so-builder-toolbar' );
|
4187 |
+
|
4188 |
+
if ( thisView.$el.hasClass( 'so-display-narrow' ) ) {
|
4189 |
+
// In this case, we don't want to stick the toolbar.
|
4190 |
+
toolbar.css( {
|
4191 |
+
top: 0,
|
4192 |
+
left: 0,
|
4193 |
+
width: '100%',
|
4194 |
+
position: 'absolute'
|
4195 |
+
} );
|
4196 |
+
thisView.$el.css( 'padding-top', toolbar.outerHeight() );
|
4197 |
+
return;
|
4198 |
+
}
|
4199 |
+
|
4200 |
+
var newTop = $( window ).scrollTop() - thisView.$el.offset().top;
|
4201 |
+
|
4202 |
+
if ( $( '#wpadminbar' ).css( 'position' ) === 'fixed' ) {
|
4203 |
+
newTop += $( '#wpadminbar' ).outerHeight();
|
4204 |
+
}
|
4205 |
+
|
4206 |
+
var limits = {
|
4207 |
+
top: 0,
|
4208 |
+
bottom: thisView.$el.outerHeight() - toolbar.outerHeight() + 20
|
4209 |
+
};
|
4210 |
+
|
4211 |
+
if ( newTop > limits.top && newTop < limits.bottom ) {
|
4212 |
+
if ( toolbar.css( 'position' ) !== 'fixed' ) {
|
4213 |
+
// The toolbar needs to stick to the top, over the interface
|
4214 |
+
toolbar.css( {
|
4215 |
+
top: $( '#wpadminbar' ).outerHeight(),
|
4216 |
+
left: thisView.$el.offset().left,
|
4217 |
+
width: thisView.$el.outerWidth(),
|
4218 |
+
position: 'fixed'
|
4219 |
+
} );
|
4220 |
+
}
|
4221 |
+
} else {
|
4222 |
+
// The toolbar needs to be at the top or bottom of the interface
|
4223 |
+
toolbar.css( {
|
4224 |
+
top: Math.min( Math.max( newTop, 0 ), thisView.$el.outerHeight() - toolbar.outerHeight() + 20 ),
|
4225 |
+
left: 0,
|
4226 |
+
width: '100%',
|
4227 |
+
position: 'absolute'
|
4228 |
+
} );
|
4229 |
+
}
|
4230 |
+
|
4231 |
+
thisView.$el.css( 'padding-top', toolbar.outerHeight() );
|
4232 |
+
};
|
4233 |
+
|
4234 |
+
this.on( 'builder_resize', stickToolbar, this );
|
4235 |
+
$( document ).scroll( stickToolbar );
|
4236 |
+
stickToolbar();
|
4237 |
+
|
4238 |
+
this.trigger( 'builder_attached_to_editor' );
|
4239 |
+
|
4240 |
+
return this;
|
4241 |
+
},
|
4242 |
+
|
4243 |
+
/**
|
4244 |
+
* Display the builder interface when attached to a WordPress editor
|
4245 |
+
*/
|
4246 |
+
displayAttachedBuilder: function ( options ) {
|
4247 |
+
options = _.extend( {
|
4248 |
+
confirm: true
|
4249 |
+
}, options );
|
4250 |
+
|
4251 |
+
// Switch to the Page Builder interface
|
4252 |
+
|
4253 |
+
if ( options.confirm ) {
|
4254 |
+
var editor = typeof tinyMCE !== 'undefined' ? tinyMCE.get( 'content' ) : false;
|
4255 |
+
var editorContent = ( editor && _.isFunction( editor.getContent ) ) ? editor.getContent() : $( 'textarea#content' ).val();
|
4256 |
+
|
4257 |
+
if ( editorContent !== '' && !confirm( panelsOptions.loc.confirm_use_builder ) ) {
|
4258 |
+
return false;
|
4259 |
+
}
|
4260 |
+
}
|
4261 |
+
|
4262 |
+
// Hide the standard content editor
|
4263 |
+
$( '#wp-content-wrap' ).hide();
|
4264 |
+
|
4265 |
+
|
4266 |
+
$( '#editor-expand-toggle' ).on( 'change.editor-expand', function () {
|
4267 |
+
if ( !$( this ).prop( 'checked' ) ) {
|
4268 |
+
$( '#wp-content-wrap' ).hide();
|
4269 |
+
}
|
4270 |
+
} );
|
4271 |
+
|
4272 |
+
// Show page builder and the inside div
|
4273 |
+
this.metabox.show().find( '> .inside' ).show();
|
4274 |
+
|
4275 |
+
// Triggers full refresh
|
4276 |
+
$( window ).resize();
|
4277 |
+
$( document ).scroll();
|
4278 |
+
|
4279 |
+
// Make sure the word count is visible
|
4280 |
+
this.attachedVisible = true;
|
4281 |
+
this.trigger( 'display_builder' );
|
4282 |
+
|
4283 |
+
return true;
|
4284 |
+
},
|
4285 |
+
|
4286 |
+
/**
|
4287 |
+
* Initialize the row sortables
|
4288 |
+
*/
|
4289 |
+
initSortable: function () {
|
4290 |
+
if ( !this.supports( 'moveRow' ) ) {
|
4291 |
+
return this;
|
4292 |
+
}
|
4293 |
+
|
4294 |
+
var builderView = this;
|
4295 |
+
var builderID = builderView.$el.attr( 'id' );
|
4296 |
+
|
4297 |
+
// Create the sortable for the rows
|
4298 |
+
this.rowsSortable = this.$( '.so-rows-container' ).sortable( {
|
4299 |
+
appendTo: '#wpwrap',
|
4300 |
+
items: '.so-row-container',
|
4301 |
+
handle: '.so-row-move',
|
4302 |
+
// For the block editor, where it's possible to have multiple Page Builder blocks on a page.
|
4303 |
+
// Also specify builderID when not in the block editor to prevent being able to drop rows from builder in a dialog
|
4304 |
+
// into builder on the page under the dialog.
|
4305 |
+
connectWith: '#' + builderID + '.so-rows-container,.block-editor .so-rows-container',
|
4306 |
+
axis: 'y',
|
4307 |
+
tolerance: 'pointer',
|
4308 |
+
scroll: false,
|
4309 |
+
remove: function ( e, ui ) {
|
4310 |
+
builderView.model.get( 'rows' ).remove(
|
4311 |
+
$( ui.item ).data( 'view' ).model,
|
4312 |
+
{ silent: true }
|
4313 |
+
);
|
4314 |
+
builderView.model.refreshPanelsData();
|
4315 |
+
},
|
4316 |
+
receive: function ( e, ui ) {
|
4317 |
+
builderView.model.get( 'rows' ).add(
|
4318 |
+
$( ui.item ).data( 'view' ).model,
|
4319 |
+
{ silent: true, at: $( ui.item ).index() }
|
4320 |
+
);
|
4321 |
+
builderView.model.refreshPanelsData();
|
4322 |
+
},
|
4323 |
+
stop: function ( e, ui ) {
|
4324 |
+
var $$ = $( ui.item ),
|
4325 |
+
row = $$.data( 'view' ),
|
4326 |
+
rows = builderView.model.get( 'rows' );
|
4327 |
+
|
4328 |
+
// If this hasn't already been removed and added to a different builder.
|
4329 |
+
if ( rows.get( row.model ) ) {
|
4330 |
+
builderView.addHistoryEntry( 'row_moved' );
|
4331 |
+
|
4332 |
+
rows.remove( row.model, {
|
4333 |
+
'silent': true
|
4334 |
+
} );
|
4335 |
+
rows.add( row.model, {
|
4336 |
+
'silent': true,
|
4337 |
+
'at': $$.index()
|
4338 |
+
} );
|
4339 |
+
|
4340 |
+
row.trigger( 'move', $$.index() );
|
4341 |
+
|
4342 |
+
builderView.model.refreshPanelsData();
|
4343 |
+
}
|
4344 |
+
}
|
4345 |
+
} );
|
4346 |
+
|
4347 |
+
return this;
|
4348 |
+
},
|
4349 |
+
|
4350 |
+
/**
|
4351 |
+
* Refresh the row sortable
|
4352 |
+
*/
|
4353 |
+
refreshSortable: function () {
|
4354 |
+
// Refresh the sortable to account for the new row
|
4355 |
+
if ( !_.isNull( this.rowsSortable ) ) {
|
4356 |
+
this.rowsSortable.sortable( 'refresh' );
|
4357 |
+
}
|
4358 |
+
},
|
4359 |
+
|
4360 |
+
/**
|
4361 |
+
* Set the field that's used to store the data
|
4362 |
+
* @param field
|
4363 |
+
* @param options
|
4364 |
+
*/
|
4365 |
+
setDataField: function ( field, options ) {
|
4366 |
+
options = _.extend( {
|
4367 |
+
load: true
|
4368 |
+
}, options );
|
4369 |
+
|
4370 |
+
this.dataField = field;
|
4371 |
+
this.dataField.data( 'builder', this );
|
4372 |
+
|
4373 |
+
if ( options.load && field.val() !== '' ) {
|
4374 |
+
var data = this.dataField.val();
|
4375 |
+
try {
|
4376 |
+
data = JSON.parse( data );
|
4377 |
+
}
|
4378 |
+
catch ( err ) {
|
4379 |
+
console.log( "Failed to parse Page Builder layout data from supplied data field." );
|
4380 |
+
data = {};
|
4381 |
+
}
|
4382 |
+
|
4383 |
+
this.setData( data );
|
4384 |
+
}
|
4385 |
+
|
4386 |
+
return this;
|
4387 |
+
},
|
4388 |
+
|
4389 |
+
/**
|
4390 |
+
* Set the current panels data to be used.
|
4391 |
+
*
|
4392 |
+
* @param data
|
4393 |
+
*/
|
4394 |
+
setData: function( data ) {
|
4395 |
+
this.model.loadPanelsData( data );
|
4396 |
+
this.currentData = data;
|
4397 |
+
this.toggleWelcomeDisplay();
|
4398 |
+
},
|
4399 |
+
|
4400 |
+
/**
|
4401 |
+
* Get the current panels data.
|
4402 |
+
*
|
4403 |
+
*/
|
4404 |
+
getData: function() {
|
4405 |
+
return this.model.get( 'data' );
|
4406 |
+
},
|
4407 |
+
|
4408 |
+
/**
|
4409 |
+
* Store the model data in the data html field set in this.setDataField.
|
4410 |
+
*/
|
4411 |
+
storeModelData: function () {
|
4412 |
+
var data = JSON.stringify( this.model.get( 'data' ) );
|
4413 |
+
|
4414 |
+
if ( $( this.dataField ).val() !== data ) {
|
4415 |
+
// If the data is different, set it and trigger a content_change event
|
4416 |
+
$( this.dataField ).val( data );
|
4417 |
+
$( this.dataField ).trigger( 'change' );
|
4418 |
+
this.trigger( 'content_change' );
|
4419 |
+
}
|
4420 |
+
},
|
4421 |
+
|
4422 |
+
/**
|
4423 |
+
* HAndle the visual side of adding a new row to the builder.
|
4424 |
+
*
|
4425 |
+
* @param row
|
4426 |
+
* @param collection
|
4427 |
+
* @param options
|
4428 |
+
*/
|
4429 |
+
onAddRow: function ( row, collection, options ) {
|
4430 |
+
options = _.extend( { noAnimate: false }, options );
|
4431 |
+
// Create a view for the row
|
4432 |
+
var rowView = new panels.view.row( { model: row } );
|
4433 |
+
rowView.builder = this;
|
4434 |
+
rowView.render();
|
4435 |
+
|
4436 |
+
// Attach the row elements to this builder
|
4437 |
+
if ( _.isUndefined( options.at ) || collection.length <= 1 ) {
|
4438 |
+
// Insert this at the end of the widgets container
|
4439 |
+
rowView.$el.appendTo( this.$( '.so-rows-container' ) );
|
4440 |
+
} else {
|
4441 |
+
// We need to insert this at a specific position
|
4442 |
+
rowView.$el.insertAfter(
|
4443 |
+
this.$( '.so-rows-container .so-row-container' ).eq( options.at - 1 )
|
4444 |
+
);
|
4445 |
+
}
|
4446 |
+
|
4447 |
+
if ( options.noAnimate === false ) {
|
4448 |
+
rowView.visualCreate();
|
4449 |
+
}
|
4450 |
+
|
4451 |
+
this.refreshSortable();
|
4452 |
+
rowView.resize();
|
4453 |
+
this.trigger( 'row_added' );
|
4454 |
+
},
|
4455 |
+
|
4456 |
+
/**
|
4457 |
+
* Display the dialog to add a new widget.
|
4458 |
+
*
|
4459 |
+
* @returns {boolean}
|
4460 |
+
*/
|
4461 |
+
displayAddWidgetDialog: function () {
|
4462 |
+
this.dialogs.widgets.openDialog();
|
4463 |
+
},
|
4464 |
+
|
4465 |
+
/**
|
4466 |
+
* Display the dialog to add a new row.
|
4467 |
+
*/
|
4468 |
+
displayAddRowDialog: function () {
|
4469 |
+
var row = new panels.model.row();
|
4470 |
+
var cells = new panels.collection.cells( [ { weight: 0.5 }, { weight: 0.5 } ] );
|
4471 |
+
cells.each( function ( cell ) {
|
4472 |
+
cell.row = row;
|
4473 |
+
} );
|
4474 |
+
row.set( 'cells', cells );
|
4475 |
+
row.builder = this.model;
|
4476 |
+
|
4477 |
+
this.dialogs.row.setRowModel( row );
|
4478 |
+
this.dialogs.row.openDialog();
|
4479 |
+
},
|
4480 |
+
|
4481 |
+
/**
|
4482 |
+
* Display the dialog to add prebuilt layouts.
|
4483 |
+
*
|
4484 |
+
* @returns {boolean}
|
4485 |
+
*/
|
4486 |
+
displayAddPrebuiltDialog: function () {
|
4487 |
+
this.dialogs.prebuilt.openDialog();
|
4488 |
+
},
|
4489 |
+
|
4490 |
+
/**
|
4491 |
+
* Display the history dialog.
|
4492 |
+
*
|
4493 |
+
* @returns {boolean}
|
4494 |
+
*/
|
4495 |
+
displayHistoryDialog: function () {
|
4496 |
+
this.dialogs.history.openDialog();
|
4497 |
+
},
|
4498 |
+
|
4499 |
+
/**
|
4500 |
+
* Handle pasting a row into the builder.
|
4501 |
+
*/
|
4502 |
+
pasteRowHandler: function () {
|
4503 |
+
var pastedModel = panels.helpers.clipboard.getModel( 'row-model' );
|
4504 |
+
|
4505 |
+
if ( !_.isEmpty( pastedModel ) && pastedModel instanceof panels.model.row ) {
|
4506 |
+
this.addHistoryEntry( 'row_pasted' );
|
4507 |
+
pastedModel.builder = this.model;
|
4508 |
+
this.model.get( 'rows' ).add( pastedModel, {
|
4509 |
+
at: this.model.get( 'rows' ).indexOf( this.model ) + 1
|
4510 |
+
} );
|
4511 |
+
this.model.refreshPanelsData();
|
4512 |
+
}
|
4513 |
+
},
|
4514 |
+
|
4515 |
+
/**
|
4516 |
+
* Get the model for the currently selected cell
|
4517 |
+
*/
|
4518 |
+
getActiveCell: function ( options ) {
|
4519 |
+
options = _.extend( {
|
4520 |
+
createCell: true,
|
4521 |
+
}, options );
|
4522 |
+
|
4523 |
+
if ( !this.model.get( 'rows' ).length ) {
|
4524 |
+
// There aren't any rows yet
|
4525 |
+
if ( options.createCell ) {
|
4526 |
+
// Create a row with a single cell
|
4527 |
+
this.model.addRow( {}, [ { weight: 1 } ], { noAnimate: true } );
|
4528 |
+
} else {
|
4529 |
+
return null;
|
4530 |
+
}
|
4531 |
+
}
|
4532 |
+
|
4533 |
+
// Make sure the active cell isn't empty, and it's in a row that exists
|
4534 |
+
var activeCell = this.activeCell;
|
4535 |
+
if ( _.isEmpty( activeCell ) || this.model.get( 'rows' ).indexOf( activeCell.model.row ) === -1 ) {
|
4536 |
+
return this.model.get( 'rows' ).last().get( 'cells' ).first();
|
4537 |
+
} else {
|
4538 |
+
return activeCell.model;
|
4539 |
+
}
|
4540 |
+
},
|
4541 |
+
|
4542 |
+
/**
|
4543 |
+
* Add a live editor to the builder
|
4544 |
+
*
|
4545 |
+
* @returns {panels.view.builder}
|
4546 |
+
*/
|
4547 |
+
addLiveEditor: function () {
|
4548 |
+
if ( _.isEmpty( this.config.liveEditorPreview ) ) {
|
4549 |
+
return this;
|
4550 |
+
}
|
4551 |
+
|
4552 |
+
// Create the live editor and set the builder to this.
|
4553 |
+
this.liveEditor = new panels.view.liveEditor( {
|
4554 |
+
builder: this,
|
4555 |
+
previewUrl: this.config.liveEditorPreview
|
4556 |
+
} );
|
4557 |
+
|
4558 |
+
// Display the live editor button in the toolbar
|
4559 |
+
if ( this.liveEditor.hasPreviewUrl() ) {
|
4560 |
+
this.$( '.so-builder-toolbar .so-live-editor' ).show();
|
4561 |
+
}
|
4562 |
+
|
4563 |
+
this.trigger( 'builder_live_editor_added' );
|
4564 |
+
|
4565 |
+
return this;
|
4566 |
+
},
|
4567 |
+
|
4568 |
+
/**
|
4569 |
+
* Show the current live editor
|
4570 |
+
*/
|
4571 |
+
displayLiveEditor: function () {
|
4572 |
+
if ( _.isUndefined( this.liveEditor ) ) {
|
4573 |
+
return;
|
4574 |
+
}
|
4575 |
+
|
4576 |
+
this.liveEditor.open();
|
4577 |
+
},
|
4578 |
+
|
4579 |
+
/**
|
4580 |
+
* Add the history browser.
|
4581 |
+
*
|
4582 |
+
* @return {panels.view.builder}
|
4583 |
+
*/
|
4584 |
+
addHistoryBrowser: function () {
|
4585 |
+
if ( _.isEmpty( this.config.liveEditorPreview ) ) {
|
4586 |
+
return this;
|
4587 |
+
}
|
4588 |
+
|
4589 |
+
this.dialogs.history = new panels.dialog.history();
|
4590 |
+
this.dialogs.history.builder = this;
|
4591 |
+
this.dialogs.history.entries.builder = this.model;
|
4592 |
+
|
4593 |
+
// Set the revert entry
|
4594 |
+
this.dialogs.history.setRevertEntry( this.model );
|
4595 |
+
|
4596 |
+
// Display the live editor button in the toolbar
|
4597 |
+
this.$( '.so-builder-toolbar .so-history' ).show();
|
4598 |
+
},
|
4599 |
+
|
4600 |
+
/**
|
4601 |
+
* Add an entry.
|
4602 |
+
*
|
4603 |
+
* @param text
|
4604 |
+
* @param data
|
4605 |
+
*/
|
4606 |
+
addHistoryEntry: function ( text, data ) {
|
4607 |
+
if ( _.isUndefined( data ) ) {
|
4608 |
+
data = null;
|
4609 |
+
}
|
4610 |
+
|
4611 |
+
if ( !_.isUndefined( this.dialogs.history ) ) {
|
4612 |
+
this.dialogs.history.entries.addEntry( text, data );
|
4613 |
+
}
|
4614 |
+
},
|
4615 |
+
|
4616 |
+
supports: function ( thing ) {
|
4617 |
+
|
4618 |
+
if ( thing === 'rowAction' ) {
|
4619 |
+
// Check if this supports any row action
|
4620 |
+
return this.supports( 'addRow' ) || this.supports( 'editRow' ) || this.supports( 'deleteRow' );
|
4621 |
+
} else if ( thing === 'widgetAction' ) {
|
4622 |
+
// Check if this supports any widget action
|
4623 |
+
return this.supports( 'addWidget' ) || this.supports( 'editWidget' ) || this.supports( 'deleteWidget' );
|
4624 |
+
}
|
4625 |
+
|
4626 |
+
return _.isUndefined( this.config.builderSupports[ thing ] ) ? false : this.config.builderSupports[ thing ];
|
4627 |
+
},
|
4628 |
+
|
4629 |
+
/**
|
4630 |
+
* Handle a change of the content
|
4631 |
+
*/
|
4632 |
+
handleContentChange: function () {
|
4633 |
+
|
4634 |
+
// Make sure we actually need to copy content.
|
4635 |
+
if ( panelsOptions.copy_content && this.attachedToEditor && this.$el.is( ':visible' ) ) {
|
4636 |
+
|
4637 |
+
var panelsData = this.model.getPanelsData();
|
4638 |
+
if ( !_.isEmpty( panelsData.widgets ) ) {
|
4639 |
+
// We're going to create a copy of page builder content into the post content
|
4640 |
+
$.post(
|
4641 |
+
panelsOptions.ajaxurl,
|
4642 |
+
{
|
4643 |
+
action: 'so_panels_builder_content',
|
4644 |
+
panels_data: JSON.stringify( panelsData ),
|
4645 |
+
post_id: this.config.postId
|
4646 |
+
},
|
4647 |
+
function ( content ) {
|
4648 |
+
if ( content !== '' ) {
|
4649 |
+
this.updateEditorContent( content );
|
4650 |
+
}
|
4651 |
+
}.bind( this )
|
4652 |
+
);
|
4653 |
+
}
|
4654 |
+
}
|
4655 |
+
},
|
4656 |
+
|
4657 |
+
/**
|
4658 |
+
* Update editor content with the given content.
|
4659 |
+
*
|
4660 |
+
* @param content
|
4661 |
+
*/
|
4662 |
+
updateEditorContent: function ( content ) {
|
4663 |
+
// Switch back to the standard editor
|
4664 |
+
if ( this.config.editorType !== 'tinyMCE' || typeof tinyMCE === 'undefined' || _.isNull( tinyMCE.get( "content" ) ) ) {
|
4665 |
+
var $editor = $( this.config.editorId );
|
4666 |
+
$editor.val( content ).trigger( 'change' ).trigger( 'keyup' );
|
4667 |
+
} else {
|
4668 |
+
var contentEd = tinyMCE.get( "content" );
|
4669 |
+
|
4670 |
+
contentEd.setContent( content );
|
4671 |
+
|
4672 |
+
contentEd.fire( 'change' );
|
4673 |
+
contentEd.fire( 'keyup' );
|
4674 |
+
}
|
4675 |
+
|
4676 |
+
this.triggerYoastSeoChange();
|
4677 |
+
},
|
4678 |
+
|
4679 |
+
/**
|
4680 |
+
* Trigger a change on Yoast SEO
|
4681 |
+
*/
|
4682 |
+
triggerYoastSeoChange: function () {
|
4683 |
+
if ( $( '#yoast_wpseo_focuskw_text_input' ).length ) {
|
4684 |
+
var element = document.getElementById( 'yoast_wpseo_focuskw_text_input' ), event;
|
4685 |
+
|
4686 |
+
if ( document.createEvent ) {
|
4687 |
+
event = document.createEvent( "HTMLEvents" );
|
4688 |
+
event.initEvent( "keyup", true, true );
|
4689 |
+
} else {
|
4690 |
+
event = document.createEventObject();
|
4691 |
+
event.eventType = "keyup";
|
4692 |
+
}
|
4693 |
+
|
4694 |
+
event.eventName = "keyup";
|
4695 |
+
|
4696 |
+
if ( document.createEvent ) {
|
4697 |
+
element.dispatchEvent( event );
|
4698 |
+
} else {
|
4699 |
+
element.fireEvent( "on" + event.eventType, event );
|
4700 |
+
}
|
4701 |
+
}
|
4702 |
+
},
|
4703 |
+
|
4704 |
+
/**
|
4705 |
+
* Handle displaying the builder
|
4706 |
+
*/
|
4707 |
+
handleDisplayBuilder: function () {
|
4708 |
+
var editor = typeof tinyMCE !== 'undefined' ? tinyMCE.get( 'content' ) : false;
|
4709 |
+
var editorContent = ( editor && _.isFunction( editor.getContent ) ) ? editor.getContent() : $( 'textarea#content' ).val();
|
4710 |
+
|
4711 |
+
if (
|
4712 |
+
(
|
4713 |
+
_.isEmpty( this.model.get( 'data' ) ) ||
|
4714 |
+
( _.isEmpty( this.model.get( 'data' ).widgets ) && _.isEmpty( this.model.get( 'data' ).grids ) )
|
4715 |
+
) &&
|
4716 |
+
editorContent !== ''
|
4717 |
+
) {
|
4718 |
+
var editorClass = panelsOptions.text_widget;
|
4719 |
+
// There is a small chance a theme will have removed this, so check
|
4720 |
+
if ( _.isEmpty( editorClass ) ) {
|
4721 |
+
return;
|
4722 |
+
}
|
4723 |
+
|
4724 |
+
// Create the existing page content in a single widget
|
4725 |
+
this.model.loadPanelsData( this.model.getPanelsDataFromHtml( editorContent, editorClass ) );
|
4726 |
+
this.model.trigger( 'change' );
|
4727 |
+
this.model.trigger( 'change:data' );
|
4728 |
+
}
|
4729 |
+
|
4730 |
+
$( '#post-status-info' ).addClass( 'for-siteorigin-panels' );
|
4731 |
+
},
|
4732 |
+
|
4733 |
+
handleHideBuilder: function () {
|
4734 |
+
$( '#post-status-info' ).show().removeClass( 'for-siteorigin-panels' );
|
4735 |
+
},
|
4736 |
+
|
4737 |
+
wrapEditorExpandAdjust: function () {
|
4738 |
+
try {
|
4739 |
+
var events = ( $.hasData( window ) && $._data( window ) ).events.scroll,
|
4740 |
+
event;
|
4741 |
+
|
4742 |
+
for ( var i = 0; i < events.length; i++ ) {
|
4743 |
+
if ( events[ i ].namespace === 'editor-expand' ) {
|
4744 |
+
event = events[ i ];
|
4745 |
+
|
4746 |
+
// Wrap the call
|
4747 |
+
$( window ).unbind( 'scroll', event.handler );
|
4748 |
+
$( window ).bind( 'scroll', function ( e ) {
|
4749 |
+
if ( !this.attachedVisible ) {
|
4750 |
+
event.handler( e );
|
4751 |
+
}
|
4752 |
+
}.bind( this ) );
|
4753 |
+
|
4754 |
+
break;
|
4755 |
+
}
|
4756 |
+
}
|
4757 |
+
}
|
4758 |
+
catch ( e ) {
|
4759 |
+
// We tried, we failed
|
4760 |
+
return;
|
4761 |
+
}
|
4762 |
+
},
|
4763 |
+
|
4764 |
+
/**
|
4765 |
+
* Either add or remove the narrow class
|
4766 |
+
* @returns {exports}
|
4767 |
+
*/
|
4768 |
+
handleBuilderSizing: function () {
|
4769 |
+
var width = this.$el.width();
|
4770 |
+
|
4771 |
+
if ( !width ) {
|
4772 |
+
return this;
|
4773 |
+
}
|
4774 |
+
|
4775 |
+
if ( width < 575 ) {
|
4776 |
+
this.$el.addClass( 'so-display-narrow' );
|
4777 |
+
} else {
|
4778 |
+
this.$el.removeClass( 'so-display-narrow' );
|
4779 |
+
}
|
4780 |
+
|
4781 |
+
return this;
|
4782 |
+
},
|
4783 |
+
|
4784 |
+
/**
|
4785 |
+
* Set the parent dialog for all the dialogs in this builder.
|
4786 |
+
*
|
4787 |
+
* @param text
|
4788 |
+
* @param dialog
|
4789 |
+
*/
|
4790 |
+
setDialogParents: function ( text, dialog ) {
|
4791 |
+
_.each( this.dialogs, function ( p, i, d ) {
|
4792 |
+
d[ i ].setParent( text, dialog );
|
4793 |
+
} );
|
4794 |
+
|
4795 |
+
// For any future dialogs
|
4796 |
+
this.on( 'add_dialog', function ( newDialog ) {
|
4797 |
+
newDialog.setParent( text, dialog );
|
4798 |
+
}, this );
|
4799 |
+
},
|
4800 |
+
|
4801 |
+
/**
|
4802 |
+
* This shows or hides the welcome display depending on whether there are any rows in the collection.
|
4803 |
+
*/
|
4804 |
+
toggleWelcomeDisplay: function () {
|
4805 |
+
if ( !this.model.get( 'rows' ).isEmpty() ) {
|
4806 |
+
this.$( '.so-panels-welcome-message' ).hide();
|
4807 |
+
} else {
|
4808 |
+
this.$( '.so-panels-welcome-message' ).show();
|
4809 |
+
}
|
4810 |
+
},
|
4811 |
+
|
4812 |
+
/**
|
4813 |
+
* Activate the contextual menu
|
4814 |
+
* @param e
|
4815 |
+
* @param menu
|
4816 |
+
*/
|
4817 |
+
activateContextMenu: function ( e, menu ) {
|
4818 |
+
var builder = this;
|
4819 |
+
|
4820 |
+
// Only run this if the event target is a descendant of this builder's DOM element.
|
4821 |
+
if ( $.contains( builder.$el.get( 0 ), e.target ) ) {
|
4822 |
+
// Get the element we're currently hovering over
|
4823 |
+
var over = $( [] )
|
4824 |
+
.add( builder.$( '.so-panels-welcome-message:visible' ) )
|
4825 |
+
.add( builder.$( '.so-rows-container > .so-row-container' ) )
|
4826 |
+
.add( builder.$( '.so-cells > .cell' ) )
|
4827 |
+
.add( builder.$( '.cell-wrapper > .so-widget' ) )
|
4828 |
+
.filter( function ( i ) {
|
4829 |
+
return menu.isOverEl( $( this ), e );
|
4830 |
+
} );
|
4831 |
+
|
4832 |
+
var activeView = over.last().data( 'view' );
|
4833 |
+
if ( activeView !== undefined && activeView.buildContextualMenu !== undefined ) {
|
4834 |
+
// We'll pass this to the current active view so it can populate the contextual menu
|
4835 |
+
activeView.buildContextualMenu( e, menu );
|
4836 |
+
}
|
4837 |
+
else if ( over.last().hasClass( 'so-panels-welcome-message' ) ) {
|
4838 |
+
// The user opened the contextual menu on the welcome message
|
4839 |
+
this.buildContextualMenu( e, menu );
|
4840 |
+
}
|
4841 |
+
}
|
4842 |
+
},
|
4843 |
+
|
4844 |
+
/**
|
4845 |
+
* Build the contextual menu for the main builder - before any content has been added.
|
4846 |
+
*/
|
4847 |
+
buildContextualMenu: function ( e, menu ) {
|
4848 |
+
var actions = {};
|
4849 |
+
|
4850 |
+
if ( this.supports( 'addRow' ) ) {
|
4851 |
+
actions.add_row = { title: panelsOptions.loc.contextual.add_row };
|
4852 |
+
}
|
4853 |
+
|
4854 |
+
if ( panels.helpers.clipboard.canCopyPaste() ) {
|
4855 |
+
if ( panels.helpers.clipboard.isModel( 'row-model' ) && this.supports( 'addRow' ) ) {
|
4856 |
+
actions.paste_row = { title: panelsOptions.loc.contextual.row_paste };
|
4857 |
+
}
|
4858 |
+
}
|
4859 |
+
|
4860 |
+
if ( !_.isEmpty( actions ) ) {
|
4861 |
+
menu.addSection(
|
4862 |
+
'builder-actions',
|
4863 |
+
{
|
4864 |
+
sectionTitle: panelsOptions.loc.contextual.row_actions,
|
4865 |
+
search: false,
|
4866 |
+
},
|
4867 |
+
actions,
|
4868 |
+
function ( c ) {
|
4869 |
+
switch ( c ) {
|
4870 |
+
case 'add_row':
|
4871 |
+
this.displayAddRowDialog();
|
4872 |
+
break;
|
4873 |
+
|
4874 |
+
case 'paste_row':
|
4875 |
+
this.pasteRowHandler();
|
4876 |
+
break;
|
4877 |
+
}
|
4878 |
+
}.bind( this )
|
4879 |
+
);
|
4880 |
+
}
|
4881 |
+
},
|
4882 |
+
} );
|
4883 |
+
|
4884 |
+
},{}],24:[function(require,module,exports){
|
4885 |
+
var panels = window.panels, $ = jQuery;
|
4886 |
+
|
4887 |
+
module.exports = Backbone.View.extend( {
|
4888 |
+
template: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-builder-cell' ).html() ) ),
|
4889 |
+
events: {
|
4890 |
+
'click .cell-wrapper': 'handleCellClick'
|
4891 |
+
},
|
4892 |
+
|
4893 |
+
/* The row view that this cell is a part of */
|
4894 |
+
row: null,
|
4895 |
+
widgetSortable: null,
|
4896 |
+
|
4897 |
+
initialize: function () {
|
4898 |
+
this.listenTo(this.model.get('widgets'), 'add', this.onAddWidget );
|
4899 |
+
},
|
4900 |
+
|
4901 |
+
/**
|
4902 |
+
* Render the actual cell
|
4903 |
+
*/
|
4904 |
+
render: function () {
|
4905 |
+
var templateArgs = {
|
4906 |
+
weight: this.model.get( 'weight' ),
|
4907 |
+
totalWeight: this.row.model.get('cells').totalWeight()
|
4908 |
+
};
|
4909 |
+
|
4910 |
+
this.setElement( this.template( templateArgs ) );
|
4911 |
+
this.$el.data( 'view', this );
|
4912 |
+
|
4913 |
+
// Now lets render any widgets that are currently in the row
|
4914 |
+
var thisView = this;
|
4915 |
+
this.model.get('widgets').each( function ( widget ) {
|
4916 |
+
var widgetView = new panels.view.widget( {model: widget} );
|
4917 |
+
widgetView.cell = thisView;
|
4918 |
+
widgetView.render();
|
4919 |
+
|
4920 |
+
widgetView.$el.appendTo( thisView.$( '.widgets-container' ) );
|
4921 |
+
} );
|
4922 |
+
|
4923 |
+
this.initSortable();
|
4924 |
+
this.initResizable();
|
4925 |
+
|
4926 |
+
return this;
|
4927 |
+
},
|
4928 |
+
|
4929 |
+
/**
|
4930 |
+
* Initialize the widget sortable
|
4931 |
+
*/
|
4932 |
+
initSortable: function () {
|
4933 |
+
if( ! this.row.builder.supports( 'moveWidget' ) ) {
|
4934 |
+
return this;
|
4935 |
+
}
|
4936 |
+
|
4937 |
+
var cellView = this;
|
4938 |
+
var builder = cellView.row.builder;
|
4939 |
+
|
4940 |
+
// Go up the view hierarchy until we find the ID attribute
|
4941 |
+
var builderID = builder.$el.attr( 'id' );
|
4942 |
+
var builderModel = builder.model;
|
4943 |
+
|
4944 |
+
// Create a widget sortable that's connected with all other cells
|
4945 |
+
this.widgetSortable = this.$( '.widgets-container' ).sortable( {
|
4946 |
+
placeholder: "so-widget-sortable-highlight",
|
4947 |
+
connectWith: '#' + builderID + ' .so-cells .cell .widgets-container,.block-editor .so-cells .cell .widgets-container',
|
4948 |
+
tolerance: 'pointer',
|
4949 |
+
scroll: false,
|
4950 |
+
over: function ( e, ui ) {
|
4951 |
+
// This will make all the rows in the current builder resize
|
4952 |
+
cellView.row.builder.trigger( 'widget_sortable_move' );
|
4953 |
+
},
|
4954 |
+
remove: function ( e, ui ) {
|
4955 |
+
cellView.model.get( 'widgets' ).remove(
|
4956 |
+
$( ui.item ).data( 'view' ).model,
|
4957 |
+
{ silent: true }
|
4958 |
+
);
|
4959 |
+
builderModel.refreshPanelsData();
|
4960 |
+
},
|
4961 |
+
receive: function ( e, ui ) {
|
4962 |
+
var widgetView = $( ui.item ).data( 'view' );
|
4963 |
+
widgetView.cell = cellView;
|
4964 |
+
var widgetModel = widgetView.model;
|
4965 |
+
widgetModel.cell = cellView.model;
|
4966 |
+
cellView.model.get( 'widgets' ).add(
|
4967 |
+
widgetModel,
|
4968 |
+
{ silent: true, at: $( ui.item ).index() }
|
4969 |
+
);
|
4970 |
+
builderModel.refreshPanelsData();
|
4971 |
+
},
|
4972 |
+
stop: function ( e, ui ) {
|
4973 |
+
var $$ = $( ui.item ),
|
4974 |
+
widget = $$.data( 'view' ),
|
4975 |
+
targetCell = $$.closest( '.cell' ).data( 'view' );
|
4976 |
+
|
4977 |
+
|
4978 |
+
// If this hasn't already been removed and added to a different builder.
|
4979 |
+
if ( cellView.model.get( 'widgets' ).get( widget.model ) ) {
|
4980 |
+
|
4981 |
+
cellView.row.builder.addHistoryEntry( 'widget_moved' );
|
4982 |
+
|
4983 |
+
// Move the model and the view to the new cell
|
4984 |
+
widget.model.moveToCell( targetCell.model, {}, $$.index() );
|
4985 |
+
widget.cell = targetCell;
|
4986 |
+
|
4987 |
+
builderModel.refreshPanelsData();
|
4988 |
+
}
|
4989 |
+
},
|
4990 |
+
helper: function ( e, el ) {
|
4991 |
+
var helper = el.clone()
|
4992 |
+
.css( {
|
4993 |
+
'width': el.outerWidth(),
|
4994 |
+
'z-index': 10000,
|
4995 |
+
'position': 'fixed'
|
4996 |
+
} )
|
4997 |
+
.addClass( 'widget-being-dragged' ).appendTo( 'body' );
|
4998 |
+
|
4999 |
+
// Center the helper to the mouse cursor.
|
5000 |
+
if ( el.outerWidth() > 720 ) {
|
5001 |
+
helper.animate( {
|
5002 |
+
'margin-left': e.pageX - el.offset().left - (
|
5003 |
+
480 / 2
|
5004 |
+
),
|
5005 |
+
'width': 480
|
5006 |
+
}, 'fast' );
|
5007 |
+
}
|
5008 |
+
|
5009 |
+
return helper;
|
5010 |
+
}
|
5011 |
+
} );
|
5012 |
+
|
5013 |
+
return this;
|
5014 |
+
},
|
5015 |
+
|
5016 |
+
/**
|
5017 |
+
* Refresh the widget sortable when a new widget is added
|
5018 |
+
*/
|
5019 |
+
refreshSortable: function () {
|
5020 |
+
if ( ! _.isNull( this.widgetSortable ) ) {
|
5021 |
+
this.widgetSortable.sortable( 'refresh' );
|
5022 |
+
}
|
5023 |
+
},
|
5024 |
+
|
5025 |
+
/**
|
5026 |
+
* This will make the cell resizble
|
5027 |
+
*/
|
5028 |
+
initResizable: function () {
|
5029 |
+
if( ! this.row.builder.supports( 'editRow' ) ) {
|
5030 |
+
return this;
|
5031 |
+
}
|
5032 |
+
|
5033 |
+
// var neighbor = this.$el.previous().data('view');
|
5034 |
+
var handle = this.$( '.resize-handle' ).css( 'position', 'absolute' );
|
5035 |
+
var container = this.row.$el;
|
5036 |
+
var cellView = this;
|
5037 |
+
|
5038 |
+
// The view of the cell to the left is stored when dragging starts.
|
5039 |
+
var previousCell;
|
5040 |
+
|
5041 |
+
handle.draggable( {
|
5042 |
+
axis: 'x',
|
5043 |
+
containment: container,
|
5044 |
+
start: function ( e, ui ) {
|
5045 |
+
// Set the containment to the cell parent
|
5046 |
+
previousCell = cellView.$el.prev().data( 'view' );
|
5047 |
+
if ( _.isUndefined( previousCell ) ) {
|
5048 |
+
return;
|
5049 |
+
}
|
5050 |
+
|
5051 |
+
// Create the clone for the current cell
|
5052 |
+
var newCellClone = cellView.$el.clone().appendTo( ui.helper ).css( {
|
5053 |
+
position: 'absolute',
|
5054 |
+
top: '0',
|
5055 |
+
width: cellView.$el.outerWidth(),
|
5056 |
+
left: 5,
|
5057 |
+
height: cellView.$el.outerHeight()
|
5058 |
+
} );
|
5059 |
+
newCellClone.find( '.resize-handle' ).remove();
|
5060 |
+
|
5061 |
+
// Create the clone for the previous cell
|
5062 |
+
var prevCellClone = previousCell.$el.clone().appendTo( ui.helper ).css( {
|
5063 |
+
position: 'absolute',
|
5064 |
+
top: '0',
|
5065 |
+
width: previousCell.$el.outerWidth(),
|
5066 |
+
right: 5,
|
5067 |
+
height: previousCell.$el.outerHeight()
|
5068 |
+
} );
|
5069 |
+
prevCellClone.find( '.resize-handle' ).remove();
|
5070 |
+
|
5071 |
+
$( this ).data( {
|
5072 |
+
'newCellClone': newCellClone,
|
5073 |
+
'prevCellClone': prevCellClone
|
5074 |
+
} );
|
5075 |
+
},
|
5076 |
+
drag: function ( e, ui ) {
|
5077 |
+
// Calculate the new cell and previous cell widths as a percent
|
5078 |
+
var containerWidth = cellView.row.$el.width() + 10;
|
5079 |
+
var ncw = cellView.model.get( 'weight' ) - (
|
5080 |
+
(
|
5081 |
+
ui.position.left + handle.outerWidth() / 2
|
5082 |
+
) / containerWidth
|
5083 |
+
);
|
5084 |
+
var pcw = previousCell.model.get( 'weight' ) + (
|
5085 |
+
(
|
5086 |
+
ui.position.left + handle.outerWidth() / 2
|
5087 |
+
) / containerWidth
|
5088 |
+
);
|
5089 |
+
|
5090 |
+
$( this ).data( 'newCellClone' ).css( 'width', containerWidth * ncw )
|
5091 |
+
.find( '.preview-cell-weight' ).html( Math.round( ncw * 1000 ) / 10 );
|
5092 |
+
|
5093 |
+
$( this ).data( 'prevCellClone' ).css( 'width', containerWidth * pcw )
|
5094 |
+
.find( '.preview-cell-weight' ).html( Math.round( pcw * 1000 ) / 10 );
|
5095 |
+
},
|
5096 |
+
stop: function ( e, ui ) {
|
5097 |
+
// Remove the clones
|
5098 |
+
$( this ).data( 'newCellClone' ).remove();
|
5099 |
+
$( this ).data( 'prevCellClone' ).remove();
|
5100 |
+
|
5101 |
+
var containerWidth = cellView.row.$el.width() + 10;
|
5102 |
+
var ncw = cellView.model.get( 'weight' ) - (
|
5103 |
+
(
|
5104 |
+
ui.position.left + handle.outerWidth() / 2
|
5105 |
+
) / containerWidth
|
5106 |
+
);
|
5107 |
+
var pcw = previousCell.model.get( 'weight' ) + (
|
5108 |
+
(
|
5109 |
+
ui.position.left + handle.outerWidth() / 2
|
5110 |
+
) / containerWidth
|
5111 |
+
);
|
5112 |
+
|
5113 |
+
if ( ncw > 0.02 && pcw > 0.02 ) {
|
5114 |
+
cellView.row.builder.addHistoryEntry( 'cell_resized' );
|
5115 |
+
cellView.model.set( 'weight', ncw );
|
5116 |
+
previousCell.model.set( 'weight', pcw );
|
5117 |
+
cellView.row.resize();
|
5118 |
+
}
|
5119 |
+
|
5120 |
+
ui.helper.css( 'left', - handle.outerWidth() / 2 );
|
5121 |
+
|
5122 |
+
// Refresh the panels data
|
5123 |
+
cellView.row.builder.model.refreshPanelsData();
|
5124 |
+
}
|
5125 |
+
} );
|
5126 |
+
|
5127 |
+
return this;
|
5128 |
+
},
|
5129 |
+
|
5130 |
+
/**
|
5131 |
+
* This is triggered when ever a widget is added to the row collection.
|
5132 |
+
*
|
5133 |
+
* @param widget
|
5134 |
+
*/
|
5135 |
+
onAddWidget: function ( widget, collection, options ) {
|
5136 |
+
options = _.extend( {noAnimate: false}, options );
|
5137 |
+
|
5138 |
+
// Create the view for the widget
|
5139 |
+
var view = new panels.view.widget( {
|
5140 |
+
model: widget
|
5141 |
+
} );
|
5142 |
+
view.cell = this;
|
5143 |
+
|
5144 |
+
if ( _.isUndefined( widget.isDuplicate ) ) {
|
5145 |
+
widget.isDuplicate = false;
|
5146 |
+
}
|
5147 |
+
|
5148 |
+
// Render and load the form if this is a duplicate
|
5149 |
+
view.render( {
|
5150 |
+
'loadForm': widget.isDuplicate
|
5151 |
+
} );
|
5152 |
+
|
5153 |
+
if ( _.isUndefined( options.at ) || collection.length <= 1 ) {
|
5154 |
+
// Insert this at the end of the widgets container
|
5155 |
+
view.$el.appendTo( this.$( '.widgets-container' ) );
|
5156 |
+
} else {
|
5157 |
+
// We need to insert this at a specific position
|
5158 |
+
view.$el.insertAfter(
|
5159 |
+
this.$( '.widgets-container .so-widget' ).eq( options.at - 1 )
|
5160 |
+
);
|
5161 |
+
}
|
5162 |
+
|
5163 |
+
if ( options.noAnimate === false ) {
|
5164 |
+
// We need an animation
|
5165 |
+
view.visualCreate();
|
5166 |
+
}
|
5167 |
+
|
5168 |
+
this.refreshSortable();
|
5169 |
+
this.row.resize();
|
5170 |
+
this.row.builder.trigger( 'widget_added', view );
|
5171 |
+
},
|
5172 |
+
|
5173 |
+
/**
|
5174 |
+
* Handle this cell being clicked on
|
5175 |
+
*
|
5176 |
+
* @param e
|
5177 |
+
* @returns {boolean}
|
5178 |
+
*/
|
5179 |
+
handleCellClick: function ( e ) {
|
5180 |
+
// Remove all existing selected cell indication for this builder
|
5181 |
+
this.row.builder.$el.find( '.so-cells .cell' ).removeClass( 'cell-selected' );
|
5182 |
+
|
5183 |
+
if( this.row.builder.activeCell === this && ! this.model.get('widgets').length ) {
|
5184 |
+
// This is a click on an empty cell
|
5185 |
+
this.row.builder.activeCell = null;
|
5186 |
+
}
|
5187 |
+
else {
|
5188 |
+
this.$el.addClass( 'cell-selected' );
|
5189 |
+
this.row.builder.activeCell = this;
|
5190 |
+
}
|
5191 |
+
},
|
5192 |
+
|
5193 |
+
/**
|
5194 |
+
* Insert a widget from the clipboard
|
5195 |
+
*/
|
5196 |
+
pasteHandler: function(){
|
5197 |
+
var pastedModel = panels.helpers.clipboard.getModel( 'widget-model' );
|
5198 |
+
if( ! _.isEmpty( pastedModel ) && pastedModel instanceof panels.model.widget ) {
|
5199 |
+
this.row.builder.addHistoryEntry( 'widget_pasted' );
|
5200 |
+
pastedModel.cell = this.model;
|
5201 |
+
this.model.get('widgets').add( pastedModel );
|
5202 |
+
this.row.builder.model.refreshPanelsData();
|
5203 |
+
}
|
5204 |
+
},
|
5205 |
+
|
5206 |
+
/**
|
5207 |
+
* Build up the contextual menu for a cell
|
5208 |
+
*
|
5209 |
+
* @param e
|
5210 |
+
* @param menu
|
5211 |
+
*/
|
5212 |
+
buildContextualMenu: function ( e, menu ) {
|
5213 |
+
var thisView = this;
|
5214 |
+
|
5215 |
+
if( ! menu.hasSection( 'add-widget-below' ) ) {
|
5216 |
+
menu.addSection(
|
5217 |
+
'add-widget-cell',
|
5218 |
+
{
|
5219 |
+
sectionTitle: panelsOptions.loc.contextual.add_widget_cell,
|
5220 |
+
searchPlaceholder: panelsOptions.loc.contextual.search_widgets,
|
5221 |
+
defaultDisplay: panelsOptions.contextual.default_widgets
|
5222 |
+
},
|
5223 |
+
panelsOptions.widgets,
|
5224 |
+
function ( c ) {
|
5225 |
+
thisView.row.builder.trigger('before_user_adds_widget')
|
5226 |
+
thisView.row.builder.addHistoryEntry( 'widget_added' );
|
5227 |
+
|
5228 |
+
var widget = new panels.model.widget( {
|
5229 |
+
class: c
|
5230 |
+
} );
|
5231 |
+
|
5232 |
+
// Add the widget to the cell model
|
5233 |
+
widget.cell = thisView.model;
|
5234 |
+
widget.cell.get('widgets').add( widget );
|
5235 |
+
|
5236 |
+
thisView.row.builder.model.refreshPanelsData();
|
5237 |
+
thisView.row.builder.trigger('after_user_adds_widget', widget);
|
5238 |
+
}
|
5239 |
+
);
|
5240 |
+
}
|
5241 |
+
|
5242 |
+
var actions = {};
|
5243 |
+
if ( this.row.builder.supports('addWidget') && panels.helpers.clipboard.isModel( 'widget-model' ) ) {
|
5244 |
+
actions.paste = {title: panelsOptions.loc.contextual.cell_paste_widget};
|
5245 |
+
}
|
5246 |
+
|
5247 |
+
if( ! _.isEmpty( actions ) ) {
|
5248 |
+
menu.addSection(
|
5249 |
+
'cell-actions',
|
5250 |
+
{
|
5251 |
+
sectionTitle: panelsOptions.loc.contextual.cell_actions,
|
5252 |
+
search: false,
|
5253 |
+
},
|
5254 |
+
actions,
|
5255 |
+
function ( c ) {
|
5256 |
+
switch ( c ) {
|
5257 |
+
case 'paste':
|
5258 |
+
this.pasteHandler();
|
5259 |
+
break;
|
5260 |
+
}
|
5261 |
+
|
5262 |
+
this.row.builder.model.refreshPanelsData();
|
5263 |
+
}.bind( this )
|
5264 |
+
);
|
5265 |
+
}
|
5266 |
+
|
5267 |
+
// Add the contextual menu for the parent row
|
5268 |
+
this.row.buildContextualMenu( e, menu );
|
5269 |
+
}
|
5270 |
+
} );
|
5271 |
+
|
5272 |
+
},{}],25:[function(require,module,exports){
|
5273 |
+
var panels = window.panels, $ = jQuery;
|
5274 |
+
|
5275 |
+
module.exports = Backbone.View.extend( {
|
5276 |
+
dialogTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-dialog' ).html() ) ),
|
5277 |
+
dialogTabTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-dialog-tab' ).html() ) ),
|
5278 |
+
|
5279 |
+
tabbed: false,
|
5280 |
+
rendered: false,
|
5281 |
+
builder: false,
|
5282 |
+
className: 'so-panels-dialog-wrapper',
|
5283 |
+
dialogClass: '',
|
5284 |
+
dialogIcon: '',
|
5285 |
+
parentDialog: false,
|
5286 |
+
dialogOpen: false,
|
5287 |
+
editableLabel: false,
|
5288 |
+
|
5289 |
+
events: {
|
5290 |
+
'click .so-close': 'closeDialog',
|
5291 |
+
'click .so-nav.so-previous': 'navToPrevious',
|
5292 |
+
'click .so-nav.so-next': 'navToNext',
|
5293 |
+
},
|
5294 |
+
|
5295 |
+
initialize: function () {
|
5296 |
+
// The first time this dialog is opened, render it
|
5297 |
+
this.once( 'open_dialog', this.render );
|
5298 |
+
this.once( 'open_dialog', this.attach );
|
5299 |
+
this.once( 'open_dialog', this.setDialogClass );
|
5300 |
+
|
5301 |
+
this.trigger( 'initialize_dialog', this );
|
5302 |
+
|
5303 |
+
if ( ! _.isUndefined( this.initializeDialog ) ) {
|
5304 |
+
this.initializeDialog();
|
5305 |
+
}
|
5306 |
+
|
5307 |
+
_.bindAll( this, 'initSidebars', 'hasSidebar', 'onResize', 'toggleLeftSideBar', 'toggleRightSideBar' );
|
5308 |
+
},
|
5309 |
+
|
5310 |
+
/**
|
5311 |
+
* Returns the next dialog in the sequence. Should be overwritten by a child dialog.
|
5312 |
+
* @returns {null}
|
5313 |
+
*/
|
5314 |
+
getNextDialog: function () {
|
5315 |
+
return null;
|
5316 |
+
},
|
5317 |
+
|
5318 |
+
/**
|
5319 |
+
* Returns the previous dialog in this sequence. Should be overwritten by child dialog.
|
5320 |
+
* @returns {null}
|
5321 |
+
*/
|
5322 |
+
getPrevDialog: function () {
|
5323 |
+
return null;
|
5324 |
+
},
|
5325 |
+
|
5326 |
+
/**
|
5327 |
+
* Adds a dialog class to uniquely identify this dialog type
|
5328 |
+
*/
|
5329 |
+
setDialogClass: function () {
|
5330 |
+
if ( this.dialogClass !== '' ) {
|
5331 |
+
this.$( '.so-panels-dialog' ).addClass( this.dialogClass );
|
5332 |
+
}
|
5333 |
+
},
|
5334 |
+
|
5335 |
+
/**
|
5336 |
+
* Set the builder that controls this dialog.
|
5337 |
+
* @param {panels.view.builder} builder
|
5338 |
+
*/
|
5339 |
+
setBuilder: function ( builder ) {
|
5340 |
+
this.builder = builder;
|
5341 |
+
|
5342 |
+
// Trigger an add dialog event on the builder so it can modify the dialog in any way
|
5343 |
+
builder.trigger( 'add_dialog', this, this.builder );
|
5344 |
+
|
5345 |
+
return this;
|
5346 |
+
},
|
5347 |
+
|
5348 |
+
/**
|
5349 |
+
* Attach the dialog to the window
|
5350 |
+
*/
|
5351 |
+
attach: function () {
|
5352 |
+
this.$el.appendTo( 'body' );
|
5353 |
+
|
5354 |
+
return this;
|
5355 |
+
},
|
5356 |
+
|
5357 |
+
/**
|
5358 |
+
* Converts an HTML representation of the dialog into arguments for a dialog box
|
5359 |
+
* @param html HTML for the dialog
|
5360 |
+
* @param args Arguments passed to the template
|
5361 |
+
* @returns {}
|
5362 |
+
*/
|
5363 |
+
parseDialogContent: function ( html, args ) {
|
5364 |
+
// Add a CID
|
5365 |
+
args = _.extend( {cid: this.cid}, args );
|
5366 |
+
|
5367 |
+
|
5368 |
+
var c = $( (
|
5369 |
+
_.template( panels.helpers.utils.processTemplate( html ) )
|
5370 |
+
)( args ) );
|
5371 |
+
var r = {
|
5372 |
+
title: c.find( '.title' ).html(),
|
5373 |
+
buttons: c.find( '.buttons' ).html(),
|
5374 |
+
content: c.find( '.content' ).html()
|
5375 |
+
};
|
5376 |
+
|
5377 |
+
if ( c.has( '.left-sidebar' ) ) {
|
5378 |
+
r.left_sidebar = c.find( '.left-sidebar' ).html();
|
5379 |
+
}
|
5380 |
+
|
5381 |
+
if ( c.has( '.right-sidebar' ) ) {
|
5382 |
+
r.right_sidebar = c.find( '.right-sidebar' ).html();
|
5383 |
+
}
|
5384 |
+
|
5385 |
+
return r;
|
5386 |
+
|
5387 |
+
},
|
5388 |
+
|
5389 |
+
/**
|
5390 |
+
* Render the dialog and initialize the tabs
|
5391 |
+
*
|
5392 |
+
* @param attributes
|
5393 |
+
* @returns {panels.view.dialog}
|
5394 |
+
*/
|
5395 |
+
renderDialog: function ( attributes ) {
|
5396 |
+
attributes = _.extend( {
|
5397 |
+
editableLabel: this.editableLabel,
|
5398 |
+
dialogIcon: this.dialogIcon,
|
5399 |
+
}, attributes );
|
5400 |
+
|
5401 |
+
this.$el.html( this.dialogTemplate( attributes ) ).hide();
|
5402 |
+
this.$el.data( 'view', this );
|
5403 |
+
this.$el.addClass( 'so-panels-dialog-wrapper' );
|
5404 |
+
|
5405 |
+
if ( this.parentDialog !== false ) {
|
5406 |
+
// Add a link to the parent dialog as a sort of crumbtrail.
|
5407 |
+
var dialogParent = $( '<h3 class="so-parent-link"></h3>' ).html( this.parentDialog.text + '<div class="so-separator"></div>' );
|
5408 |
+
dialogParent.click( function ( e ) {
|
5409 |
+
e.preventDefault();
|
5410 |
+
this.closeDialog();
|
5411 |
+
this.parentDialog.dialog.openDialog();
|
5412 |
+
}.bind(this) );
|
5413 |
+
this.$( '.so-title-bar .so-title' ).before( dialogParent );
|
5414 |
+
}
|
5415 |
+
|
5416 |
+
if( this.$( '.so-title-bar .so-title-editable' ).length ) {
|
5417 |
+
// Added here because .so-edit-title is only available after the template has been rendered.
|
5418 |
+
this.initEditableLabel();
|
5419 |
+
}
|
5420 |
+
|
5421 |
+
setTimeout( this.initSidebars, 1 );
|
5422 |
+
|
5423 |
+
return this;
|
5424 |
+
},
|
5425 |
+
|
5426 |
+
initSidebars: function () {
|
5427 |
+
var $leftButton = this.$( '.so-show-left-sidebar' ).hide();
|
5428 |
+
var $rightButton = this.$( '.so-show-right-sidebar' ).hide();
|
5429 |
+
var hasLeftSidebar = this.hasSidebar( 'left' );
|
5430 |
+
var hasRightSidebar = this.hasSidebar( 'right' );
|
5431 |
+
// Set up resize handling
|
5432 |
+
if ( hasLeftSidebar || hasRightSidebar ) {
|
5433 |
+
$( window ).on( 'resize', this.onResize );
|
5434 |
+
if ( hasLeftSidebar ) {
|
5435 |
+
$leftButton.show();
|
5436 |
+
$leftButton.on( 'click', this.toggleLeftSideBar );
|
5437 |
+
}
|
5438 |
+
if ( hasRightSidebar ) {
|
5439 |
+
$rightButton.show();
|
5440 |
+
$rightButton.on( 'click', this.toggleRightSideBar );
|
5441 |
+
}
|
5442 |
+
}
|
5443 |
+
|
5444 |
+
this.onResize();
|
5445 |
+
},
|
5446 |
+
|
5447 |
+
/**
|
5448 |
+
* Initialize the sidebar tabs
|
5449 |
+
*/
|
5450 |
+
initTabs: function () {
|
5451 |
+
var tabs = this.$( '.so-sidebar-tabs li a' );
|
5452 |
+
|
5453 |
+
if ( tabs.length === 0 ) {
|
5454 |
+
return this;
|
5455 |
+
}
|
5456 |
+
|
5457 |
+
var thisDialog = this;
|
5458 |
+
tabs.click( function ( e ) {
|
5459 |
+
e.preventDefault();
|
5460 |
+
var $$ = $( this );
|
5461 |
+
|
5462 |
+
thisDialog.$( '.so-sidebar-tabs li' ).removeClass( 'tab-active' );
|
5463 |
+
thisDialog.$( '.so-content .so-content-tabs > *' ).hide();
|
5464 |
+
|
5465 |
+
$$.parent().addClass( 'tab-active' );
|
5466 |
+
|
5467 |
+
var url = $$.attr( 'href' );
|
5468 |
+
if ( ! _.isUndefined( url ) && url.charAt( 0 ) === '#' ) {
|
5469 |
+
// Display the new tab
|
5470 |
+
var tabName = url.split( '#' )[1];
|
5471 |
+
thisDialog.$( '.so-content .so-content-tabs .tab-' + tabName ).show();
|
5472 |
+
}
|
5473 |
+
|
5474 |
+
// This lets other dialogs implement their own custom handlers
|
5475 |
+
thisDialog.trigger( 'tab_click', $$ );
|
5476 |
+
|
5477 |
+
} );
|
5478 |
+
|
5479 |
+
// Trigger a click on the first tab
|
5480 |
+
this.$( '.so-sidebar-tabs li a' ).first().click();
|
5481 |
+
return this;
|
5482 |
+
},
|
5483 |
+
|
5484 |
+
initToolbar: function () {
|
5485 |
+
// Trigger simplified click event for elements marked as toolbar buttons.
|
5486 |
+
var buttons = this.$( '.so-toolbar .so-buttons .so-toolbar-button' );
|
5487 |
+
buttons.click( function ( e ) {
|
5488 |
+
e.preventDefault();
|
5489 |
+
|
5490 |
+
this.trigger( 'button_click', $( e.currentTarget ) );
|
5491 |
+
}.bind( this ) );
|
5492 |
+
|
5493 |
+
// Handle showing and hiding the dropdown list items
|
5494 |
+
var $dropdowns = this.$( '.so-toolbar .so-buttons .so-dropdown-button' );
|
5495 |
+
$dropdowns.click( function ( e ) {
|
5496 |
+
e.preventDefault();
|
5497 |
+
var $dropdownButton = $( e.currentTarget );
|
5498 |
+
var $dropdownList = $dropdownButton.siblings( '.so-dropdown-links-wrapper' );
|
5499 |
+
if ( $dropdownList.is( '.hidden' ) ) {
|
5500 |
+
$dropdownList.removeClass( 'hidden' );
|
5501 |
+
} else {
|
5502 |
+
$dropdownList.addClass( 'hidden' );
|
5503 |
+
}
|
5504 |
+
|
5505 |
+
}.bind( this ) );
|
5506 |
+
|
5507 |
+
// Hide dropdown list on click anywhere, unless it's a dropdown option which requires confirmation in it's
|
5508 |
+
// unconfirmed state.
|
5509 |
+
$( 'html' ).click( function ( e ) {
|
5510 |
+
this.$( '.so-dropdown-links-wrapper' ).not( '.hidden' ).each( function ( index, el ) {
|
5511 |
+
var $dropdownList = $( el );
|
5512 |
+
var $trgt = $( e.target );
|
5513 |
+
if ( $trgt.length === 0 || !(
|
5514 |
+
(
|
5515 |
+
$trgt.is('.so-needs-confirm') && !$trgt.is('.so-confirmed')
|
5516 |
+
) || $trgt.is('.so-dropdown-button')
|
5517 |
+
) ) {
|
5518 |
+
$dropdownList.addClass('hidden');
|
5519 |
+
}
|
5520 |
+
} );
|
5521 |
+
}.bind( this ) );
|
5522 |
+
},
|
5523 |
+
|
5524 |
+
/**
|
5525 |
+
* Initialize the editable dialog title
|
5526 |
+
*/
|
5527 |
+
initEditableLabel: function(){
|
5528 |
+
var $editElt = this.$( '.so-title-bar .so-title-editable' );
|
5529 |
+
|
5530 |
+
$editElt.keypress( function ( event ) {
|
5531 |
+
var enterPressed = event.type === 'keypress' && event.keyCode === 13;
|
5532 |
+
if ( enterPressed ) {
|
5533 |
+
// Need to make sure tab focus is on another element, otherwise pressing enter multiple times refocuses
|
5534 |
+
// the element and allows newlines.
|
5535 |
+
var tabbables = $( ':tabbable' );
|
5536 |
+
var curTabIndex = tabbables.index( $editElt );
|
5537 |
+
tabbables.eq( curTabIndex + 1 ).focus();
|
5538 |
+
// After the above, we're somehow left with the first letter of text selected,
|
5539 |
+
// so this removes the selection.
|
5540 |
+
window.getSelection().removeAllRanges();
|
5541 |
+
}
|
5542 |
+
return !enterPressed;
|
5543 |
+
} ).blur( function () {
|
5544 |
+
var newValue = $editElt.text().replace( /^\s+|\s+$/gm, '' );
|
5545 |
+
var oldValue = $editElt.data( 'original-value' ).replace( /^\s+|\s+$/gm, '' );
|
5546 |
+
if ( newValue !== oldValue ) {
|
5547 |
+
$editElt.text( newValue );
|
5548 |
+
this.trigger( 'edit_label', newValue );
|
5549 |
+
}
|
5550 |
+
|
5551 |
+
}.bind( this ) );
|
5552 |
+
|
5553 |
+
$editElt.focus( function() {
|
5554 |
+
$editElt.data( 'original-value', $editElt.text() );
|
5555 |
+
panels.helpers.utils.selectElementContents( this );
|
5556 |
+
} );
|
5557 |
+
},
|
5558 |
+
|
5559 |
+
/**
|
5560 |
+
* Quickly setup the dialog by opening and closing it.
|
5561 |
+
*/
|
5562 |
+
setupDialog: function () {
|
5563 |
+
this.openDialog();
|
5564 |
+
this.closeDialog();
|
5565 |
+
},
|
5566 |
+
|
5567 |
+
/**
|
5568 |
+
* Refresh the next and previous buttons.
|
5569 |
+
*/
|
5570 |
+
refreshDialogNav: function () {
|
5571 |
+
this.$( '.so-title-bar .so-nav' ).show().removeClass( 'so-disabled' );
|
5572 |
+
|
5573 |
+
// Lets also hide the next and previous if we don't have a next and previous dialog
|
5574 |
+
var nextDialog = this.getNextDialog();
|
5575 |
+
var nextButton = this.$( '.so-title-bar .so-next' );
|
5576 |
+
|
5577 |
+
var prevDialog = this.getPrevDialog();
|
5578 |
+
var prevButton = this.$( '.so-title-bar .so-previous' );
|
5579 |
+
|
5580 |
+
if ( nextDialog === null ) {
|
5581 |
+
nextButton.hide();
|
5582 |
+
}
|
5583 |
+
else if ( nextDialog === false ) {
|
5584 |
+
nextButton.addClass( 'so-disabled' );
|
5585 |
+
}
|
5586 |
+
|
5587 |
+
if ( prevDialog === null ) {
|
5588 |
+
prevButton.hide();
|
5589 |
+
}
|
5590 |
+
else if ( prevDialog === false ) {
|
5591 |
+
prevButton.addClass( 'so-disabled' );
|
5592 |
+
}
|
5593 |
+
},
|
5594 |
+
|
5595 |
+
/**
|
5596 |
+
* Open the dialog
|
5597 |
+
*/
|
5598 |
+
openDialog: function ( options ) {
|
5599 |
+
options = _.extend( {
|
5600 |
+
silent: false
|
5601 |
+
}, options );
|
5602 |
+
|
5603 |
+
if ( ! options.silent ) {
|
5604 |
+
this.trigger( 'open_dialog' );
|
5605 |
+
}
|
5606 |
+
|
5607 |
+
this.dialogOpen = true;
|
5608 |
+
|
5609 |
+
this.refreshDialogNav();
|
5610 |
+
|
5611 |
+
// Stop scrolling for the main body
|
5612 |
+
panels.helpers.pageScroll.lock();
|
5613 |
+
|
5614 |
+
this.onResize();
|
5615 |
+
|
5616 |
+
this.$el.show();
|
5617 |
+
|
5618 |
+
if ( ! options.silent ) {
|
5619 |
+
// This triggers once everything is visible
|
5620 |
+
this.trigger( 'open_dialog_complete' );
|
5621 |
+
this.builder.trigger( 'open_dialog', this );
|
5622 |
+
$( document ).trigger( 'open_dialog', this );
|
5623 |
+
}
|
5624 |
+
},
|
5625 |
+
|
5626 |
+
/**
|
5627 |
+
* Close the dialog
|
5628 |
+
*
|
5629 |
+
* @param e
|
5630 |
+
* @returns {boolean}
|
5631 |
+
*/
|
5632 |
+
closeDialog: function ( options ) {
|
5633 |
+
options = _.extend( {
|
5634 |
+
silent: false
|
5635 |
+
}, options );
|
5636 |
+
|
5637 |
+
if ( ! options.silent ) {
|
5638 |
+
this.trigger( 'close_dialog' );
|
5639 |
+
}
|
5640 |
+
|
5641 |
+
this.dialogOpen = false;
|
5642 |
+
|
5643 |
+
this.$el.hide();
|
5644 |
+
panels.helpers.pageScroll.unlock();
|
5645 |
+
|
5646 |
+
if ( ! options.silent ) {
|
5647 |
+
// This triggers once everything is hidden
|
5648 |
+
this.trigger( 'close_dialog_complete' );
|
5649 |
+
this.builder.trigger( 'close_dialog', this );
|
5650 |
+
}
|
5651 |
+
},
|
5652 |
+
|
5653 |
+
/**
|
5654 |
+
* Navigate to the previous dialog
|
5655 |
+
*/
|
5656 |
+
navToPrevious: function () {
|
5657 |
+
this.closeDialog();
|
5658 |
+
|
5659 |
+
var prev = this.getPrevDialog();
|
5660 |
+
if ( prev !== null && prev !== false ) {
|
5661 |
+
prev.openDialog();
|
5662 |
+
}
|
5663 |
+
},
|
5664 |
+
|
5665 |
+
/**
|
5666 |
+
* Navigate to the next dialog
|
5667 |
+
*/
|
5668 |
+
navToNext: function () {
|
5669 |
+
this.closeDialog();
|
5670 |
+
|
5671 |
+
var next = this.getNextDialog();
|
5672 |
+
if ( next !== null && next !== false ) {
|
5673 |
+
next.openDialog();
|
5674 |
+
}
|
5675 |
+
},
|
5676 |
+
|
5677 |
+
/**
|
5678 |
+
* Get the values from the form and convert them into a data array
|
5679 |
+
*/
|
5680 |
+
getFormValues: function ( formSelector ) {
|
5681 |
+
if ( _.isUndefined( formSelector ) ) {
|
5682 |
+
formSelector = '.so-content';
|
5683 |
+
}
|
5684 |
+
|
5685 |
+
var $f = this.$( formSelector );
|
5686 |
+
|
5687 |
+
var data = {}, parts;
|
5688 |
+
|
5689 |
+
// Find all the named fields in the form
|
5690 |
+
$f.find( '[name]' ).each( function () {
|
5691 |
+
var $$ = $( this );
|
5692 |
+
|
5693 |
+
try {
|
5694 |
+
|
5695 |
+
var name = /([A-Za-z_]+)\[(.*)\]/.exec( $$.attr( 'name' ) );
|
5696 |
+
if ( _.isEmpty( name ) ) {
|
5697 |
+
return true;
|
5698 |
+
}
|
5699 |
+
|
5700 |
+
// Create an array with the parts of the name
|
5701 |
+
if ( _.isUndefined( name[2] ) ) {
|
5702 |
+
parts = $$.attr( 'name' );
|
5703 |
+
} else {
|
5704 |
+
parts = name[2].split( '][' );
|
5705 |
+
parts.unshift( name[1] );
|
5706 |
+
}
|
5707 |
+
|
5708 |
+
parts = parts.map( function ( e ) {
|
5709 |
+
if ( ! isNaN( parseFloat( e ) ) && isFinite( e ) ) {
|
5710 |
+
return parseInt( e );
|
5711 |
+
} else {
|
5712 |
+
return e;
|
5713 |
+
}
|
5714 |
+
} );
|
5715 |
+
|
5716 |
+
var sub = data;
|
5717 |
+
var fieldValue = null;
|
5718 |
+
|
5719 |
+
var fieldType = (
|
5720 |
+
_.isString( $$.attr( 'type' ) ) ? $$.attr( 'type' ).toLowerCase() : false
|
5721 |
+
);
|
5722 |
+
|
5723 |
+
// First we need to get the value from the field
|
5724 |
+
if ( fieldType === 'checkbox' ) {
|
5725 |
+
if ( $$.is( ':checked' ) ) {
|
5726 |
+
fieldValue = $$.val() !== '' ? $$.val() : true;
|
5727 |
+
} else {
|
5728 |
+
fieldValue = null;
|
5729 |
+
}
|
5730 |
+
}
|
5731 |
+
else if ( fieldType === 'radio' ) {
|
5732 |
+
if ( $$.is( ':checked' ) ) {
|
5733 |
+
fieldValue = $$.val();
|
5734 |
+
} else {
|
5735 |
+
//skip over unchecked radios
|
5736 |
+
return;
|
5737 |
+
}
|
5738 |
+
}
|
5739 |
+
else if ( $$.prop( 'tagName' ) === 'SELECT' ) {
|
5740 |
+
var selected = $$.find( 'option:selected' );
|
5741 |
+
|
5742 |
+
if ( selected.length === 1 ) {
|
5743 |
+
fieldValue = $$.find( 'option:selected' ).val();
|
5744 |
+
}
|
5745 |
+
else if ( selected.length > 1 ) {
|
5746 |
+
// This is a mutli-select field
|
5747 |
+
fieldValue = _.map( $$.find( 'option:selected' ), function ( n, i ) {
|
5748 |
+
return $( n ).val();
|
5749 |
+
} );
|
5750 |
+
}
|
5751 |
+
|
5752 |
+
} else {
|
5753 |
+
// This is a fallback that will work for most fields
|
5754 |
+
fieldValue = $$.val();
|
5755 |
+
}
|
5756 |
+
|
5757 |
+
// Now, we need to filter this value if necessary
|
5758 |
+
if ( ! _.isUndefined( $$.data( 'panels-filter' ) ) ) {
|
5759 |
+
switch ( $$.data( 'panels-filter' ) ) {
|
5760 |
+
case 'json_parse':
|
5761 |
+
// Attempt to parse the JSON value of this field
|
5762 |
+
try {
|
5763 |
+
fieldValue = JSON.parse( fieldValue );
|
5764 |
+
}
|
5765 |
+
catch ( err ) {
|
5766 |
+
fieldValue = '';
|
5767 |
+
}
|
5768 |
+
break;
|
5769 |
+
}
|
5770 |
+
}
|
5771 |
+
|
5772 |
+
// Now convert this into an array
|
5773 |
+
if ( fieldValue !== null ) {
|
5774 |
+
for ( var i = 0; i < parts.length; i ++ ) {
|
5775 |
+
if ( i === parts.length - 1 ) {
|
5776 |
+
if ( parts[i] === '' ) {
|
5777 |
+
// This needs to be an array
|
5778 |
+
sub.push( fieldValue );
|
5779 |
+
} else {
|
5780 |
+
sub[parts[i]] = fieldValue;
|
5781 |
+
}
|
5782 |
+
} else {
|
5783 |
+
if ( _.isUndefined( sub[parts[i]] ) ) {
|
5784 |
+
if ( parts[i + 1] === '' ) {
|
5785 |
+
sub[parts[i]] = [];
|
5786 |
+
} else {
|
5787 |
+
sub[parts[i]] = {};
|
5788 |
+
}
|
5789 |
+
}
|
5790 |
+
sub = sub[parts[i]];
|
5791 |
+
}
|
5792 |
+
}
|
5793 |
+
}
|
5794 |
+
}
|
5795 |
+
catch ( error ) {
|
5796 |
+
// Ignore this error, just log the message for debugging
|
5797 |
+
console.log( 'Field [' + $$.attr('name') + '] could not be processed and was skipped - ' + error.message );
|
5798 |
+
}
|
5799 |
+
|
5800 |
+
} ); // End of each through input fields
|
5801 |
+
|
5802 |
+
return data;
|
5803 |
+
},
|
5804 |
+
|
5805 |
+
/**
|
5806 |
+
* Set a status message for the dialog
|
5807 |
+
*/
|
5808 |
+
setStatusMessage: function ( message, loading, error ) {
|
5809 |
+
var msg = error ? '<span class="dashicons dashicons-warning"></span>' + message : message;
|
5810 |
+
this.$( '.so-toolbar .so-status' ).html( msg );
|
5811 |
+
if ( ! _.isUndefined( loading ) && loading ) {
|
5812 |
+
this.$( '.so-toolbar .so-status' ).addClass( 'so-panels-loading' );
|
5813 |
+
} else {
|
5814 |
+
this.$( '.so-toolbar .so-status' ).removeClass( 'so-panels-loading' );
|
5815 |
+
}
|
5816 |
+
},
|
5817 |
+
|
5818 |
+
/**
|
5819 |
+
* Set the parent after.
|
5820 |
+
*/
|
5821 |
+
setParent: function ( text, dialog ) {
|
5822 |
+
this.parentDialog = {
|
5823 |
+
text: text,
|
5824 |
+
dialog: dialog
|
5825 |
+
};
|
5826 |
+
},
|
5827 |
+
|
5828 |
+
onResize: function () {
|
5829 |
+
var mediaQuery = window.matchMedia( '(max-width: 980px)' );
|
5830 |
+
var sides = [ 'left', 'right' ];
|
5831 |
+
|
5832 |
+
sides.forEach( function ( side ) {
|
5833 |
+
var $sideBar = this.$( '.so-' + side + '-sidebar' );
|
5834 |
+
var $showSideBarButton = this.$( '.so-show-' + side + '-sidebar' );
|
5835 |
+
if ( this.hasSidebar( side ) ) {
|
5836 |
+
$showSideBarButton.hide();
|
5837 |
+
if ( mediaQuery.matches ) {
|
5838 |
+
$showSideBarButton.show();
|
5839 |
+
$showSideBarButton.closest( '.so-title-bar' ).addClass( 'so-has-' + side + '-button' );
|
5840 |
+
$sideBar.hide();
|
5841 |
+
$sideBar.closest( '.so-panels-dialog' ).removeClass( 'so-panels-dialog-has-' + side + '-sidebar' );
|
5842 |
+
} else {
|
5843 |
+
$showSideBarButton.hide();
|
5844 |
+
$showSideBarButton.closest( '.so-title-bar' ).removeClass( 'so-has-' + side + '-button' );
|
5845 |
+
$sideBar.show();
|
5846 |
+
$sideBar.closest( '.so-panels-dialog' ).addClass( 'so-panels-dialog-has-' + side + '-sidebar' );
|
5847 |
+
}
|
5848 |
+
} else {
|
5849 |
+
$sideBar.hide();
|
5850 |
+
$showSideBarButton.hide();
|
5851 |
+
}
|
5852 |
+
}.bind( this ) );
|
5853 |
+
},
|
5854 |
+
|
5855 |
+
hasSidebar: function ( side ) {
|
5856 |
+
return this.$( '.so-' + side + '-sidebar' ).children().length > 0;
|
5857 |
+
},
|
5858 |
+
|
5859 |
+
toggleLeftSideBar: function () {
|
5860 |
+
this.toggleSidebar( 'left' );
|
5861 |
+
},
|
5862 |
+
|
5863 |
+
toggleRightSideBar: function () {
|
5864 |
+
this.toggleSidebar( 'right' );
|
5865 |
+
},
|
5866 |
+
|
5867 |
+
toggleSidebar: function ( side ) {
|
5868 |
+
var sidebar = this.$( '.so-' + side + '-sidebar' );
|
5869 |
+
|
5870 |
+
if ( sidebar.is( ':visible' ) ) {
|
5871 |
+
sidebar.hide();
|
5872 |
+
} else {
|
5873 |
+
sidebar.show();
|
5874 |
+
}
|
5875 |
+
},
|
5876 |
+
|
5877 |
+
} );
|
5878 |
+
|
5879 |
+
},{}],26:[function(require,module,exports){
|
5880 |
+
var panels = window.panels, $ = jQuery;
|
5881 |
+
|
5882 |
+
module.exports = Backbone.View.extend( {
|
5883 |
+
template: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-live-editor' ).html() ) ),
|
5884 |
+
|
5885 |
+
previewScrollTop: 0,
|
5886 |
+
loadTimes: [],
|
5887 |
+
previewFrameId: 1,
|
5888 |
+
|
5889 |
+
previewUrl: null,
|
5890 |
+
previewIframe: null,
|
5891 |
+
|
5892 |
+
events: {
|
5893 |
+
'click .live-editor-close': 'close',
|
5894 |
+
'click .live-editor-save': 'closeAndSave',
|
5895 |
+
'click .live-editor-collapse': 'collapse',
|
5896 |
+
'click .live-editor-mode': 'mobileToggle'
|
5897 |
+
},
|
5898 |
+
|
5899 |
+
initialize: function ( options ) {
|
5900 |
+
options = _.extend( {
|
5901 |
+
builder: false,
|
5902 |
+
previewUrl: false,
|
5903 |
+
}, options );
|
5904 |
+
|
5905 |
+
if( _.isEmpty( options.previewUrl ) ) {
|
5906 |
+
options.previewUrl = panelsOptions.ajaxurl + "&action=so_panels_live_editor_preview";
|
5907 |
+
}
|
5908 |
+
|
5909 |
+
this.builder = options.builder;
|
5910 |
+
this.previewUrl = options.previewUrl;
|
5911 |
+
|
5912 |
+
this.listenTo( this.builder.model, 'refresh_panels_data', this.handleRefreshData );
|
5913 |
+
this.listenTo( this.builder.model, 'load_panels_data', this.handleLoadData );
|
5914 |
+
},
|
5915 |
+
|
5916 |
+
/**
|
5917 |
+
* Render the live editor
|
5918 |
+
*/
|
5919 |
+
render: function () {
|
5920 |
+
this.setElement( this.template() );
|
5921 |
+
this.$el.hide();
|
5922 |
+
|
5923 |
+
if ( $( '#submitdiv #save-post' ).length > 0 ) {
|
5924 |
+
var $saveButton = this.$el.find( '.live-editor-save' );
|
5925 |
+
$saveButton.text( $saveButton.data( 'save' ) );
|
5926 |
+
}
|
5927 |
+
|
5928 |
+
var isMouseDown = false;
|
5929 |
+
$( document )
|
5930 |
+
.mousedown( function () {
|
5931 |
+
isMouseDown = true;
|
5932 |
+
} )
|
5933 |
+
.mouseup( function () {
|
5934 |
+
isMouseDown = false;
|
5935 |
+
} );
|
5936 |
+
|
5937 |
+
// Handle highlighting the relevant widget in the live editor preview
|
5938 |
+
var liveEditorView = this;
|
5939 |
+
this.$el.on( 'mouseenter', '.so-widget-wrapper', function () {
|
5940 |
+
var $$ = $( this ),
|
5941 |
+
previewWidget = $$.data( 'live-editor-preview-widget' );
|
5942 |
+
|
5943 |
+
if ( ! isMouseDown && previewWidget !== undefined && previewWidget.length && ! liveEditorView.$( '.so-preview-overlay' ).is( ':visible' ) ) {
|
5944 |
+
liveEditorView.highlightElement( previewWidget );
|
5945 |
+
liveEditorView.scrollToElement( previewWidget );
|
5946 |
+
}
|
5947 |
+
} );
|
5948 |
+
|
5949 |
+
this.$el.on( 'mouseleave', '.so-widget-wrapper', function () {
|
5950 |
+
this.resetHighlights();
|
5951 |
+
}.bind(this) );
|
5952 |
+
|
5953 |
+
this.listenTo( this.builder, 'open_dialog', function () {
|
5954 |
+
this.resetHighlights();
|
5955 |
+
} );
|
5956 |
+
|
5957 |
+
return this;
|
5958 |
+
},
|
5959 |
+
|
5960 |
+
/**
|
5961 |
+
* Attach the live editor to the document
|
5962 |
+
*/
|
5963 |
+
attach: function () {
|
5964 |
+
this.$el.appendTo( 'body' );
|
5965 |
+
},
|
5966 |
+
|
5967 |
+
/**
|
5968 |
+
* Display the live editor
|
5969 |
+
*/
|
5970 |
+
open: function () {
|
5971 |
+
if ( this.$el.html() === '' ) {
|
5972 |
+
this.render();
|
5973 |
+
}
|
5974 |
+
if ( this.$el.closest( 'body' ).length === 0 ) {
|
5975 |
+
this.attach();
|
5976 |
+
}
|
5977 |
+
|
5978 |
+
// Disable page scrolling
|
5979 |
+
panels.helpers.pageScroll.lock();
|
5980 |
+
|
5981 |
+
if ( this.$el.is( ':visible' ) ) {
|
5982 |
+
return this;
|
5983 |
+
}
|
5984 |
+
|
5985 |
+
// Refresh the preview display
|
5986 |
+
this.$el.show();
|
5987 |
+
this.refreshPreview( this.builder.model.getPanelsData() );
|
5988 |
+
|
5989 |
+
// Move the builder view into the Live Editor
|
5990 |
+
this.originalContainer = this.builder.$el.parent();
|
5991 |
+
this.builder.$el.appendTo( this.$( '.so-live-editor-builder' ) );
|
5992 |
+
this.builder.$( '.so-tool-button.so-live-editor' ).hide();
|
5993 |
+
this.builder.trigger( 'builder_resize' );
|
5994 |
+
|
5995 |
+
|
5996 |
+
if( $('#original_post_status' ).val() === 'auto-draft' && ! this.autoSaved ) {
|
5997 |
+
// The live editor requires a saved draft post, so we'll create one for auto-draft posts
|
5998 |
+
var thisView = this;
|
5999 |
+
|
6000 |
+
if ( wp.autosave ) {
|
6001 |
+
// Set a temporary post title so the autosave triggers properly
|
6002 |
+
if( $('#title[name="post_title"]' ).val() === '' ) {
|
6003 |
+
$('#title[name="post_title"]' ).val( panelsOptions.loc.draft ).trigger('keydown');
|
6004 |
+
}
|
6005 |
+
|
6006 |
+
$( document ).one( 'heartbeat-tick.autosave', function(){
|
6007 |
+
thisView.autoSaved = true;
|
6008 |
+
thisView.refreshPreview( thisView.builder.model.getPanelsData() );
|
6009 |
+
} );
|
6010 |
+
wp.autosave.server.triggerSave();
|
6011 |
+
}
|
6012 |
+
}
|
6013 |
+
},
|
6014 |
+
|
6015 |
+
/**
|
6016 |
+
* Close the Live Editor
|
6017 |
+
*/
|
6018 |
+
close: function () {
|
6019 |
+
if ( ! this.$el.is( ':visible' ) ) {
|
6020 |
+
return this;
|
6021 |
+
}
|
6022 |
+
|
6023 |
+
this.$el.hide();
|
6024 |
+
panels.helpers.pageScroll.unlock();
|
6025 |
+
|
6026 |
+
// Move the builder back to its original container
|
6027 |
+
this.builder.$el.appendTo( this.originalContainer );
|
6028 |
+
this.builder.$( '.so-tool-button.so-live-editor' ).show();
|
6029 |
+
this.builder.trigger( 'builder_resize' );
|
6030 |
+
},
|
6031 |
+
|
6032 |
+
/**
|
6033 |
+
* Close the Live Editor and save the post.
|
6034 |
+
*/
|
6035 |
+
closeAndSave: function(){
|
6036 |
+
this.close();
|
6037 |
+
// Finds the submit input for saving without publishing draft posts.
|
6038 |
+
$('#submitdiv input[type="submit"][name="save"]').click();
|
6039 |
+
},
|
6040 |
+
|
6041 |
+
/**
|
6042 |
+
* Collapse the live editor
|
6043 |
+
*/
|
6044 |
+
collapse: function () {
|
6045 |
+
this.$el.toggleClass( 'so-collapsed' );
|
6046 |
+
},
|
6047 |
+
|
6048 |
+
/**
|
6049 |
+
* Create an overlay in the preview.
|
6050 |
+
*
|
6051 |
+
* @param over
|
6052 |
+
* @return {*|Object} The item we're hovering over.
|
6053 |
+
*/
|
6054 |
+
highlightElement: function ( over ) {
|
6055 |
+
if( ! _.isUndefined( this.resetHighlightTimeout ) ) {
|
6056 |
+
clearTimeout( this.resetHighlightTimeout );
|
6057 |
+
}
|
6058 |
+
|
6059 |
+
// Remove any old overlays
|
6060 |
+
|
6061 |
+
var body = this.previewIframe.contents().find( 'body' );
|
6062 |
+
body.find( '.panel-grid .panel-grid-cell .so-panel' )
|
6063 |
+
.filter( function () {
|
6064 |
+
// Filter to only include non nested
|
6065 |
+
return $( this ).parents( '.so-panel' ).length === 0;
|
6066 |
+
} )
|
6067 |
+
.not( over )
|
6068 |
+
.addClass( 'so-panels-faded' );
|
6069 |
+
|
6070 |
+
over.removeClass( 'so-panels-faded' ).addClass( 'so-panels-highlighted' );
|
6071 |
+
},
|
6072 |
+
|
6073 |
+
/**
|
6074 |
+
* Reset highlights in the live preview
|
6075 |
+
*/
|
6076 |
+
resetHighlights: function() {
|
6077 |
+
|
6078 |
+
var body = this.previewIframe.contents().find( 'body' );
|
6079 |
+
this.resetHighlightTimeout = setTimeout( function(){
|
6080 |
+
body.find( '.panel-grid .panel-grid-cell .so-panel' )
|
6081 |
+
.removeClass( 'so-panels-faded so-panels-highlighted' );
|
6082 |
+
}, 100 );
|
6083 |
+
},
|
6084 |
+
|
6085 |
+
/**
|
6086 |
+
* Scroll over an element in the live preview
|
6087 |
+
* @param over
|
6088 |
+
*/
|
6089 |
+
scrollToElement: function( over ) {
|
6090 |
+
var contentWindow = this.$( '.so-preview iframe' )[0].contentWindow;
|
6091 |
+
contentWindow.liveEditorScrollTo( over );
|
6092 |
+
},
|
6093 |
+
|
6094 |
+
handleRefreshData: function ( newData ) {
|
6095 |
+
if ( ! this.$el.is( ':visible' ) ) {
|
6096 |
+
return this;
|
6097 |
+
}
|
6098 |
+
|
6099 |
+
this.refreshPreview( newData );
|
6100 |
+
},
|
6101 |
+
|
6102 |
+
handleLoadData: function () {
|
6103 |
+
if ( ! this.$el.is( ':visible' ) ) {
|
6104 |
+
return this;
|
6105 |
+
}
|
6106 |
+
|
6107 |
+
this.refreshPreview( this.builder.model.getPanelsData() );
|
6108 |
+
},
|
6109 |
+
|
6110 |
+
/**
|
6111 |
+
* Refresh the Live Editor preview.
|
6112 |
+
* @returns {exports}
|
6113 |
+
*/
|
6114 |
+
refreshPreview: function ( data ) {
|
6115 |
+
var loadTimePrediction = this.loadTimes.length ?
|
6116 |
+
_.reduce( this.loadTimes, function ( memo, num ) {
|
6117 |
+
return memo + num;
|
6118 |
+
}, 0 ) / this.loadTimes.length : 1000;
|
6119 |
+
|
6120 |
+
// Store the last preview iframe position
|
6121 |
+
if( ! _.isNull( this.previewIframe ) ) {
|
6122 |
+
if ( ! this.$( '.so-preview-overlay' ).is( ':visible' ) ) {
|
6123 |
+
this.previewScrollTop = this.previewIframe.contents().scrollTop();
|
6124 |
+
}
|
6125 |
+
}
|
6126 |
+
|
6127 |
+
// Add a loading bar
|
6128 |
+
this.$( '.so-preview-overlay' ).show();
|
6129 |
+
this.$( '.so-preview-overlay .so-loading-bar' )
|
6130 |
+
.clearQueue()
|
6131 |
+
.css( 'width', '0%' )
|
6132 |
+
.animate( {width: '100%'}, parseInt( loadTimePrediction ) + 100 );
|
6133 |
+
|
6134 |
+
|
6135 |
+
this.postToIframe(
|
6136 |
+
{
|
6137 |
+
live_editor_panels_data: JSON.stringify( data ),
|
6138 |
+
live_editor_post_ID: this.builder.config.postId
|
6139 |
+
},
|
6140 |
+
this.previewUrl,
|
6141 |
+
this.$('.so-preview')
|
6142 |
+
);
|
6143 |
+
|
6144 |
+
this.previewIframe.data( 'load-start', new Date().getTime() );
|
6145 |
+
},
|
6146 |
+
|
6147 |
+
/**
|
6148 |
+
* Use a temporary form to post data to an iframe.
|
6149 |
+
*
|
6150 |
+
* @param data The data to send
|
6151 |
+
* @param url The preview URL
|
6152 |
+
* @param target The target iframe
|
6153 |
+
*/
|
6154 |
+
postToIframe: function( data, url, target ){
|
6155 |
+
// Store the old preview
|
6156 |
+
|
6157 |
+
if( ! _.isNull( this.previewIframe ) ) {
|
6158 |
+
this.previewIframe.remove();
|
6159 |
+
}
|
6160 |
Â
|
6161 |
+
var iframeId = 'siteorigin-panels-live-preview-' + this.previewFrameId;
|
6162 |
+
|
6163 |
+
// Remove the old preview frame
|
6164 |
+
this.previewIframe = $('<iframe src="javascript:false;" />')
|
6165 |
+
.attr( {
|
6166 |
+
'id' : iframeId,
|
6167 |
+
'name' : iframeId,
|
6168 |
+
} )
|
6169 |
+
.appendTo( target );
|
6170 |
+
|
6171 |
+
this.setupPreviewFrame( this.previewIframe );
|
6172 |
+
|
6173 |
+
// We can use a normal POST form submit
|
6174 |
+
var tempForm = $('<form id="soPostToPreviewFrame" method="post" />')
|
6175 |
+
.attr( {
|
6176 |
+
id: iframeId,
|
6177 |
+
target: this.previewIframe.attr('id'),
|
6178 |
+
action: url
|
6179 |
+
} )
|
6180 |
+
.appendTo( 'body' );
|
6181 |
+
|
6182 |
+
$.each( data, function( name, value ){
|
6183 |
+
$('<input type="hidden" />')
|
6184 |
+
.attr( {
|
6185 |
+
name: name,
|
6186 |
+
value: value
|
6187 |
+
} )
|
6188 |
+
.appendTo( tempForm );
|
6189 |
+
} );
|
6190 |
+
|
6191 |
+
tempForm
|
6192 |
+
.submit()
|
6193 |
+
.remove();
|
6194 |
+
|
6195 |
+
this.previewFrameId++;
|
6196 |
+
|
6197 |
+
return this.previewIframe;
|
6198 |
+
},
|
6199 |
+
|
6200 |
+
/**
|
6201 |
+
* Do all the basic setup for the preview Iframe element
|
6202 |
+
* @param iframe
|
6203 |
+
*/
|
6204 |
+
setupPreviewFrame: function( iframe ){
|
6205 |
+
var thisView = this;
|
6206 |
+
iframe
|
6207 |
+
.data( 'iframeready', false )
|
6208 |
+
.on( 'iframeready', function () {
|
6209 |
+
var $$ = $( this ),
|
6210 |
+
$iframeContents = $$.contents();
|
6211 |
+
|
6212 |
+
if( $$.data( 'iframeready' ) ) {
|
6213 |
+
// Skip this if the iframeready function has already run
|
6214 |
+
return;
|
6215 |
+
}
|
6216 |
+
|
6217 |
+
$$.data( 'iframeready', true );
|
6218 |
+
|
6219 |
+
if ( $$.data( 'load-start' ) !== undefined ) {
|
6220 |
+
thisView.loadTimes.unshift( new Date().getTime() - $$.data( 'load-start' ) );
|
6221 |
+
|
6222 |
+
if ( ! _.isEmpty( thisView.loadTimes ) ) {
|
6223 |
+
thisView.loadTimes = thisView.loadTimes.slice( 0, 4 );
|
6224 |
+
}
|
6225 |
+
}
|
6226 |
+
|
6227 |
+
setTimeout( function(){
|
6228 |
+
// Scroll to the correct position
|
6229 |
+
$iframeContents.scrollTop( thisView.previewScrollTop );
|
6230 |
+
thisView.$( '.so-preview-overlay' ).hide();
|
6231 |
+
}, 100 );
|
6232 |
+
|
6233 |
+
|
6234 |
+
// Lets find all the first level grids. This is to account for the Page Builder layout widget.
|
6235 |
+
var layoutWrapper = $iframeContents.find( '#pl-' + thisView.builder.config.postId );
|
6236 |
+
layoutWrapper.find( '.panel-grid .panel-grid-cell .so-panel' )
|
6237 |
+
.filter( function () {
|
6238 |
+
// Filter to only include non nested
|
6239 |
+
return $( this ).closest( '.panel-layout' ).is( layoutWrapper );
|
6240 |
+
} )
|
6241 |
+
.each( function ( i, el ) {
|
6242 |
+
var $$ = $( el );
|
6243 |
+
var widgetEdit = thisView.$( '.so-live-editor-builder .so-widget-wrapper' ).eq( $$.data( 'index' ) );
|
6244 |
+
widgetEdit.data( 'live-editor-preview-widget', $$ );
|
6245 |
+
|
6246 |
+
$$
|
6247 |
+
.css( {
|
6248 |
+
'cursor': 'pointer'
|
6249 |
+
} )
|
6250 |
+
.mouseenter( function () {
|
6251 |
+
widgetEdit.parent().addClass( 'so-hovered' );
|
6252 |
+
thisView.highlightElement( $$ );
|
6253 |
+
} )
|
6254 |
+
.mouseleave( function () {
|
6255 |
+
widgetEdit.parent().removeClass( 'so-hovered' );
|
6256 |
+
thisView.resetHighlights();
|
6257 |
+
} )
|
6258 |
+
.click( function ( e ) {
|
6259 |
+
e.preventDefault();
|
6260 |
+
// When we click a widget, send that click to the form
|
6261 |
+
widgetEdit.find( '.title h4' ).click();
|
6262 |
+
} );
|
6263 |
Â
} );
|
6264 |
+
|
6265 |
+
// Prevent default clicks inside the preview iframe
|
6266 |
+
$iframeContents.find( "a" ).css( {'pointer-events': 'none'} ).click( function ( e ) {
|
6267 |
+
e.preventDefault();
|
6268 |
Â
} );
|
6269 |
+
|
6270 |
+
} )
|
6271 |
+
.on( 'load', function(){
|
6272 |
+
var $$ = $( this );
|
6273 |
+
if( ! $$.data( 'iframeready' ) ) {
|
6274 |
+
$$.trigger('iframeready');
|
6275 |
+
}
|
6276 |
Â
} );
|
6277 |
+
},
|
6278 |
Â
|
6279 |
+
/**
|
6280 |
+
* Return true if the live editor has a valid preview URL.
|
6281 |
+
* @return {boolean}
|
6282 |
+
*/
|
6283 |
+
hasPreviewUrl: function () {
|
6284 |
+
return this.$( 'form.live-editor-form' ).attr( 'action' ) !== '';
|
6285 |
+
},
|
6286 |
Â
|
6287 |
+
/**
|
6288 |
+
* Toggle the size of the preview iframe to simulate mobile devices.
|
6289 |
+
* @param e
|
6290 |
+
*/
|
6291 |
+
mobileToggle: function( e ){
|
6292 |
+
var button = $( e.currentTarget );
|
6293 |
+
this.$('.live-editor-mode' ).not( button ).removeClass('so-active');
|
6294 |
+
button.addClass( 'so-active' );
|
6295 |
+
|
6296 |
+
this.$el
|
6297 |
+
.removeClass( 'live-editor-desktop-mode live-editor-tablet-mode live-editor-mobile-mode' )
|
6298 |
+
.addClass( 'live-editor-' + button.data( 'mode' ) + '-mode' );
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
6299 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
6300 |
Â
}
|
6301 |
Â
} );
|
6302 |
Â
|
6303 |
+
},{}],27:[function(require,module,exports){
|
6304 |
+
var panels = window.panels, $ = jQuery;
|
Â
|
|
Â
|
|
6305 |
Â
|
6306 |
+
module.exports = Backbone.View.extend( {
|
6307 |
+
template: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-builder-row' ).html() ) ),
|
6308 |
Â
|
6309 |
+
events: {
|
6310 |
+
'click .so-row-settings': 'editSettingsHandler',
|
6311 |
+
'click .so-row-duplicate': 'duplicateHandler',
|
6312 |
+
'click .so-row-delete': 'confirmedDeleteHandler',
|
6313 |
+
'click .so-row-color': 'rowColorChangeHandler',
|
6314 |
Â
},
|
6315 |
Â
|
6316 |
+
builder: null,
|
6317 |
+
dialog: null,
|
6318 |
Â
|
6319 |
Â
/**
|
6320 |
+
* Initialize the row view
|
6321 |
Â
*/
|
6322 |
Â
initialize: function () {
|
6323 |
+
|
6324 |
+
var rowCells = this.model.get('cells');
|
6325 |
+
this.listenTo(rowCells, 'add', this.handleCellAdd );
|
6326 |
+
this.listenTo(rowCells, 'remove', this.handleCellRemove );
|
6327 |
+
|
6328 |
+
this.listenTo( this.model, 'reweight_cells', this.resize );
|
6329 |
+
this.listenTo( this.model, 'destroy', this.onModelDestroy );
|
6330 |
+
|
6331 |
+
var thisView = this;
|
6332 |
+
rowCells.each( function ( cell ) {
|
6333 |
+
thisView.listenTo( cell.get('widgets'), 'add', thisView.resize );
|
6334 |
+
} );
|
6335 |
+
|
6336 |
+
// When ever a new cell is added, listen to it for new widgets
|
6337 |
+
rowCells.on( 'add', function ( cell ) {
|
6338 |
+
thisView.listenTo( cell.get('widgets'), 'add', thisView.resize );
|
6339 |
+
}, this );
|
6340 |
+
|
6341 |
+
this.listenTo( this.model, 'change:label', this.onLabelChange );
|
6342 |
Â
},
|
6343 |
Â
|
6344 |
Â
/**
|
6345 |
+
* Render the row.
|
6346 |
+
*
|
6347 |
+
* @returns {panels.view.row}
|
6348 |
Â
*/
|
6349 |
+
render: function () {
|
6350 |
+
var rowColorLabel = this.model.has( 'color_label' ) ? this.model.get( 'color_label' ) : 1;
|
6351 |
+
var rowLabel = this.model.has( 'label' ) ? this.model.get( 'label' ) : '';
|
6352 |
+
this.setElement( this.template( { rowColorLabel: rowColorLabel, rowLabel: rowLabel } ) );
|
6353 |
+
this.$el.data( 'view', this );
|
6354 |
+
|
6355 |
+
// Create views for the cells in this row
|
6356 |
+
var thisView = this;
|
6357 |
+
this.model.get('cells').each( function ( cell ) {
|
6358 |
+
var cellView = new panels.view.cell( {
|
6359 |
+
model: cell
|
6360 |
+
} );
|
6361 |
+
cellView.row = thisView;
|
6362 |
+
cellView.render();
|
6363 |
+
cellView.$el.appendTo( thisView.$( '.so-cells' ) );
|
6364 |
+
} );
|
6365 |
+
|
6366 |
+
// Remove any unsupported actions
|
6367 |
+
if( ! this.builder.supports( 'rowAction' ) ) {
|
6368 |
+
this.$('.so-row-toolbar .so-dropdown-wrapper' ).remove();
|
6369 |
+
this.$el.addClass('so-row-no-actions');
|
6370 |
+
}
|
6371 |
+
else {
|
6372 |
+
if( ! this.builder.supports( 'editRow' ) ) {
|
6373 |
+
this.$('.so-row-toolbar .so-dropdown-links-wrapper .so-row-settings' ).parent().remove();
|
6374 |
+
this.$el.addClass('so-row-no-edit');
|
6375 |
+
}
|
6376 |
+
if( ! this.builder.supports( 'addRow' ) ) {
|
6377 |
+
this.$('.so-row-toolbar .so-dropdown-links-wrapper .so-row-duplicate' ).parent().remove();
|
6378 |
+
this.$el.addClass('so-row-no-duplicate');
|
6379 |
+
}
|
6380 |
+
if( ! this.builder.supports( 'deleteRow' ) ) {
|
6381 |
+
this.$('.so-row-toolbar .so-dropdown-links-wrapper .so-row-delete' ).parent().remove();
|
6382 |
+
this.$el.addClass('so-row-no-delete');
|
6383 |
+
}
|
6384 |
+
}
|
6385 |
+
if( ! this.builder.supports( 'moveRow' ) ) {
|
6386 |
+
this.$('.so-row-toolbar .so-row-move' ).remove();
|
6387 |
+
this.$el.addClass('so-row-no-move');
|
6388 |
+
}
|
6389 |
+
if( !$.trim( this.$('.so-row-toolbar').html() ).length ) {
|
6390 |
+
this.$('.so-row-toolbar' ).remove();
|
6391 |
+
}
|
6392 |
+
|
6393 |
+
// Resize the rows when ever the widget sortable moves
|
6394 |
+
this.listenTo( this.builder, 'widget_sortable_move', this.resize );
|
6395 |
+
this.listenTo( this.builder, 'builder_resize', this.resize );
|
6396 |
+
|
6397 |
+
this.resize();
|
6398 |
+
|
6399 |
+
return this;
|
6400 |
Â
},
|
6401 |
Â
|
6402 |
Â
/**
|
6403 |
+
* Give a visual indication of the creation of this row
|
6404 |
Â
*/
|
6405 |
+
visualCreate: function () {
|
6406 |
+
this.$el.hide().fadeIn( 'fast' );
|
6407 |
+
},
|
6408 |
+
|
6409 |
+
/**
|
6410 |
+
* Visually resize the row so that all cell heights are the same and the widths so that they balance to 100%
|
6411 |
+
*
|
6412 |
+
* @param e
|
6413 |
+
*/
|
6414 |
+
resize: function ( e ) {
|
6415 |
+
// Don't resize this
|
6416 |
+
if ( ! this.$el.is( ':visible' ) ) {
|
6417 |
+
return;
|
6418 |
+
}
|
6419 |
+
|
6420 |
+
// Reset everything to have an automatic height
|
6421 |
+
this.$( '.so-cells .cell-wrapper' ).css( 'min-height', 0 );
|
6422 |
+
this.$( '.so-cells .resize-handle' ).css( 'height', 0 );
|
6423 |
+
|
6424 |
+
// We'll tie the values to the row view, to prevent issue with values going to different rows
|
6425 |
+
var height = 0;
|
6426 |
+
this.$( '.so-cells .cell' ).each( function () {
|
6427 |
+
height = Math.max(
|
6428 |
+
height,
|
6429 |
+
$( this ).height()
|
6430 |
+
);
|
6431 |
+
|
6432 |
+
$( this ).css(
|
6433 |
+
'width',
|
6434 |
+
( $( this ).data( 'view' ).model.get( 'weight' ) * 100) + "%"
|
6435 |
+
);
|
6436 |
+
} );
|
6437 |
+
|
6438 |
+
// Resize all the grids and cell wrappers
|
6439 |
+
this.$( '.so-cells .cell-wrapper' ).css( 'min-height', Math.max( height, 63 ) );
|
6440 |
+
this.$( '.so-cells .resize-handle' ).css( 'height', this.$( '.so-cells .cell-wrapper' ).outerHeight() );
|
6441 |
+
},
|
6442 |
+
|
6443 |
+
/**
|
6444 |
+
* Remove the view from the dom.
|
6445 |
+
*/
|
6446 |
+
onModelDestroy: function () {
|
6447 |
+
this.remove();
|
6448 |
+
},
|
6449 |
+
|
6450 |
+
/**
|
6451 |
+
* Fade out the view and destroy the model
|
6452 |
+
*/
|
6453 |
+
visualDestroyModel: function () {
|
6454 |
+
this.builder.addHistoryEntry( 'row_deleted' );
|
6455 |
+
var thisView = this;
|
6456 |
+
this.$el.fadeOut( 'normal', function () {
|
6457 |
+
thisView.model.destroy();
|
6458 |
+
thisView.builder.model.refreshPanelsData();
|
6459 |
+
} );
|
6460 |
+
},
|
6461 |
+
|
6462 |
+
onLabelChange: function( model, text ) {
|
6463 |
+
if ( this.$('.so-row-label').length == 0 ) {
|
6464 |
+
this.$( '.so-row-toolbar' ).prepend( '<h3 class="so-row-label">' + text + '</h3>' );
|
6465 |
+
} else {
|
6466 |
+
this.$('.so-row-label').text( text );
|
6467 |
+
}
|
6468 |
+
},
|
6469 |
+
|
6470 |
+
/**
|
6471 |
+
* Duplicate this row.
|
6472 |
+
*
|
6473 |
+
* @return {boolean}
|
6474 |
+
*/
|
6475 |
+
duplicateHandler: function () {
|
6476 |
+
this.builder.addHistoryEntry( 'row_duplicated' );
|
6477 |
+
|
6478 |
+
var duplicateRow = this.model.clone( this.builder.model );
|
6479 |
+
|
6480 |
+
this.builder.model.get('rows').add( duplicateRow, {
|
6481 |
+
at: this.builder.model.get('rows').indexOf( this.model ) + 1
|
6482 |
+
} );
|
6483 |
+
|
6484 |
+
this.builder.model.refreshPanelsData();
|
6485 |
+
},
|
6486 |
+
|
6487 |
+
/**
|
6488 |
+
* Copy the row to a localStorage
|
6489 |
+
*/
|
6490 |
+
copyHandler: function(){
|
6491 |
+
panels.helpers.clipboard.setModel( this.model );
|
6492 |
+
},
|
6493 |
+
|
6494 |
+
/**
|
6495 |
+
* Create a new row and insert it
|
6496 |
+
*/
|
6497 |
+
pasteHandler: function(){
|
6498 |
+
var pastedModel = panels.helpers.clipboard.getModel( 'row-model' );
|
6499 |
+
|
6500 |
+
if( ! _.isEmpty( pastedModel ) && pastedModel instanceof panels.model.row ) {
|
6501 |
+
this.builder.addHistoryEntry( 'row_pasted' );
|
6502 |
+
pastedModel.builder = this.builder.model;
|
6503 |
+
this.builder.model.get('rows').add( pastedModel, {
|
6504 |
+
at: this.builder.model.get('rows').indexOf( this.model ) + 1
|
6505 |
+
} );
|
6506 |
+
this.builder.model.refreshPanelsData();
|
6507 |
+
}
|
6508 |
+
},
|
6509 |
+
|
6510 |
+
/**
|
6511 |
+
* Handles deleting the row with a confirmation.
|
6512 |
+
*/
|
6513 |
+
confirmedDeleteHandler: function ( e ) {
|
6514 |
+
var $$ = $( e.target );
|
6515 |
+
|
6516 |
+
// The user clicked on the dashicon
|
6517 |
+
if ( $$.hasClass( 'dashicons' ) ) {
|
6518 |
+
$$ = $$.parent();
|
6519 |
+
}
|
6520 |
+
|
6521 |
+
if ( $$.hasClass( 'so-confirmed' ) ) {
|
6522 |
+
this.visualDestroyModel();
|
6523 |
+
} else {
|
6524 |
+
var originalText = $$.html();
|
6525 |
+
|
6526 |
+
$$.addClass( 'so-confirmed' ).html(
|
6527 |
+
'<span class="dashicons dashicons-yes"></span>' + panelsOptions.loc.dropdown_confirm
|
6528 |
+
);
|
6529 |
+
|
6530 |
+
setTimeout( function () {
|
6531 |
+
$$.removeClass( 'so-confirmed' ).html( originalText );
|
6532 |
+
}, 2500 );
|
6533 |
+
}
|
6534 |
+
},
|
6535 |
+
|
6536 |
+
/**
|
6537 |
+
* Handle displaying the settings dialog
|
6538 |
+
*/
|
6539 |
+
editSettingsHandler: function () {
|
6540 |
+
if ( ! this.builder.supports( 'editRow' ) ) {
|
6541 |
+
return;
|
6542 |
+
}
|
6543 |
+
// Lets open up an instance of the settings dialog
|
6544 |
+
if ( this.dialog === null ) {
|
6545 |
+
// Create the dialog
|
6546 |
+
this.dialog = new panels.dialog.row();
|
6547 |
+
this.dialog.setBuilder( this.builder ).setRowModel( this.model );
|
6548 |
+
this.dialog.rowView = this;
|
6549 |
+
}
|
6550 |
+
|
6551 |
+
this.dialog.openDialog();
|
6552 |
+
|
6553 |
+
return this;
|
6554 |
+
},
|
6555 |
+
|
6556 |
+
/**
|
6557 |
+
* Handle deleting this entire row.
|
6558 |
+
*/
|
6559 |
+
deleteHandler: function () {
|
6560 |
+
this.model.destroy();
|
6561 |
+
return this;
|
6562 |
+
},
|
6563 |
+
|
6564 |
+
/**
|
6565 |
+
* Change the row background color.
|
6566 |
+
*/
|
6567 |
+
rowColorChangeHandler: function ( event ) {
|
6568 |
+
this.$( '.so-row-color' ).removeClass( 'so-row-color-selected' );
|
6569 |
+
var clickedColorElem = $( event.target );
|
6570 |
+
var newColorLabel = clickedColorElem.data( 'color-label' );
|
6571 |
+
var oldColorLabel = this.model.has( 'color_label' ) ? this.model.get( 'color_label' ) : 1;
|
6572 |
+
clickedColorElem.addClass( 'so-row-color-selected' );
|
6573 |
+
this.$el.removeClass( 'so-row-color-' + oldColorLabel );
|
6574 |
+
this.$el.addClass( 'so-row-color-' + newColorLabel );
|
6575 |
+
this.model.set( 'color_label', newColorLabel );
|
6576 |
+
},
|
6577 |
+
|
6578 |
+
/**
|
6579 |
+
* Handle a new cell being added to this row view. For now we'll assume the new cell is always last
|
6580 |
+
*/
|
6581 |
+
handleCellAdd: function ( cell ) {
|
6582 |
+
var cellView = new panels.view.cell( {
|
6583 |
+
model: cell
|
6584 |
+
} );
|
6585 |
+
cellView.row = this;
|
6586 |
+
cellView.render();
|
6587 |
+
cellView.$el.appendTo( this.$( '.so-cells' ) );
|
6588 |
+
},
|
6589 |
+
|
6590 |
+
/**
|
6591 |
+
* Handle a cell being removed from this row view
|
6592 |
+
*/
|
6593 |
+
handleCellRemove: function ( cell ) {
|
6594 |
+
// Find the view that ties in to the cell we're removing
|
6595 |
+
this.$( '.so-cells > .cell' ).each( function () {
|
6596 |
+
var view = $( this ).data( 'view' );
|
6597 |
+
if ( _.isUndefined( view ) ) {
|
6598 |
+
return;
|
6599 |
+
}
|
6600 |
+
|
6601 |
+
if ( view.model.cid === cell.cid ) {
|
6602 |
+
// Remove this view
|
6603 |
+
view.remove();
|
6604 |
+
}
|
6605 |
+
} );
|
6606 |
+
},
|
6607 |
+
|
6608 |
+
/**
|
6609 |
+
* Build up the contextual menu for a row
|
6610 |
+
*
|
6611 |
+
* @param e
|
6612 |
+
* @param menu
|
6613 |
+
*/
|
6614 |
+
buildContextualMenu: function ( e, menu ) {
|
6615 |
+
var options = [];
|
6616 |
+
for ( var i = 1; i < 5; i ++ ) {
|
6617 |
+
options.push( {
|
6618 |
+
title: i + ' ' + panelsOptions.loc.contextual.column
|
6619 |
+
} );
|
6620 |
+
}
|
6621 |
+
|
6622 |
+
if( this.builder.supports( 'addRow' ) ) {
|
6623 |
+
menu.addSection(
|
6624 |
+
'add-row',
|
6625 |
+
{
|
6626 |
+
sectionTitle: panelsOptions.loc.contextual.add_row,
|
6627 |
+
search: false
|
6628 |
+
},
|
6629 |
+
options,
|
6630 |
+
function ( c ) {
|
6631 |
+
this.builder.addHistoryEntry( 'row_added' );
|
6632 |
+
|
6633 |
+
var columns = Number( c ) + 1;
|
6634 |
+
var weights = [];
|
6635 |
+
for ( var i = 0; i < columns; i ++ ) {
|
6636 |
+
weights.push( {weight: 100 / columns } );
|
6637 |
+
}
|
6638 |
+
|
6639 |
+
// Create the actual row
|
6640 |
+
var newRow = new panels.model.row( {
|
6641 |
+
collection: this.collection
|
6642 |
+
} );
|
6643 |
+
|
6644 |
+
var cells = new panels.collection.cells(weights);
|
6645 |
+
cells.each(function (cell) {
|
6646 |
+
cell.row = newRow;
|
6647 |
+
});
|
6648 |
+
newRow.setCells(cells);
|
6649 |
+
newRow.builder = this.builder.model;
|
6650 |
+
|
6651 |
+
this.builder.model.get('rows').add( newRow, {
|
6652 |
+
at: this.builder.model.get('rows').indexOf( this.model ) + 1
|
6653 |
+
} );
|
6654 |
+
|
6655 |
+
this.builder.model.refreshPanelsData();
|
6656 |
+
}.bind( this )
|
6657 |
+
);
|
6658 |
Â
}
|
Â
|
|
6659 |
Â
|
6660 |
+
var actions = {};
|
Â
|
|
Â
|
|
6661 |
Â
|
6662 |
+
if( this.builder.supports( 'editRow' ) ) {
|
6663 |
+
actions.edit = { title: panelsOptions.loc.contextual.row_edit };
|
Â
|
|
Â
|
|
Â
|
|
6664 |
Â
}
|
6665 |
Â
|
6666 |
+
// Copy and paste functions
|
6667 |
+
if ( panels.helpers.clipboard.canCopyPaste() ) {
|
6668 |
+
actions.copy = { title: panelsOptions.loc.contextual.row_copy };
|
6669 |
+
if ( this.builder.supports( 'addRow' ) && panels.helpers.clipboard.isModel( 'row-model' ) ) {
|
6670 |
+
actions.paste = { title: panelsOptions.loc.contextual.row_paste };
|
6671 |
+
}
|
6672 |
+
}
|
6673 |
Â
|
6674 |
+
if( this.builder.supports( 'addRow' ) ) {
|
6675 |
+
actions.duplicate = { title: panelsOptions.loc.contextual.row_duplicate };
|
6676 |
+
}
|
6677 |
Â
|
6678 |
+
if( this.builder.supports( 'deleteRow' ) ) {
|
6679 |
+
actions.delete = { title: panelsOptions.loc.contextual.row_delete, confirm: true };
|
6680 |
+
}
|
6681 |
+
|
6682 |
+
if( ! _.isEmpty( actions ) ) {
|
6683 |
+
menu.addSection(
|
6684 |
+
'row-actions',
|
6685 |
+
{
|
6686 |
+
sectionTitle: panelsOptions.loc.contextual.row_actions,
|
6687 |
+
search: false,
|
6688 |
+
},
|
6689 |
+
actions,
|
6690 |
+
function ( c ) {
|
6691 |
+
switch ( c ) {
|
6692 |
+
case 'edit':
|
6693 |
+
this.editSettingsHandler();
|
6694 |
+
break;
|
6695 |
+
case 'copy':
|
6696 |
+
this.copyHandler();
|
6697 |
+
break;
|
6698 |
+
case 'paste':
|
6699 |
+
this.pasteHandler();
|
6700 |
+
break;
|
6701 |
+
case 'duplicate':
|
6702 |
+
this.duplicateHandler();
|
6703 |
+
break;
|
6704 |
+
case 'delete':
|
6705 |
+
this.visualDestroyModel();
|
6706 |
+
break;
|
6707 |
+
}
|
6708 |
+
}.bind( this )
|
6709 |
+
);
|
6710 |
+
}
|
6711 |
+
},
|
6712 |
Â
} );
|
6713 |
Â
|
6714 |
+
},{}],28:[function(require,module,exports){
|
6715 |
+
var panels = window.panels, $ = jQuery;
|
Â
|
|
Â
|
|
6716 |
Â
|
6717 |
+
module.exports = Backbone.View.extend( {
|
Â
|
|
Â
|
|
6718 |
Â
|
6719 |
+
stylesLoaded: false,
|
6720 |
Â
|
Â
|
|
Â
|
|
Â
|
|
6721 |
Â
initialize: function () {
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
6722 |
Â
|
6723 |
+
},
|
6724 |
+
|
6725 |
Â
/**
|
6726 |
+
* Render the visual styles object.
|
6727 |
Â
*
|
6728 |
+
* @param stylesType
|
6729 |
+
* @param postId
|
6730 |
+
* @param args
|
6731 |
Â
*/
|
6732 |
+
render: function ( stylesType, postId, args ) {
|
6733 |
+
if ( _.isUndefined( stylesType ) ) {
|
6734 |
+
return;
|
6735 |
+
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
6736 |
Â
|
6737 |
+
// Add in the default args
|
6738 |
+
args = _.extend( {
|
6739 |
+
builderType: '',
|
6740 |
+
dialog: null
|
6741 |
+
}, args );
|
6742 |
Â
|
6743 |
+
this.$el.addClass( 'so-visual-styles so-' + stylesType + '-styles so-panels-loading' );
|
Â
|
|
Â
|
|
6744 |
Â
|
6745 |
+
var postArgs = {
|
6746 |
+
builderType: args.builderType
|
6747 |
+
};
|
6748 |
Â
|
6749 |
+
if ( stylesType === 'cell') {
|
6750 |
+
postArgs.index = args.index;
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
6751 |
Â
}
|
6752 |
+
|
6753 |
+
// Load the form
|
6754 |
+
$.post(
|
6755 |
+
panelsOptions.ajaxurl,
|
6756 |
+
{
|
6757 |
+
action: 'so_panels_style_form',
|
6758 |
+
type: stylesType,
|
6759 |
+
style: this.model.get( 'style' ),
|
6760 |
+
args: JSON.stringify( postArgs ),
|
6761 |
+
postId: postId
|
6762 |
+
},
|
6763 |
+
null,
|
6764 |
+
'html'
|
6765 |
+
).done( function ( response ) {
|
6766 |
+
this.$el.html( response );
|
6767 |
+
this.setupFields();
|
6768 |
+
this.stylesLoaded = true;
|
6769 |
+
this.trigger( 'styles_loaded', !_.isEmpty( response ) );
|
6770 |
+
if ( !_.isNull( args.dialog ) ) {
|
6771 |
+
args.dialog.trigger( 'styles_loaded', !_.isEmpty( response ) );
|
6772 |
+
}
|
6773 |
+
}.bind( this ) )
|
6774 |
+
.fail( function ( error ) {
|
6775 |
+
var html;
|
6776 |
+
if ( error && error.responseText ) {
|
6777 |
+
html = error.responseText;
|
6778 |
+
} else {
|
6779 |
+
html = panelsOptions.forms.loadingFailed;
|
6780 |
+
}
|
6781 |
+
|
6782 |
+
this.$el.html( html );
|
6783 |
+
}.bind( this ) )
|
6784 |
+
.always( function () {
|
6785 |
+
this.$el.removeClass( 'so-panels-loading' );
|
6786 |
+
}.bind( this ) );
|
6787 |
Â
|
6788 |
+
return this;
|
Â
|
|
6789 |
Â
},
|
6790 |
Â
|
6791 |
Â
/**
|
6792 |
+
* Attach the style view to the DOM.
|
6793 |
+
*
|
6794 |
+
* @param wrapper
|
6795 |
Â
*/
|
6796 |
+
attach: function ( wrapper ) {
|
6797 |
+
wrapper.append( this.$el );
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
6798 |
Â
},
|
6799 |
Â
|
6800 |
Â
/**
|
6801 |
+
* Detach the styles view from the DOM
|
6802 |
Â
*/
|
6803 |
+
detach: function () {
|
6804 |
+
this.$el.detach();
|
Â
|
|
Â
|
|
6805 |
Â
},
|
6806 |
Â
|
6807 |
Â
/**
|
6808 |
+
* Setup all the fields
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
6809 |
Â
*/
|
6810 |
+
setupFields: function () {
|
Â
|
|
Â
|
|
Â
|
|
6811 |
Â
|
6812 |
+
// Set up the sections as collapsible
|
6813 |
+
this.$( '.style-section-wrapper' ).each( function () {
|
6814 |
+
var $s = $( this );
|
6815 |
Â
|
6816 |
+
$s.find( '.style-section-head' ).click( function ( e ) {
|
6817 |
+
e.preventDefault();
|
6818 |
+
$s.find( '.style-section-fields' ).slideToggle( 'fast' );
|
6819 |
+
} );
|
6820 |
Â
} );
|
6821 |
Â
|
6822 |
+
// Set up the color fields
|
6823 |
+
if ( ! _.isUndefined( $.fn.wpColorPicker ) ) {
|
6824 |
+
if ( _.isObject( panelsOptions.wpColorPickerOptions.palettes ) && ! $.isArray( panelsOptions.wpColorPickerOptions.palettes ) ) {
|
6825 |
+
panelsOptions.wpColorPickerOptions.palettes = $.map( panelsOptions.wpColorPickerOptions.palettes, function ( el ) {
|
6826 |
+
return el;
|
6827 |
+
} );
|
6828 |
+
}
|
6829 |
+
this.$( '.so-wp-color-field' ).wpColorPicker( panelsOptions.wpColorPickerOptions );
|
6830 |
+
}
|
6831 |
Â
|
6832 |
+
// Set up the image select fields
|
6833 |
+
this.$( '.style-field-image' ).each( function () {
|
6834 |
+
var frame = null;
|
6835 |
+
var $s = $( this );
|
6836 |
Â
|
6837 |
+
$s.find( '.so-image-selector' ).click( function ( e ) {
|
6838 |
+
e.preventDefault();
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
6839 |
Â
|
6840 |
+
if ( frame === null ) {
|
6841 |
+
// Create the media frame.
|
6842 |
+
frame = wp.media( {
|
6843 |
+
// Set the title of the modal.
|
6844 |
+
title: 'choose',
|
6845 |
+
|
6846 |
+
// Tell the modal to show only images.
|
6847 |
+
library: {
|
6848 |
+
type: 'image'
|
6849 |
+
},
|
6850 |
+
|
6851 |
+
// Customize the submit button.
|
6852 |
+
button: {
|
6853 |
+
// Set the text of the button.
|
6854 |
+
text: 'Done',
|
6855 |
+
close: true
|
6856 |
+
}
|
6857 |
+
} );
|
6858 |
Â
|
6859 |
+
frame.on( 'select', function () {
|
6860 |
+
var attachment = frame.state().get( 'selection' ).first().attributes;
|
Â
|
|
6861 |
Â
|
6862 |
+
var url = attachment.url;
|
6863 |
+
if ( ! _.isUndefined( attachment.sizes ) ) {
|
6864 |
+
try {
|
6865 |
+
url = attachment.sizes.thumbnail.url;
|
6866 |
+
}
|
6867 |
+
catch ( e ) {
|
6868 |
+
// We'll use the full image instead
|
6869 |
+
url = attachment.sizes.full.url;
|
6870 |
+
}
|
6871 |
+
}
|
6872 |
+
$s.find( '.current-image' ).css( 'background-image', 'url(' + url + ')' );
|
6873 |
Â
|
6874 |
+
// Store the ID
|
6875 |
+
$s.find( '.so-image-selector > input' ).val( attachment.id );
|
6876 |
+
|
6877 |
+
$s.find( '.remove-image' ).removeClass( 'hidden' );
|
6878 |
+
} );
|
6879 |
+
}
|
6880 |
Â
|
6881 |
+
frame.open();
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
6882 |
Â
|
6883 |
+
} );
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
6884 |
Â
|
6885 |
+
// Handle clicking on remove
|
6886 |
+
$s.find( '.remove-image' ).click( function ( e ) {
|
Â
|
|
Â
|
|
6887 |
Â
e.preventDefault();
|
6888 |
+
$s.find( '.current-image' ).css( 'background-image', 'none' );
|
6889 |
+
$s.find( '.so-image-selector > input' ).val( '' );
|
6890 |
+
$s.find( '.remove-image' ).addClass( 'hidden' );
|
6891 |
+
} );
|
6892 |
+
} );
|
6893 |
Â
|
6894 |
+
// Set up all the measurement fields
|
6895 |
+
this.$( '.style-field-measurement' ).each( function () {
|
6896 |
+
var $$ = $( this );
|
Â
|
|
6897 |
Â
|
6898 |
+
var text = $$.find( 'input[type="text"]' );
|
6899 |
+
var unit = $$.find( 'select' );
|
6900 |
+
var hidden = $$.find( 'input[type="hidden"]' );
|
6901 |
Â
|
6902 |
+
text.focus( function(){
|
6903 |
+
$(this).select();
|
6904 |
+
} );
|
6905 |
Â
|
6906 |
+
/**
|
6907 |
+
* Load value into the visible input fields.
|
6908 |
+
* @param value
|
6909 |
+
*/
|
6910 |
+
var loadValue = function( value ) {
|
6911 |
+
if( value === '' ) {
|
6912 |
+
return;
|
6913 |
+
}
|
6914 |
+
|
6915 |
+
var re = /(?:([0-9\.,\-]+)(.*))+/;
|
6916 |
+
var valueList = hidden.val().split( ' ' );
|
6917 |
+
var valueListValue = [];
|
6918 |
+
for ( var i in valueList ) {
|
6919 |
+
var match = re.exec( valueList[i] );
|
6920 |
+
if ( ! _.isNull( match ) && ! _.isUndefined( match[1] ) && ! _.isUndefined( match[2] ) ) {
|
6921 |
+
valueListValue.push( match[1] );
|
6922 |
+
unit.val( match[2] );
|
6923 |
+
}
|
6924 |
+
}
|
6925 |
+
|
6926 |
+
if( text.length === 1 ) {
|
6927 |
+
// This is a single input text field
|
6928 |
+
text.val( valueListValue.join( ' ' ) );
|
6929 |
+
}
|
6930 |
+
else {
|
6931 |
+
// We're dealing with a multiple field
|
6932 |
+
if( valueListValue.length === 1 ) {
|
6933 |
+
valueListValue = [ valueListValue[0], valueListValue[0], valueListValue[0], valueListValue[0] ];
|
6934 |
+
}
|
6935 |
+
else if( valueListValue.length === 2 ) {
|
6936 |
+
valueListValue = [ valueListValue[0], valueListValue[1], valueListValue[0], valueListValue[1] ];
|
6937 |
+
}
|
6938 |
+
else if( valueListValue.length === 3 ) {
|
6939 |
+
valueListValue = [ valueListValue[0], valueListValue[1], valueListValue[2], valueListValue[1] ];
|
6940 |
+
}
|
6941 |
+
|
6942 |
+
// Store this in the visible fields
|
6943 |
+
text.each( function( i, el ) {
|
6944 |
+
$( el ).val( valueListValue[i] );
|
6945 |
+
} );
|
6946 |
+
}
|
6947 |
+
};
|
6948 |
+
loadValue( hidden.val() );
|
6949 |
+
|
6950 |
+
/**
|
6951 |
+
* Set value of the hidden field based on inputs
|
6952 |
+
*/
|
6953 |
+
var setValue = function( e ){
|
6954 |
+
var i;
|
6955 |
+
|
6956 |
+
if( text.length === 1 ) {
|
6957 |
+
// We're dealing with a single measurement
|
6958 |
+
var fullString = text
|
6959 |
+
.val()
|
6960 |
+
.split( ' ' )
|
6961 |
+
.filter( function ( value ) {
|
6962 |
+
return value !== '';
|
6963 |
+
} )
|
6964 |
+
.map( function ( value ) {
|
6965 |
+
return value + unit.val();
|
6966 |
+
} )
|
6967 |
+
.join( ' ' );
|
6968 |
+
hidden.val( fullString );
|
6969 |
+
}
|
6970 |
+
else {
|
6971 |
+
var target = $( e.target ),
|
6972 |
+
valueList = [],
|
6973 |
+
emptyIndex = [],
|
6974 |
+
fullIndex = [];
|
6975 |
+
|
6976 |
+
text.each( function( i, el ) {
|
6977 |
+
var value = $( el ).val( ) !== '' ? parseFloat( $( el ).val( ) ) : null;
|
6978 |
+
valueList.push( value );
|
6979 |
+
|
6980 |
+
if( value === null ) {
|
6981 |
+
emptyIndex.push( i );
|
6982 |
+
}
|
6983 |
+
else {
|
6984 |
+
fullIndex.push( i );
|
6985 |
+
}
|
6986 |
+
} );
|
6987 |
+
|
6988 |
+
if( emptyIndex.length === 3 && fullIndex[0] === text.index( target ) ) {
|
6989 |
+
text.val( target.val() );
|
6990 |
+
valueList = [ target.val(), target.val(), target.val(), target.val() ];
|
6991 |
+
}
|
6992 |
+
|
6993 |
+
if( JSON.stringify( valueList ) === JSON.stringify( [ null, null, null, null ] ) ) {
|
6994 |
+
hidden.val('');
|
6995 |
+
}
|
6996 |
+
else {
|
6997 |
+
hidden.val( valueList.map( function( k ){
|
6998 |
+
return ( k === null ? 0 : k ) + unit.val();
|
6999 |
+
} ).join( ' ' ) );
|
7000 |
+
}
|
7001 |
+
}
|
7002 |
+
};
|
7003 |
+
|
7004 |
+
// Set the value when ever anything changes
|
7005 |
+
text.change( setValue );
|
7006 |
+
unit.change( setValue );
|
7007 |
Â
} );
|
7008 |
+
}
|
7009 |
Â
|
7010 |
+
} );
|
Â
|
|
Â
|
|
7011 |
Â
|
7012 |
+
},{}],29:[function(require,module,exports){
|
7013 |
+
var panels = window.panels, $ = jQuery;
|
7014 |
+
|
7015 |
+
module.exports = Backbone.View.extend( {
|
7016 |
+
template: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-builder-widget' ).html() ) ),
|
7017 |
+
|
7018 |
+
// The cell view that this widget belongs to
|
7019 |
+
cell: null,
|
7020 |
+
|
7021 |
+
// The edit dialog
|
7022 |
+
dialog: null,
|
7023 |
+
|
7024 |
+
events: {
|
7025 |
+
'click .widget-edit': 'editHandler',
|
7026 |
+
'click .title h4': 'editHandler',
|
7027 |
+
'click .actions .widget-duplicate': 'duplicateHandler',
|
7028 |
+
'click .actions .widget-delete': 'deleteHandler'
|
7029 |
Â
},
|
7030 |
Â
|
7031 |
Â
/**
|
7032 |
+
* Initialize the widget
|
Â
|
|
Â
|
|
7033 |
Â
*/
|
7034 |
+
initialize: function () {
|
7035 |
+
this.listenTo(this.model, 'destroy', this.onModelDestroy);
|
7036 |
+
this.listenTo(this.model, 'change:values', this.onModelChange);
|
7037 |
+
this.listenTo(this.model, 'change:label', this.onLabelChange);
|
7038 |
+
},
|
7039 |
+
|
7040 |
+
/**
|
7041 |
+
* Render the widget
|
7042 |
+
*/
|
7043 |
+
render: function ( options ) {
|
7044 |
+
options = _.extend( {'loadForm': false}, options );
|
7045 |
Â
|
7046 |
+
this.setElement( this.template( {
|
7047 |
+
title: this.model.getWidgetField( 'title' ),
|
7048 |
+
description: this.model.getTitle(),
|
7049 |
+
widget_class: this.model.attributes.class
|
7050 |
+
} ) );
|
7051 |
Â
|
7052 |
+
this.$el.data( 'view', this );
|
Â
|
|
7053 |
Â
|
7054 |
+
// Remove any unsupported actions
|
7055 |
+
if( ! this.cell.row.builder.supports( 'editWidget' ) || this.model.get( 'read_only' ) ) {
|
7056 |
+
this.$( '.actions .widget-edit' ).remove();
|
7057 |
+
this.$el.addClass('so-widget-no-edit');
|
7058 |
Â
}
|
7059 |
+
if( ! this.cell.row.builder.supports( 'addWidget' ) ) {
|
7060 |
+
this.$( '.actions .widget-duplicate' ).remove();
|
7061 |
+
this.$el.addClass('so-widget-no-duplicate');
|
7062 |
Â
}
|
7063 |
+
if( ! this.cell.row.builder.supports( 'deleteWidget' ) ) {
|
7064 |
+
this.$( '.actions .widget-delete' ).remove();
|
7065 |
+
this.$el.addClass('so-widget-no-delete');
|
Â
|
|
7066 |
Â
}
|
7067 |
+
if( ! this.cell.row.builder.supports( 'moveWidget' ) ) {
|
7068 |
+
this.$el.addClass('so-widget-no-move');
|
7069 |
+
}
|
7070 |
+
if( !$.trim( this.$('.actions').html() ).length ) {
|
7071 |
+
this.$( '.actions' ).remove();
|
7072 |
Â
}
|
7073 |
Â
|
7074 |
+
if( this.model.get( 'read_only' ) ) {
|
7075 |
+
this.$el.addClass('so-widget-read-only');
|
7076 |
+
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
7077 |
Â
|
7078 |
+
if ( _.size( this.model.get( 'values' ) ) === 0 || options.loadForm ) {
|
7079 |
+
// If this widget doesn't have a value, create a form and save it
|
7080 |
+
var dialog = this.getEditDialog();
|
7081 |
Â
|
7082 |
+
// Save the widget as soon as the form is loaded
|
7083 |
+
dialog.once( 'form_loaded', dialog.saveWidget, dialog );
|
Â
|
|
7084 |
Â
|
7085 |
+
// Setup the dialog to load the form
|
7086 |
+
dialog.setupDialog();
|
7087 |
+
}
|
7088 |
+
|
7089 |
+
// Add the global builder listeners
|
7090 |
+
this.listenTo(this.cell.row.builder, 'after_user_adds_widget', this.afterUserAddsWidgetHandler);
|
7091 |
+
|
7092 |
+
return this;
|
7093 |
Â
},
|
7094 |
Â
|
7095 |
Â
/**
|
7096 |
+
* Display an animation that implies creation using a visual animation
|
7097 |
Â
*/
|
7098 |
+
visualCreate: function () {
|
7099 |
+
this.$el.hide().fadeIn( 'fast' );
|
7100 |
+
},
|
7101 |
Â
|
7102 |
+
/**
|
7103 |
+
* Get the dialog view of the form that edits this widget
|
7104 |
+
*
|
7105 |
+
* @returns {null}
|
7106 |
+
*/
|
7107 |
+
getEditDialog: function () {
|
7108 |
+
if ( this.dialog === null ) {
|
7109 |
+
this.dialog = new panels.dialog.widget( {
|
7110 |
+
model: this.model
|
7111 |
+
} );
|
7112 |
+
this.dialog.setBuilder( this.cell.row.builder );
|
7113 |
+
|
7114 |
+
// Store the widget view
|
7115 |
+
this.dialog.widgetView = this;
|
7116 |
Â
}
|
7117 |
+
return this.dialog;
|
7118 |
Â
},
|
7119 |
Â
|
7120 |
Â
/**
|
7121 |
+
* Handle clicking on edit widget.
|
Â
|
|
7122 |
Â
*/
|
7123 |
+
editHandler: function () {
|
7124 |
+
// Create a new dialog for editing this
|
7125 |
+
if ( ! this.cell.row.builder.supports( 'editWidget' ) || this.model.get( 'read_only' ) ) {
|
7126 |
+
return this;
|
7127 |
Â
}
|
7128 |
+
|
7129 |
+
this.getEditDialog().openDialog();
|
7130 |
+
return this;
|
7131 |
Â
},
|
7132 |
Â
|
7133 |
Â
/**
|
7134 |
+
* Handle clicking on duplicate.
|
7135 |
Â
*
|
7136 |
+
* @returns {boolean}
|
Â
|
|
Â
|
|
7137 |
Â
*/
|
7138 |
+
duplicateHandler: function () {
|
7139 |
+
// Add the history entry
|
7140 |
+
this.cell.row.builder.addHistoryEntry( 'widget_duplicated' );
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
7141 |
Â
|
7142 |
+
// Create the new widget and connect it to the widget collection for the current row
|
7143 |
+
var newWidget = this.model.clone( this.model.cell );
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
7144 |
Â
|
7145 |
+
this.cell.model.get('widgets').add( newWidget, {
|
7146 |
+
// Add this after the existing model
|
7147 |
+
at: this.model.collection.indexOf( this.model ) + 1
|
Â
|
|
7148 |
Â
} );
|
7149 |
Â
|
7150 |
+
this.cell.row.builder.model.refreshPanelsData();
|
7151 |
+
return this;
|
7152 |
+
},
|
7153 |
Â
|
7154 |
+
/**
|
7155 |
+
* Copy the row to a cookie based clipboard
|
7156 |
+
*/
|
7157 |
+
copyHandler: function(){
|
7158 |
+
panels.helpers.clipboard.setModel( this.model );
|
7159 |
+
},
|
7160 |
Â
|
7161 |
+
/**
|
7162 |
+
* Handle clicking on delete.
|
7163 |
+
*
|
7164 |
+
* @returns {boolean}
|
7165 |
+
*/
|
7166 |
+
deleteHandler: function () {
|
7167 |
+
this.visualDestroyModel();
|
7168 |
+
return this;
|
7169 |
+
},
|
7170 |
Â
|
7171 |
+
onModelChange: function () {
|
7172 |
+
// Update the description when ever the model changes
|
7173 |
+
this.$( '.description' ).html( this.model.getTitle() );
|
7174 |
+
},
|
Â
|
|
7175 |
Â
|
7176 |
+
onLabelChange: function( model ) {
|
7177 |
+
this.$( '.title > h4' ).text( model.getWidgetField( 'title' ) );
|
7178 |
+
},
|
7179 |
Â
|
7180 |
+
/**
|
7181 |
+
* When the model is destroyed, fade it out
|
7182 |
+
*/
|
7183 |
+
onModelDestroy: function () {
|
7184 |
+
this.remove();
|
7185 |
Â
},
|
7186 |
Â
|
7187 |
Â
/**
|
7188 |
+
* Visually destroy a model
|
Â
|
|
Â
|
|
Â
|
|
7189 |
Â
*/
|
7190 |
+
visualDestroyModel: function () {
|
7191 |
+
// Add the history entry
|
7192 |
+
this.cell.row.builder.addHistoryEntry( 'widget_deleted' );
|
7193 |
+
|
7194 |
+
this.$el.fadeOut( 'fast', function () {
|
7195 |
+
this.cell.row.resize();
|
7196 |
+
this.model.destroy();
|
7197 |
+
this.cell.row.builder.model.refreshPanelsData();
|
7198 |
+
this.remove();
|
7199 |
+
}.bind(this) );
|
7200 |
+
|
7201 |
+
return this;
|
7202 |
Â
},
|
7203 |
Â
|
7204 |
Â
/**
|
7205 |
+
* Build up the contextual menu for a widget
|
7206 |
Â
*
|
7207 |
Â
* @param e
|
7208 |
+
* @param menu
|
7209 |
Â
*/
|
7210 |
+
buildContextualMenu: function ( e, menu ) {
|
7211 |
+
if( this.cell.row.builder.supports( 'addWidget' ) ) {
|
7212 |
+
menu.addSection(
|
7213 |
+
'add-widget-below',
|
7214 |
+
{
|
7215 |
+
sectionTitle: panelsOptions.loc.contextual.add_widget_below,
|
7216 |
+
searchPlaceholder: panelsOptions.loc.contextual.search_widgets,
|
7217 |
+
defaultDisplay: panelsOptions.contextual.default_widgets
|
7218 |
+
},
|
7219 |
+
panelsOptions.widgets,
|
7220 |
+
function ( c ) {
|
7221 |
+
this.cell.row.builder.trigger('before_user_adds_widget');
|
7222 |
+
this.cell.row.builder.addHistoryEntry( 'widget_added' );
|
7223 |
+
|
7224 |
+
var widget = new panels.model.widget( {
|
7225 |
+
class: c
|
7226 |
+
} );
|
7227 |
+
widget.cell = this.cell.model;
|
7228 |
Â
|
7229 |
+
// Insert the new widget below
|
7230 |
+
this.cell.model.get('widgets').add( widget, {
|
7231 |
+
// Add this after the existing model
|
7232 |
+
at: this.model.collection.indexOf( this.model ) + 1
|
7233 |
+
} );
|
7234 |
Â
|
7235 |
+
this.cell.row.builder.model.refreshPanelsData();
|
Â
|
|
7236 |
Â
|
7237 |
+
this.cell.row.builder.trigger('after_user_adds_widget', widget);
|
7238 |
+
}.bind( this )
|
7239 |
+
);
|
7240 |
+
}
|
7241 |
Â
|
7242 |
+
var actions = {};
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
7243 |
Â
|
7244 |
+
if( this.cell.row.builder.supports( 'editWidget' ) && ! this.model.get( 'read_only' ) ) {
|
7245 |
+
actions.edit = { title: panelsOptions.loc.contextual.widget_edit };
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
7246 |
Â
}
|
7247 |
Â
|
7248 |
+
// Copy and paste functions
|
7249 |
+
if ( panels.helpers.clipboard.canCopyPaste() ) {
|
7250 |
+
actions.copy = {title: panelsOptions.loc.contextual.widget_copy};
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
7251 |
Â
}
|
7252 |
Â
|
7253 |
+
if( this.cell.row.builder.supports( 'addWidget' ) ) {
|
7254 |
+
actions.duplicate = { title: panelsOptions.loc.contextual.widget_duplicate };
|
7255 |
+
}
|
Â
|
|
7256 |
Â
|
7257 |
+
if( this.cell.row.builder.supports( 'deleteWidget' ) ) {
|
7258 |
+
actions.delete = { title: panelsOptions.loc.contextual.widget_delete, confirm: true };
|
7259 |
+
}
|
7260 |
Â
|
7261 |
+
if( ! _.isEmpty( actions ) ) {
|
7262 |
+
menu.addSection(
|
7263 |
+
'widget-actions',
|
7264 |
+
{
|
7265 |
+
sectionTitle: panelsOptions.loc.contextual.widget_actions,
|
7266 |
+
search: false,
|
7267 |
+
},
|
7268 |
+
actions,
|
7269 |
+
function ( c ) {
|
7270 |
+
switch ( c ) {
|
7271 |
+
case 'edit':
|
7272 |
+
this.editHandler();
|
7273 |
+
break;
|
7274 |
+
case 'copy':
|
7275 |
+
this.copyHandler();
|
7276 |
+
break;
|
7277 |
+
case 'duplicate':
|
7278 |
+
this.duplicateHandler();
|
7279 |
+
break;
|
7280 |
+
case 'delete':
|
7281 |
+
this.visualDestroyModel();
|
7282 |
+
break;
|
7283 |
+
}
|
7284 |
+
}.bind( this )
|
7285 |
+
);
|
7286 |
Â
}
|
7287 |
+
|
7288 |
+
// Lets also add the contextual menu for the entire row
|
7289 |
+
this.cell.buildContextualMenu( e, menu );
|
7290 |
Â
},
|
7291 |
Â
|
7292 |
Â
/**
|
7293 |
+
* Handler for any action after the user adds a new widget.
|
7294 |
+
* @param widget
|
Â
|
|
7295 |
Â
*/
|
7296 |
+
afterUserAddsWidgetHandler: function( widget ) {
|
7297 |
+
if( this.model === widget && panelsOptions.instant_open ) {
|
7298 |
+
setTimeout(this.editHandler.bind(this), 350);
|
7299 |
+
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
7300 |
Â
}
|
7301 |
Â
|
7302 |
Â
} );
|
7303 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
7304 |
Â
},{}],30:[function(require,module,exports){
|
7305 |
Â
var $ = jQuery;
|
7306 |
Â
|
7407 |
Â
module.exports = mediaWidget;
|
7408 |
Â
|
7409 |
Â
},{}],33:[function(require,module,exports){
|
7410 |
+
var $ = jQuery;
|
7411 |
+
|
7412 |
+
var textWidget = {
|
7413 |
+
addWidget: function( idBase, widgetContainer, widgetId ) {
|
7414 |
+
var component = wp.textWidgets;
|
7415 |
+
|
7416 |
+
var options = {};
|
7417 |
+
var visualField = widgetContainer.find( '.visual' );
|
7418 |
+
// 'visual' field and syncContainer were introduced together in 4.8.1
|
7419 |
+
if ( visualField.length > 0 ) {
|
7420 |
+
// If 'visual' field has no value it's a legacy text widget.
|
7421 |
+
if ( ! visualField.val() ) {
|
7422 |
+
return null;
|
7423 |
+
}
|
7424 |
+
|
7425 |
+
var fieldContainer = $( '<div></div>' );
|
7426 |
+
var syncContainer = widgetContainer.find( '.widget-content:first' );
|
7427 |
+
syncContainer.before( fieldContainer );
|
7428 |
+
|
7429 |
+
options = {
|
7430 |
+
el: fieldContainer,
|
7431 |
+
syncContainer: syncContainer,
|
7432 |
+
};
|
7433 |
+
} else {
|
7434 |
+
options = { el: widgetContainer };
|
7435 |
+
}
|
7436 |
+
|
7437 |
+
var widgetControl = new component.TextWidgetControl( options );
|
7438 |
+
var wpEditor = wp.oldEditor ? wp.oldEditor : wp.editor;
|
7439 |
+
if ( wpEditor && wpEditor.hasOwnProperty( 'autop' ) ) {
|
7440 |
+
wp.editor.autop = wpEditor.autop;
|
7441 |
+
wp.editor.removep = wpEditor.removep;
|
7442 |
+
wp.editor.initialize = wpEditor.initialize
|
7443 |
+
}
|
7444 |
+
|
7445 |
+
widgetControl.initializeEditor();
|
7446 |
+
|
7447 |
+
return widgetControl;
|
7448 |
+
}
|
7449 |
+
};
|
7450 |
+
|
7451 |
+
module.exports = textWidget;
|
7452 |
Â
|
7453 |
Â
},{}]},{},[16]);
|
js/siteorigin-panels-2107.min.js
ADDED
@@ -0,0 +1 @@
|
|
Â
|
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(c)return c(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 c="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,c=jQuery;t.exports=a.view.dialog.extend({cellPreviewTemplate:_.template(a.helpers.utils.processTemplate(c("#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.openSelectedCellStyles()},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(c("#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(){c(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=c(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=c('<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(),c(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;c(this).data("newCellClone").css("width",d.width()*l).find(".preview-cell-weight").html(Math.round(1e3*l)/10),c(this).data("prevCellClone").css("width",d.width()*o).find(".preview-cell-weight").html(Math.round(1e3*o)/10)},stop:function(e,t){c(this).data("newCellClone").remove(),c(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(c(e.target).is(".preview-cell")||c(e.target).is(".preview-cell-in")){var t=c(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();c('<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&&c(this).removeClass("no-user-interacted"),13===e.keyCode&&(e.preventDefault(),c(this).blur())}).keydown(function(e){if(9===e.keyCode){e.preventDefault();var t=d.find(".preview-cell-weight-input"),i=t.index(c(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(c(t).val()))&&c(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(c(t).val());i=isNaN(i)?1/r.row.cells.length:Math.round(10*i)/1e3;var s=!c(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");c(t).animate({width:Math.round(1e3*i)/10+"%"},250),c(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(){c(this).select()})}),c(this).siblings(".preview-cell-weight-input").select()})},this),this.trigger("form_loaded",this)},getSelectedCellIndex:function(){var i=-1;return this.$(".preview-cell .preview-cell-in").each(function(e,t){c(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(),e.off("styles_loaded")}),this.cellStylesCache=[]},scaleRowWidths:function(){var s=this;this.$(".row-preview .preview-cell").each(function(e,t){var i=s.row.cells.at(e);c(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");c(t).animate({width:Math.round(1e3*i)/10+"%"},250),c(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 i=this.$(".so-sidebar-tabs");_.each(panelsOptions.widget_dialog_tabs,function(e,t){o(this.dialogTabTemplate({title:e.title,tab:t})).data({message:e.message,filter:e.filter}).appendTo(i)},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,c=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=c.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(),c(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});i(document).trigger("before_panels_setup",d),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()}),i(window).on("keyup",function(e){27===e.which&&i(".so-panels-dialog-wrapper, .so-panels-live-editor").filter(":visible").last().find(".so-title-bar .so-close, .live-editor-close").click()})})},{"./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,h){var t,u=this,i=jQuery('<div id="wrapper">'+e+"</div>");if(i.find(".panel-layout .panel-grid").length){function p(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()}}function s(e,t){return jQuery(t).closest(".panel-layout").is(l)}var g={grids:[],grid_cells:[],widgets:[]},f=new RegExp(panelsOptions.siteoriginWidgetRegex,"i"),w=(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}),l=i.find(".panel-layout").eq(0);return i.find("> .panel-layout > .panel-grid").filter(s).each(function(c,e){var t=jQuery(e),i=t.find(".panel-grid-cell").filter(s);g.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(s);g.grid_cells.push({grid:c,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:c,cell:d,style:i.data("style"),raw:!1,label:i.data("label")};s=s.trim();var o=f.exec(s);if(_.isNull(o)||""!==s.replace(f,"").trim())return-1!==s.indexOf("panel-layout")&&jQuery("<div>"+s+"</div>").find(".panel-layout .panel-grid").length?(l.class="SiteOrigin_Panels_Widgets_Layout",g.widgets.push({panels_data:u.getPanelsDataFromHtml(s,h),panels_info:l})):(l.class=h,g.widgets.push(_.extend(p(i),{filter:"1",type:"visual",panels_info:l}))),!0;try{var n=/class="(.*?)"/.exec(o[3]),a=jQuery(o[5]),r=JSON.parse(w(a.val())).instance;l.class=n[1].replace(/\\\\+/g,"\\"),l.raw=!1,r.panels_info=l,g.widgets.push(r)}catch(e){l.class=h,g.widgets.push(_.extend(p(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&&(g.grids.push({cells:1,style:{}}),g.grid_cells.push({grid:g.grids.length-1,weight:1}),g.widgets.push({filter:"1",text:i.html().replace(/^\s+|\s+$/gm,""),title:"",type:"visual",panels_info:{class:h,raw:!1,grid:g.grids.length-1,cell:0}})),g}return{grid_cells:[{grid:0,weight:1}],grids:[{cells:1}],widgets:[{filter:"1",text:e,title:"",type:"visual",panels_info:{class:h,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)"_"!==s.charAt(0)&&"so_sidebar_emulator_id"!==s&&"option_name"!==s&&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});function i(){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},displayL
|