Version Description
- Bug fixes
Download this release
Release Info
Developer | Unyson |
Plugin | Unyson |
Version | 2.7.2 |
Comparing to | |
See all releases |
Code changes from version 2.6.16 to 2.7.2
- framework/core/components/backend.php +46 -3
- framework/core/extends/class-fw-container-type.php +1 -1
- framework/core/extends/class-fw-option-type.php +37 -2
- framework/helpers/general.php +7 -33
- framework/includes/customizer/class--fw-customizer-setting-option.php +4 -0
- framework/includes/option-types/addable-box/class-fw-option-type-addable-box.php +4 -0
- framework/includes/option-types/addable-box/static/js/scripts.js +77 -6
- framework/includes/option-types/addable-box/view.php +3 -3
- framework/includes/option-types/addable-option/class-fw-option-type-addable-option.php +4 -0
- framework/includes/option-types/addable-option/static/js/scripts.js +67 -2
- framework/includes/option-types/addable-option/view.php +3 -3
- framework/includes/option-types/addable-popup/class-fw-option-type-addable-popup.php +5 -1
- framework/includes/option-types/addable-popup/static/css/styles.css +14 -1
- framework/includes/option-types/addable-popup/static/js/scripts.js +90 -6
- framework/includes/option-types/addable-popup/view.php +4 -2
- framework/includes/option-types/background-image/class-fw-option-type-background-image.php +4 -0
- framework/includes/option-types/background-image/static/js/scripts.js +87 -17
- framework/includes/option-types/datetime-picker/class-fw-option-type-datetime-picker.php +10 -4
- framework/includes/option-types/datetime-picker/static/js/script.js +21 -1
- framework/includes/option-types/datetime-range/class-fw-option-type-datetime-range.php +5 -1
- framework/includes/option-types/datetime-range/static/css/styles.css +3 -6
- framework/includes/option-types/datetime-range/static/js/script.js +42 -2
- framework/includes/option-types/icon-v2/class-fw-option-type-icon-v2.php +5 -1
- framework/includes/option-types/icon-v2/static/js/icon-picker-v2.js +2 -2
- framework/includes/option-types/icon-v2/static/js/render-icon-previews.js +28 -11
- framework/includes/option-types/image-picker/class-fw-option-type-image-picker.php +5 -1
- framework/includes/option-types/image-picker/static/js/scripts.js +14 -0
- framework/includes/option-types/map/class-fw-option-type-map.php +12 -6
- framework/includes/option-types/map/static/js/scripts.js +311 -204
- framework/includes/option-types/multi-picker/class-fw-option-type-multi-picker.php +80 -39
- framework/includes/option-types/multi-picker/static/js/multi-picker.js +166 -70
- framework/includes/option-types/multi-select/class-fw-option-type-multi-select.php +194 -69
- framework/includes/option-types/multi-select/static/css/style.css +19 -0
- framework/includes/option-types/multi-select/static/js/scripts.js +23 -10
- framework/includes/option-types/multi-upload/class-fw-option-type-multi-upload.php +5 -1
- framework/includes/option-types/multi-upload/static/js/any-files.js +23 -1
- framework/includes/option-types/multi-upload/static/js/images-only.js +45 -1
- framework/includes/option-types/multi/class-fw-option-type-multi.php +9 -1
- framework/includes/option-types/popup/class-fw-option-type-popup.php +5 -1
- framework/includes/option-types/popup/static/js/popup.js +17 -0
- framework/includes/option-types/range-slider/class-fw-option-type-range-slider.php +5 -1
- framework/includes/option-types/range-slider/static/js/scripts.js +29 -1
- framework/includes/option-types/rgba-color-picker/static/js/scripts.js +263 -282
- framework/includes/option-types/simple.php +47 -3
- framework/includes/option-types/slider/class-fw-option-type-slider.php +5 -1
- framework/includes/option-types/slider/static/js/scripts.js +1 -1
- framework/includes/option-types/switch/class-fw-option-type-switch.php +6 -1
- framework/includes/option-types/switch/static/js/scripts.js +17 -1
- framework/includes/option-types/typography-v2/class-fw-option-type-typography-v2.php +4 -1
- framework/includes/option-types/upload/class-fw-option-type-upload.php +5 -1
- framework/includes/option-types/upload/static/js/any-files.js +17 -0
- framework/includes/option-types/upload/static/js/images-only.js +54 -0
- framework/includes/option-types/wp-editor/class-fw-option-type-wp-editor.php +5 -1
- framework/includes/option-types/wp-editor/static/scripts.js +19 -0
- framework/manifest.php +1 -1
- framework/static/js/fw-events.js +201 -88
- framework/views/backend-option-design-customizer.php +4 -2
- framework/views/backend-option-design-default.php +5 -2
- readme.txt +13 -3
- unyson.php +1 -1
framework/core/components/backend.php
CHANGED
@@ -294,7 +294,7 @@ final class _FW_Component_Backend {
|
|
294 |
wp_register_script(
|
295 |
'fw-events',
|
296 |
fw_get_framework_directory_uri( '/static/js/fw-events.js' ),
|
297 |
-
array(
|
298 |
fw()->manifest->get_version(),
|
299 |
true
|
300 |
);
|
@@ -335,6 +335,45 @@ final class _FW_Component_Backend {
|
|
335 |
fw()->manifest->get_version()
|
336 |
);
|
337 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
338 |
wp_register_script(
|
339 |
'fw',
|
340 |
fw_get_framework_directory_uri( '/static/js/fw.js' ),
|
@@ -381,7 +420,7 @@ final class _FW_Component_Backend {
|
|
381 |
wp_register_script(
|
382 |
'fw-backend-options',
|
383 |
fw_get_framework_directory_uri( '/static/js/backend-options.js' ),
|
384 |
-
array( 'fw', 'fw-events', 'postbox', 'jquery-ui-tabs' ),
|
385 |
fw()->manifest->get_version(),
|
386 |
true
|
387 |
);
|
@@ -1147,7 +1186,11 @@ final class _FW_Component_Backend {
|
|
1147 |
) );
|
1148 |
}
|
1149 |
|
1150 |
-
$options =
|
|
|
|
|
|
|
|
|
1151 |
|
1152 |
if ( ! $options ) {
|
1153 |
wp_send_json_error( array(
|
294 |
wp_register_script(
|
295 |
'fw-events',
|
296 |
fw_get_framework_directory_uri( '/static/js/fw-events.js' ),
|
297 |
+
array(),
|
298 |
fw()->manifest->get_version(),
|
299 |
true
|
300 |
);
|
335 |
fw()->manifest->get_version()
|
336 |
);
|
337 |
|
338 |
+
wp_register_script(
|
339 |
+
'fw-reactive-options-registry',
|
340 |
+
fw_get_framework_directory_uri(
|
341 |
+
'/static/js/fw-reactive-options-registry.js'
|
342 |
+
),
|
343 |
+
array('fw', 'fw-events'),
|
344 |
+
false
|
345 |
+
);
|
346 |
+
|
347 |
+
wp_register_script(
|
348 |
+
'fw-reactive-options-simple-options',
|
349 |
+
fw_get_framework_directory_uri(
|
350 |
+
'/static/js/fw-reactive-options-simple-options.js'
|
351 |
+
),
|
352 |
+
array('fw', 'fw-events', 'fw-reactive-options-undefined-option'),
|
353 |
+
false
|
354 |
+
);
|
355 |
+
|
356 |
+
wp_register_script(
|
357 |
+
'fw-reactive-options-undefined-option',
|
358 |
+
fw_get_framework_directory_uri(
|
359 |
+
'/static/js/fw-reactive-options-undefined-option.js'
|
360 |
+
),
|
361 |
+
array(
|
362 |
+
'fw', 'fw-events', 'fw-reactive-options-registry'
|
363 |
+
),
|
364 |
+
false
|
365 |
+
);
|
366 |
+
|
367 |
+
wp_register_script(
|
368 |
+
'fw-reactive-options',
|
369 |
+
fw_get_framework_directory_uri('/static/js/fw-reactive-options.js'),
|
370 |
+
array(
|
371 |
+
'fw', 'fw-events', 'fw-reactive-options-undefined-option',
|
372 |
+
'fw-reactive-options-simple-options'
|
373 |
+
),
|
374 |
+
false
|
375 |
+
);
|
376 |
+
|
377 |
wp_register_script(
|
378 |
'fw',
|
379 |
fw_get_framework_directory_uri( '/static/js/fw.js' ),
|
420 |
wp_register_script(
|
421 |
'fw-backend-options',
|
422 |
fw_get_framework_directory_uri( '/static/js/backend-options.js' ),
|
423 |
+
array( 'fw', 'fw-events', 'fw-reactive-options', 'postbox', 'jquery-ui-tabs' ),
|
424 |
fw()->manifest->get_version(),
|
425 |
true
|
426 |
);
|
1186 |
) );
|
1187 |
}
|
1188 |
|
1189 |
+
$options = FW_Request::POST( 'options' );
|
1190 |
+
|
1191 |
+
if (is_string( $options )) {
|
1192 |
+
$options = json_decode( FW_Request::POST( 'options' ), true );
|
1193 |
+
}
|
1194 |
|
1195 |
if ( ! $options ) {
|
1196 |
wp_send_json_error( array(
|
framework/core/extends/class-fw-container-type.php
CHANGED
@@ -230,4 +230,4 @@ abstract class FW_Container_Type
|
|
230 |
|
231 |
fw()->backend->_register_container_type($registration_access_key, $container_type_class);
|
232 |
}
|
233 |
-
}
|
230 |
|
231 |
fw()->backend->_register_container_type($registration_access_key, $container_type_class);
|
232 |
}
|
233 |
+
}
|
framework/core/extends/class-fw-option-type.php
CHANGED
@@ -68,6 +68,15 @@ abstract class FW_Option_Type
|
|
68 |
*/
|
69 |
abstract protected function _get_defaults();
|
70 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
/**
|
72 |
* Prevent execute enqueue multiple times
|
73 |
* @var bool
|
@@ -188,7 +197,23 @@ abstract class FW_Option_Type
|
|
188 |
|
189 |
$this->enqueue_static($id, $option, $data);
|
190 |
|
191 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
192 |
}
|
193 |
|
194 |
/**
|
@@ -232,7 +257,7 @@ abstract class FW_Option_Type
|
|
232 |
wp_enqueue_script(
|
233 |
'fw-option-types',
|
234 |
fw_get_framework_directory_uri('/static/js/option-types.js'),
|
235 |
-
array('fw-events', 'qtip'),
|
236 |
fw()->manifest->get_version(),
|
237 |
true
|
238 |
);
|
@@ -313,6 +338,16 @@ abstract class FW_Option_Type
|
|
313 |
return 'fixed';
|
314 |
}
|
315 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
316 |
/**
|
317 |
* Use this method to register a new option type
|
318 |
*
|
68 |
*/
|
69 |
abstract protected function _get_defaults();
|
70 |
|
71 |
+
/**
|
72 |
+
* Put data for to be accessed in JavaScript for each option type instance
|
73 |
+
*/
|
74 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
75 |
+
return array(
|
76 |
+
'option' => $option
|
77 |
+
);
|
78 |
+
}
|
79 |
+
|
80 |
/**
|
81 |
* Prevent execute enqueue multiple times
|
82 |
* @var bool
|
197 |
|
198 |
$this->enqueue_static($id, $option, $data);
|
199 |
|
200 |
+
$html_attributes = array(
|
201 |
+
'class' => 'fw-backend-option-descriptor',
|
202 |
+
'data-fw-option-id' => $id,
|
203 |
+
'data-fw-option-type' => $option['type']
|
204 |
+
);
|
205 |
+
|
206 |
+
$data_for_js = $this->_get_data_for_js($id, $option, $data);
|
207 |
+
|
208 |
+
if ($data_for_js) {
|
209 |
+
$html_attributes['data-fw-for-js'] = json_encode($data_for_js);
|
210 |
+
}
|
211 |
+
|
212 |
+
return fw_html_tag(
|
213 |
+
'div',
|
214 |
+
$html_attributes,
|
215 |
+
$this->_render( $id, $this->load_callbacks( $option ), $data )
|
216 |
+
);
|
217 |
}
|
218 |
|
219 |
/**
|
257 |
wp_enqueue_script(
|
258 |
'fw-option-types',
|
259 |
fw_get_framework_directory_uri('/static/js/option-types.js'),
|
260 |
+
array('fw-events', 'qtip', 'fw-reactive-options'),
|
261 |
fw()->manifest->get_version(),
|
262 |
true
|
263 |
);
|
338 |
return 'fixed';
|
339 |
}
|
340 |
|
341 |
+
/**
|
342 |
+
* a general purpose 'label' => false | true from options.php
|
343 |
+
* @return bool | string
|
344 |
+
*
|
345 |
+
* @since 2.7.1
|
346 |
+
*/
|
347 |
+
public function _default_label($id, $option) {
|
348 |
+
return fw_id_to_title($id);
|
349 |
+
}
|
350 |
+
|
351 |
/**
|
352 |
* Use this method to register a new option type
|
353 |
*
|
framework/helpers/general.php
CHANGED
@@ -1313,42 +1313,16 @@ function fw_get_google_fonts_v2() {
|
|
1313 |
*/
|
1314 |
function fw_current_url() {
|
1315 |
static $url = null;
|
1316 |
-
|
1317 |
if ( $url === null ) {
|
1318 |
-
|
1319 |
-
|
1320 |
-
|
1321 |
-
|
1322 |
-
|
1323 |
-
if (
|
1324 |
-
$_SERVER['SERVER_NAME'] === '_'
|
1325 |
-
||
|
1326 |
-
1 === $server_wildcard_or_regex
|
1327 |
-
) { // https://github.com/ThemeFuse/Unyson/issues/126
|
1328 |
-
$url .= $_SERVER['HTTP_HOST'];
|
1329 |
} else {
|
1330 |
-
$url
|
1331 |
}
|
1332 |
-
|
1333 |
-
if ( ! in_array( intval( $_SERVER['SERVER_PORT'] ), array( 80, 443 ) ) ) {
|
1334 |
-
$url .= ':' . $_SERVER['SERVER_PORT'];
|
1335 |
-
}
|
1336 |
-
|
1337 |
-
$url .= $_SERVER['REQUEST_URI'];
|
1338 |
-
|
1339 |
$url = set_url_scheme( $url ); // https fix
|
1340 |
-
|
1341 |
-
if ( is_multisite() ) {
|
1342 |
-
if ( defined( 'SUBDOMAIN_INSTALL' ) && SUBDOMAIN_INSTALL ) {
|
1343 |
-
$site_url = parse_url( $url );
|
1344 |
-
|
1345 |
-
if ( isset( $site_url['query'] ) ) {
|
1346 |
-
$url = home_url( $site_url['path'] . '?' . $site_url['query'] );
|
1347 |
-
} else {
|
1348 |
-
$url = home_url( $site_url['path'] );
|
1349 |
-
}
|
1350 |
-
}
|
1351 |
-
}
|
1352 |
}
|
1353 |
|
1354 |
return $url;
|
@@ -1989,4 +1963,4 @@ function fw_is_callback( $value ) {
|
|
1989 |
*/
|
1990 |
function fw_is_cli() {
|
1991 |
return ( php_sapi_name() === 'cli' ) && defined( 'WP_CLI' );
|
1992 |
-
}
|
1313 |
*/
|
1314 |
function fw_current_url() {
|
1315 |
static $url = null;
|
|
|
1316 |
if ( $url === null ) {
|
1317 |
+
if ( is_multisite() && ! ( defined( 'SUBDOMAIN_INSTALL' ) && SUBDOMAIN_INSTALL ) ) {
|
1318 |
+
switch_to_blog( 1 );
|
1319 |
+
$url = get_option( 'home' );
|
1320 |
+
restore_current_blog();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1321 |
} else {
|
1322 |
+
$url = get_option( 'home' );
|
1323 |
}
|
1324 |
+
$url .= fw_akg( 'REQUEST_URI', $_SERVER, '/' );
|
|
|
|
|
|
|
|
|
|
|
|
|
1325 |
$url = set_url_scheme( $url ); // https fix
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1326 |
}
|
1327 |
|
1328 |
return $url;
|
1963 |
*/
|
1964 |
function fw_is_cli() {
|
1965 |
return ( php_sapi_name() === 'cli' ) && defined( 'WP_CLI' );
|
1966 |
+
}
|
framework/includes/customizer/class--fw-customizer-setting-option.php
CHANGED
@@ -18,6 +18,10 @@ class _FW_Customizer_Setting_Option extends WP_Customize_Setting {
|
|
18 |
}
|
19 |
|
20 |
public function sanitize($value) {
|
|
|
|
|
|
|
|
|
21 |
$value = json_decode($value, true);
|
22 |
|
23 |
if (is_null($value) || !is_array($value)) {
|
18 |
}
|
19 |
|
20 |
public function sanitize($value) {
|
21 |
+
if ( is_array( $value ) ) {
|
22 |
+
return null;
|
23 |
+
}
|
24 |
+
|
25 |
$value = json_decode($value, true);
|
26 |
|
27 |
if (is_null($value) || !is_array($value)) {
|
framework/includes/option-types/addable-box/class-fw-option-type-addable-box.php
CHANGED
@@ -10,6 +10,10 @@ class FW_Option_Type_Addable_Box extends FW_Option_Type
|
|
10 |
return 'addable-box';
|
11 |
}
|
12 |
|
|
|
|
|
|
|
|
|
13 |
/**
|
14 |
* @internal
|
15 |
* {@inheritdoc}
|
10 |
return 'addable-box';
|
11 |
}
|
12 |
|
13 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
14 |
+
return false;
|
15 |
+
}
|
16 |
+
|
17 |
/**
|
18 |
* @internal
|
19 |
* {@inheritdoc}
|
framework/includes/option-types/addable-box/static/js/scripts.js
CHANGED
@@ -55,10 +55,15 @@ jQuery(document).ready(function ($) {
|
|
55 |
}
|
56 |
},
|
57 |
update: function(){
|
58 |
-
$(this).closest(optionTypeClass)
|
|
|
|
|
|
|
|
|
59 |
}
|
60 |
});
|
61 |
},
|
|
|
62 |
/** Init boxes controls */
|
63 |
initControls: function ($boxes) {
|
64 |
$boxes
|
@@ -78,6 +83,9 @@ jQuery(document).ready(function ($) {
|
|
78 |
|
79 |
methods.checkLimit($option);
|
80 |
methods.updateHasBoxesClass($option);
|
|
|
|
|
|
|
81 |
break;
|
82 |
default:
|
83 |
// custom control. trigger event for others to handle this
|
@@ -227,6 +235,23 @@ jQuery(document).ready(function ($) {
|
|
227 |
fwEvents.on('fw:options:init', function (data) {
|
228 |
var $elements = data.$elements.find(optionTypeClass +':not(.fw-option-initialized)');
|
229 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
230 |
/** Init Add button */
|
231 |
$elements.on('click', '> .fw-option-boxes-controls > .fw-option-boxes-add-button', function(){
|
232 |
var $button = $(this);
|
@@ -250,7 +275,6 @@ jQuery(document).ready(function ($) {
|
|
250 |
}, 300);
|
251 |
}
|
252 |
|
253 |
-
|
254 |
$boxes.append($newBox);
|
255 |
|
256 |
// Re-render wp-editor
|
@@ -259,10 +283,14 @@ jQuery(document).ready(function ($) {
|
|
259 |
&&
|
260 |
$newBox.find('.fw-option-type-wp-editor:first').length
|
261 |
) {
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
|
|
|
|
|
|
|
|
266 |
}
|
267 |
|
268 |
methods.initControls($newBox);
|
@@ -282,6 +310,8 @@ jQuery(document).ready(function ($) {
|
|
282 |
|
283 |
methods.checkLimit($option);
|
284 |
methods.updateHasBoxesClass($option);
|
|
|
|
|
285 |
});
|
286 |
|
287 |
// close postboxes and attach event listener
|
@@ -326,4 +356,45 @@ jQuery(document).ready(function ($) {
|
|
326 |
|
327 |
titleUpdater.update();
|
328 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
329 |
});
|
55 |
}
|
56 |
},
|
57 |
update: function(){
|
58 |
+
var optionType = $(this).closest(optionTypeClass);
|
59 |
+
|
60 |
+
optionType.trigger('change'); // for customizer
|
61 |
+
|
62 |
+
fw.options.trigger.changeForEl(optionType);
|
63 |
}
|
64 |
});
|
65 |
},
|
66 |
+
|
67 |
/** Init boxes controls */
|
68 |
initControls: function ($boxes) {
|
69 |
$boxes
|
83 |
|
84 |
methods.checkLimit($option);
|
85 |
methods.updateHasBoxesClass($option);
|
86 |
+
|
87 |
+
fw.options.trigger.changeForEl($option);
|
88 |
+
|
89 |
break;
|
90 |
default:
|
91 |
// custom control. trigger event for others to handle this
|
235 |
fwEvents.on('fw:options:init', function (data) {
|
236 |
var $elements = data.$elements.find(optionTypeClass +':not(.fw-option-initialized)');
|
237 |
|
238 |
+
$elements.toArray().map(function (el) {
|
239 |
+
fw.options.on.change(function (data) {
|
240 |
+
if (! $(data.context).is(
|
241 |
+
'[data-fw-option-type="addable-box"] .fw-option-boxes > .fw-option-box'
|
242 |
+
)) {
|
243 |
+
return;
|
244 |
+
}
|
245 |
+
|
246 |
+
// Listen to just its own virtual contexts
|
247 |
+
if (! el.contains(data.context)) {
|
248 |
+
return;
|
249 |
+
}
|
250 |
+
|
251 |
+
fw.options.trigger.changeForEl(el);
|
252 |
+
});
|
253 |
+
});
|
254 |
+
|
255 |
/** Init Add button */
|
256 |
$elements.on('click', '> .fw-option-boxes-controls > .fw-option-boxes-add-button', function(){
|
257 |
var $button = $(this);
|
275 |
}, 300);
|
276 |
}
|
277 |
|
|
|
278 |
$boxes.append($newBox);
|
279 |
|
280 |
// Re-render wp-editor
|
283 |
&&
|
284 |
$newBox.find('.fw-option-type-wp-editor:first').length
|
285 |
) {
|
286 |
+
$newBox.find(
|
287 |
+
'.fw-option-type-wp-editor textarea'
|
288 |
+
).toArray().map(function (textarea) {
|
289 |
+
fwWpEditorRefreshIds(
|
290 |
+
$(textarea).attr('id'),
|
291 |
+
$newBox
|
292 |
+
);
|
293 |
+
});
|
294 |
}
|
295 |
|
296 |
methods.initControls($newBox);
|
310 |
|
311 |
methods.checkLimit($option);
|
312 |
methods.updateHasBoxesClass($option);
|
313 |
+
|
314 |
+
fw.options.trigger.changeForEl($boxes);
|
315 |
});
|
316 |
|
317 |
// close postboxes and attach event listener
|
356 |
|
357 |
titleUpdater.update();
|
358 |
});
|
359 |
+
|
360 |
+
fw.options.register('addable-box', {
|
361 |
+
startListeningForChanges: $.noop,
|
362 |
+
getValue: function (optionDescriptor) {
|
363 |
+
var promise = $.Deferred();
|
364 |
+
|
365 |
+
// TODO: refactor that!!!
|
366 |
+
if (jQuery.when.all===undefined) {
|
367 |
+
jQuery.when.all = function(deferreds) {
|
368 |
+
var deferred = new jQuery.Deferred();
|
369 |
+
$.when.apply(jQuery, deferreds).then(
|
370 |
+
function() {
|
371 |
+
deferred.resolve(Array.prototype.slice.call(arguments));
|
372 |
+
},
|
373 |
+
function() {
|
374 |
+
deferred.fail(Array.prototype.slice.call(arguments));
|
375 |
+
});
|
376 |
+
|
377 |
+
return deferred;
|
378 |
+
}
|
379 |
+
}
|
380 |
+
|
381 |
+
jQuery.when.all(
|
382 |
+
$(optionDescriptor.el).find(
|
383 |
+
'.fw-option-boxes'
|
384 |
+
).first().find(
|
385 |
+
'> .fw-option-box.fw-backend-options-virtual-context'
|
386 |
+
).toArray().map(fw.options.getContextValue)
|
387 |
+
).then(function (valuesAsArray) {
|
388 |
+
promise.resolve({
|
389 |
+
value: valuesAsArray.map(function (singleContextValue) {
|
390 |
+
return singleContextValue.value;
|
391 |
+
}),
|
392 |
+
|
393 |
+
optionDescriptor: optionDescriptor
|
394 |
+
})
|
395 |
+
});
|
396 |
+
|
397 |
+
return promise;
|
398 |
+
}
|
399 |
+
})
|
400 |
});
|
framework/includes/option-types/addable-box/view.php
CHANGED
@@ -42,7 +42,7 @@ if (!empty($data['value'])) {
|
|
42 |
<div class="fw-option-boxes metabox-holder">
|
43 |
<?php foreach ($data['value'] as $value_index => &$values): ?>
|
44 |
<?php $i++; ?>
|
45 |
-
<div class="fw-option-box" data-name-prefix="<?php echo fw_htmlspecialchars($data['name_prefix'] .'['. $id .']['. $i .']') ?>" data-values="<?php echo fw_htmlspecialchars(json_encode($values)) ?>">
|
46 |
<?php ob_start() ?>
|
47 |
<div class="fw-option-box-options fw-force-xs">
|
48 |
<?php
|
@@ -80,7 +80,7 @@ if (!empty($data['value'])) {
|
|
80 |
$increment_placeholder = '###-addable-box-increment-'. fw_rand_md5() .'-###';
|
81 |
|
82 |
echo fw_htmlspecialchars(
|
83 |
-
'<div class="fw-option-box" data-name-prefix="'. fw_htmlspecialchars($data['name_prefix'] .'['. $id .']['. $increment_placeholder .']') .'">'.
|
84 |
fw()->backend->render_box(
|
85 |
$data['id_prefix'] . $id .'-'. $increment_placeholder .'-box',
|
86 |
' ',
|
@@ -109,4 +109,4 @@ if (!empty($data['value'])) {
|
|
109 |
), fw_htmlspecialchars($option['add-button-text']));
|
110 |
?>
|
111 |
</div>
|
112 |
-
</div>
|
42 |
<div class="fw-option-boxes metabox-holder">
|
43 |
<?php foreach ($data['value'] as $value_index => &$values): ?>
|
44 |
<?php $i++; ?>
|
45 |
+
<div class="fw-option-box fw-backend-options-virtual-context" data-name-prefix="<?php echo fw_htmlspecialchars($data['name_prefix'] .'['. $id .']['. $i .']') ?>" data-values="<?php echo fw_htmlspecialchars(json_encode($values)) ?>">
|
46 |
<?php ob_start() ?>
|
47 |
<div class="fw-option-box-options fw-force-xs">
|
48 |
<?php
|
80 |
$increment_placeholder = '###-addable-box-increment-'. fw_rand_md5() .'-###';
|
81 |
|
82 |
echo fw_htmlspecialchars(
|
83 |
+
'<div class="fw-option-box fw-backend-options-virtual-context" data-name-prefix="'. fw_htmlspecialchars($data['name_prefix'] .'['. $id .']['. $increment_placeholder .']') .'">'.
|
84 |
fw()->backend->render_box(
|
85 |
$data['id_prefix'] . $id .'-'. $increment_placeholder .'-box',
|
86 |
' ',
|
109 |
), fw_htmlspecialchars($option['add-button-text']));
|
110 |
?>
|
111 |
</div>
|
112 |
+
</div>
|
framework/includes/option-types/addable-option/class-fw-option-type-addable-option.php
CHANGED
@@ -28,6 +28,10 @@ class FW_Option_Type_Addable_Option extends FW_Option_Type
|
|
28 |
);
|
29 |
}
|
30 |
|
|
|
|
|
|
|
|
|
31 |
/**
|
32 |
* @internal
|
33 |
* {@inheritdoc}
|
28 |
);
|
29 |
}
|
30 |
|
31 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
32 |
+
return false;
|
33 |
+
}
|
34 |
+
|
35 |
/**
|
36 |
* @internal
|
37 |
* {@inheritdoc}
|
framework/includes/option-types/addable-option/static/js/scripts.js
CHANGED
@@ -8,7 +8,7 @@ jQuery(document).ready(function ($) {
|
|
8 |
// happens when sortable was not initialized before
|
9 |
}
|
10 |
|
11 |
-
if (
|
12 |
return false;
|
13 |
}
|
14 |
|
@@ -34,6 +34,7 @@ jQuery(document).ready(function ($) {
|
|
34 |
},
|
35 |
update: function(){
|
36 |
$(this).closest(optionClass).trigger('change'); // for customizer
|
|
|
37 |
}
|
38 |
});
|
39 |
}
|
@@ -48,6 +49,24 @@ jQuery(document).ready(function ($) {
|
|
48 |
fwEvents.on('fw:options:init', function (data) {
|
49 |
var $elements = data.$elements.find(optionClass +':not(.fw-option-initialized)');
|
50 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
/** Init Add button */
|
52 |
$elements.on('click', optionClass +'-add', function(){
|
53 |
var $button = $(this);
|
@@ -91,10 +110,15 @@ jQuery(document).ready(function ($) {
|
|
91 |
fwEvents.trigger('fw:options:init', {$elements: $newOption});
|
92 |
|
93 |
$option.trigger(methods.makeEventName('option:init'), {$option: $newOption});
|
|
|
94 |
});
|
95 |
|
96 |
/** Init Remove button */
|
97 |
$elements.on('click', optionClass +'-remove', function(){
|
|
|
|
|
|
|
|
|
98 |
$(this).closest(optionClass +'-option').remove();
|
99 |
});
|
100 |
|
@@ -104,4 +128,45 @@ jQuery(document).ready(function ($) {
|
|
104 |
|
105 |
$elements.addClass('fw-option-initialized');
|
106 |
});
|
107 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
// happens when sortable was not initialized before
|
9 |
}
|
10 |
|
11 |
+
if (! $options.first().closest(optionClass).hasClass('is-sortable')) {
|
12 |
return false;
|
13 |
}
|
14 |
|
34 |
},
|
35 |
update: function(){
|
36 |
$(this).closest(optionClass).trigger('change'); // for customizer
|
37 |
+
fw.options.trigger.changeForEl($(this).closest(optionClass));
|
38 |
}
|
39 |
});
|
40 |
}
|
49 |
fwEvents.on('fw:options:init', function (data) {
|
50 |
var $elements = data.$elements.find(optionClass +':not(.fw-option-initialized)');
|
51 |
|
52 |
+
$elements.toArray().map(function (el) {
|
53 |
+
// Trigger change when one of the underlying contexts change
|
54 |
+
fw.options.on.change(function (data) {
|
55 |
+
if (! $(data.context).is(
|
56 |
+
'[data-fw-option-type="addable-option"] tr.fw-option-type-addable-option-option'
|
57 |
+
)) {
|
58 |
+
return;
|
59 |
+
}
|
60 |
+
|
61 |
+
// Listen to just its own virtual contexts
|
62 |
+
if (! el.contains(data.context)) {
|
63 |
+
return;
|
64 |
+
}
|
65 |
+
|
66 |
+
fw.options.trigger.changeForEl(el);
|
67 |
+
});
|
68 |
+
});
|
69 |
+
|
70 |
/** Init Add button */
|
71 |
$elements.on('click', optionClass +'-add', function(){
|
72 |
var $button = $(this);
|
110 |
fwEvents.trigger('fw:options:init', {$elements: $newOption});
|
111 |
|
112 |
$option.trigger(methods.makeEventName('option:init'), {$option: $newOption});
|
113 |
+
fw.options.trigger.changeForEl($option);
|
114 |
});
|
115 |
|
116 |
/** Init Remove button */
|
117 |
$elements.on('click', optionClass +'-remove', function(){
|
118 |
+
fw.options.trigger.changeForEl($(this).closest(
|
119 |
+
'[data-fw-option-type="addable-option"]'
|
120 |
+
));
|
121 |
+
|
122 |
$(this).closest(optionClass +'-option').remove();
|
123 |
});
|
124 |
|
128 |
|
129 |
$elements.addClass('fw-option-initialized');
|
130 |
});
|
131 |
+
|
132 |
+
fw.options.register('addable-option', {
|
133 |
+
startListeningForChanges: $.noop,
|
134 |
+
getValue: function (optionDescriptor) {
|
135 |
+
var promise = $.Deferred();
|
136 |
+
|
137 |
+
// TODO: refactor that!!!
|
138 |
+
if (jQuery.when.all===undefined) {
|
139 |
+
jQuery.when.all = function(deferreds) {
|
140 |
+
var deferred = new jQuery.Deferred();
|
141 |
+
$.when.apply(jQuery, deferreds).then(
|
142 |
+
function() {
|
143 |
+
deferred.resolve(Array.prototype.slice.call(arguments));
|
144 |
+
},
|
145 |
+
function() {
|
146 |
+
deferred.fail(Array.prototype.slice.call(arguments));
|
147 |
+
});
|
148 |
+
|
149 |
+
return deferred;
|
150 |
+
}
|
151 |
+
}
|
152 |
+
|
153 |
+
jQuery.when.all(
|
154 |
+
$(optionDescriptor.el).find(
|
155 |
+
'table.fw-option-type-addable-option-options'
|
156 |
+
).first().find(
|
157 |
+
'> tbody > .fw-backend-options-virtual-context'
|
158 |
+
).toArray().map(fw.options.getContextValue)
|
159 |
+
).then(function (valuesAsArray) {
|
160 |
+
promise.resolve({
|
161 |
+
value: valuesAsArray.map(function (singleContextValue) {
|
162 |
+
return _.values(singleContextValue.value)[0];
|
163 |
+
}),
|
164 |
+
|
165 |
+
optionDescriptor: optionDescriptor
|
166 |
+
})
|
167 |
+
});
|
168 |
+
|
169 |
+
return promise;
|
170 |
+
}
|
171 |
+
})
|
172 |
+
});
|
framework/includes/option-types/addable-option/view.php
CHANGED
@@ -20,7 +20,7 @@ if ($option['sortable']) {
|
|
20 |
<table class="fw-option-type-addable-option-options" width="100%" cellpadding="0" cellspacing="0" border="0">
|
21 |
<?php $i = 1; ?>
|
22 |
<?php foreach($data['value'] as $option_value): ?>
|
23 |
-
<tr class="fw-option-type-addable-option-option">
|
24 |
<td class="td-move">
|
25 |
<img src="<?php echo esc_attr($move_img_src); ?>" width="7" />
|
26 |
</td>
|
@@ -64,7 +64,7 @@ if ($option['sortable']) {
|
|
64 |
$increment_placeholder = '###-addable-option-increment-'. fw_rand_md5() .'-###';
|
65 |
|
66 |
echo fw_htmlspecialchars(
|
67 |
-
'<tr class="fw-option-type-addable-option-option">
|
68 |
<td class="td-move">
|
69 |
<img src="'. $move_img_src .'" width="7" />
|
70 |
</td>
|
@@ -94,4 +94,4 @@ if ($option['sortable']) {
|
|
94 |
), fw_htmlspecialchars($option['add-button-text']));
|
95 |
?>
|
96 |
</div>
|
97 |
-
</div>
|
20 |
<table class="fw-option-type-addable-option-options" width="100%" cellpadding="0" cellspacing="0" border="0">
|
21 |
<?php $i = 1; ?>
|
22 |
<?php foreach($data['value'] as $option_value): ?>
|
23 |
+
<tr class="fw-option-type-addable-option-option fw-backend-options-virtual-context">
|
24 |
<td class="td-move">
|
25 |
<img src="<?php echo esc_attr($move_img_src); ?>" width="7" />
|
26 |
</td>
|
64 |
$increment_placeholder = '###-addable-option-increment-'. fw_rand_md5() .'-###';
|
65 |
|
66 |
echo fw_htmlspecialchars(
|
67 |
+
'<tr class="fw-option-type-addable-option-option fw-backend-options-virtual-context">
|
68 |
<td class="td-move">
|
69 |
<img src="'. $move_img_src .'" width="7" />
|
70 |
</td>
|
94 |
), fw_htmlspecialchars($option['add-button-text']));
|
95 |
?>
|
96 |
</div>
|
97 |
+
</div>
|
framework/includes/option-types/addable-popup/class-fw-option-type-addable-popup.php
CHANGED
@@ -12,6 +12,10 @@ class FW_Option_Type_Addable_Popup extends FW_Option_Type
|
|
12 |
return 'fixed';
|
13 |
}
|
14 |
|
|
|
|
|
|
|
|
|
15 |
/**
|
16 |
* @internal
|
17 |
* {@inheritdoc}
|
@@ -212,4 +216,4 @@ class FW_Option_Type_Addable_Popup_Full extends FW_Option_Type_Addable_Popup
|
|
212 |
|
213 |
return parent::_render($id, $option, $data);
|
214 |
}
|
215 |
-
}
|
12 |
return 'fixed';
|
13 |
}
|
14 |
|
15 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
16 |
+
return false;
|
17 |
+
}
|
18 |
+
|
19 |
/**
|
20 |
* @internal
|
21 |
* {@inheritdoc}
|
216 |
|
217 |
return parent::_render($id, $option, $data);
|
218 |
}
|
219 |
+
}
|
framework/includes/option-types/addable-popup/static/css/styles.css
CHANGED
@@ -26,6 +26,18 @@
|
|
26 |
margin-top: -10px;
|
27 |
}
|
28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
.fw-option-type-addable-popup .sort-item {
|
30 |
position: absolute;
|
31 |
left: 11px;
|
@@ -35,7 +47,8 @@
|
|
35 |
}
|
36 |
|
37 |
.fw-option-type-addable-popup .default-item,
|
38 |
-
.fw-option-type-addable-popup:not(.is-sortable) .sort-item
|
|
|
39 |
display: none;
|
40 |
}
|
41 |
|
26 |
margin-top: -10px;
|
27 |
}
|
28 |
|
29 |
+
.fw-option-type-addable-popup .clone-item {
|
30 |
+
position: absolute;
|
31 |
+
right: 25px;
|
32 |
+
top:50%;
|
33 |
+
margin-top: -8px;
|
34 |
+
font-size:16px;
|
35 |
+
opacity:0.4;
|
36 |
+
}
|
37 |
+
.fw-option-type-addable-popup .clone-item:hover{
|
38 |
+
opacity:0.7;
|
39 |
+
}
|
40 |
+
|
41 |
.fw-option-type-addable-popup .sort-item {
|
42 |
position: absolute;
|
43 |
left: 11px;
|
47 |
}
|
48 |
|
49 |
.fw-option-type-addable-popup .default-item,
|
50 |
+
.fw-option-type-addable-popup:not(.is-sortable) .sort-item,
|
51 |
+
.fw-option-type-addable-popup .items-wrapper.hide-clone .clone-item {
|
52 |
display: none;
|
53 |
}
|
54 |
|
framework/includes/option-types/addable-popup/static/js/scripts.js
CHANGED
@@ -10,25 +10,32 @@
|
|
10 |
return $defaultItem.clone().removeClass('default-item').addClass('item');
|
11 |
}
|
12 |
},
|
|
|
13 |
data = JSON.parse(
|
14 |
JSON.parse(nodes.$optionWrapper.attr('data-for-js')).join('{{') // check option php class
|
15 |
),
|
|
|
16 |
utils = {
|
17 |
modal: new fw.OptionsModal({
|
18 |
title: data.title,
|
19 |
options: data.options,
|
20 |
size : data.size
|
21 |
}),
|
|
|
22 |
countItems: function () {
|
23 |
return nodes.$itemsWrapper.find('> .item').length;
|
24 |
},
|
|
|
25 |
removeDefaultItem: function () {
|
26 |
nodes.$optionWrapper.find('.default-item:first').remove();
|
27 |
},
|
|
|
28 |
toogleNodes : function(){
|
29 |
utils.toogleItemsWrapper();
|
30 |
utils.toogleAddButton();
|
|
|
31 |
},
|
|
|
32 |
toogleItemsWrapper: function () {
|
33 |
|
34 |
if (utils.countItems() === 0) {
|
@@ -36,7 +43,9 @@
|
|
36 |
} else {
|
37 |
nodes.$itemsWrapper.show();
|
38 |
}
|
|
|
39 |
},
|
|
|
40 |
toogleAddButton: function(){
|
41 |
if(data.limit !== 0 ){
|
42 |
(utils.countItems() >= data.limit ) ?
|
@@ -44,14 +53,24 @@
|
|
44 |
nodes.$addButton.show();
|
45 |
}
|
46 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
init: function () {
|
48 |
utils.initItemsTemplates();
|
49 |
utils.toogleNodes();
|
50 |
utils.removeDefaultItem();
|
51 |
utils.initSortable();
|
52 |
},
|
|
|
53 |
initSortable: function () {
|
54 |
-
if (!nodes.$optionWrapper.hasClass('is-sortable')) {
|
55 |
return false;
|
56 |
}
|
57 |
|
@@ -63,6 +82,7 @@
|
|
63 |
axis: 'y',
|
64 |
update: function(){
|
65 |
nodes.$optionWrapper.trigger('change'); // for customizer
|
|
|
66 |
},
|
67 |
start: function(e, ui){
|
68 |
// Update the height of the placeholder to match the moving item.
|
@@ -74,31 +94,39 @@
|
|
74 |
}
|
75 |
});
|
76 |
},
|
|
|
77 |
initItemsTemplates: function () {
|
78 |
var $items = nodes.$itemsWrapper.find('> .item');
|
|
|
79 |
if ($items.length > 0) {
|
80 |
$items.each(function () {
|
81 |
utils.editItem($(this), JSON.parse($(this).find('input').val()));
|
82 |
});
|
83 |
}
|
84 |
},
|
|
|
85 |
createItem: function (values) {
|
86 |
var $clonedItem = nodes.getDefaultItem(),
|
87 |
$clonedInput = $clonedItem.find('.input-wrapper');
|
88 |
|
89 |
var $inputTemplate = $(
|
90 |
$.trim($clonedInput.html())
|
91 |
-
.split(
|
|
|
|
|
|
|
92 |
);
|
93 |
-
$inputTemplate.attr('value', JSON.stringify(values));
|
94 |
|
95 |
-
$
|
|
|
|
|
96 |
|
97 |
var template = '';
|
98 |
|
99 |
try {
|
100 |
/**
|
101 |
-
* may throw error in in template is used an option id
|
|
|
102 |
*/
|
103 |
values._context = $clonedItem.find('.content');
|
104 |
|
@@ -119,9 +147,11 @@
|
|
119 |
|
120 |
return $clonedItem;
|
121 |
},
|
|
|
122 |
addNewItem: function (values) {
|
123 |
nodes.$itemsWrapper.append(utils.createItem(values));
|
124 |
},
|
|
|
125 |
editItem: function (item, values) {
|
126 |
item.replaceWith(utils.createItem(values));
|
127 |
}
|
@@ -132,8 +162,18 @@
|
|
132 |
e.preventDefault();
|
133 |
$(this).closest('.item').remove();
|
134 |
utils.toogleNodes();
|
135 |
-
|
136 |
nodes.$optionWrapper.trigger('change'); // for customizer
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
});
|
138 |
|
139 |
nodes.$itemsWrapper.on('click', '> .item', function (e) {
|
@@ -167,6 +207,7 @@
|
|
167 |
}
|
168 |
|
169 |
nodes.$optionWrapper.trigger('change'); // for customizer
|
|
|
170 |
});
|
171 |
|
172 |
_.map(
|
@@ -200,4 +241,47 @@
|
|
200 |
.addClass('fw-option-initialized');
|
201 |
});
|
202 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
203 |
})(jQuery, _, fwEvents, window);
|
10 |
return $defaultItem.clone().removeClass('default-item').addClass('item');
|
11 |
}
|
12 |
},
|
13 |
+
|
14 |
data = JSON.parse(
|
15 |
JSON.parse(nodes.$optionWrapper.attr('data-for-js')).join('{{') // check option php class
|
16 |
),
|
17 |
+
|
18 |
utils = {
|
19 |
modal: new fw.OptionsModal({
|
20 |
title: data.title,
|
21 |
options: data.options,
|
22 |
size : data.size
|
23 |
}),
|
24 |
+
|
25 |
countItems: function () {
|
26 |
return nodes.$itemsWrapper.find('> .item').length;
|
27 |
},
|
28 |
+
|
29 |
removeDefaultItem: function () {
|
30 |
nodes.$optionWrapper.find('.default-item:first').remove();
|
31 |
},
|
32 |
+
|
33 |
toogleNodes : function(){
|
34 |
utils.toogleItemsWrapper();
|
35 |
utils.toogleAddButton();
|
36 |
+
utils.toogleClone();
|
37 |
},
|
38 |
+
|
39 |
toogleItemsWrapper: function () {
|
40 |
|
41 |
if (utils.countItems() === 0) {
|
43 |
} else {
|
44 |
nodes.$itemsWrapper.show();
|
45 |
}
|
46 |
+
|
47 |
},
|
48 |
+
|
49 |
toogleAddButton: function(){
|
50 |
if(data.limit !== 0 ){
|
51 |
(utils.countItems() >= data.limit ) ?
|
53 |
nodes.$addButton.show();
|
54 |
}
|
55 |
},
|
56 |
+
|
57 |
+
toogleClone: function(){
|
58 |
+
if(data.limit !== 0 ){
|
59 |
+
(utils.countItems() >= data.limit ) ?
|
60 |
+
nodes.$itemsWrapper.addClass('hide-clone') :
|
61 |
+
nodes.$itemsWrapper.removeClass('hide-clone');
|
62 |
+
}
|
63 |
+
},
|
64 |
+
|
65 |
init: function () {
|
66 |
utils.initItemsTemplates();
|
67 |
utils.toogleNodes();
|
68 |
utils.removeDefaultItem();
|
69 |
utils.initSortable();
|
70 |
},
|
71 |
+
|
72 |
initSortable: function () {
|
73 |
+
if (! nodes.$optionWrapper.hasClass('is-sortable')) {
|
74 |
return false;
|
75 |
}
|
76 |
|
82 |
axis: 'y',
|
83 |
update: function(){
|
84 |
nodes.$optionWrapper.trigger('change'); // for customizer
|
85 |
+
fw.options.trigger.changeForEl(nodes.$optionWrapper);
|
86 |
},
|
87 |
start: function(e, ui){
|
88 |
// Update the height of the placeholder to match the moving item.
|
94 |
}
|
95 |
});
|
96 |
},
|
97 |
+
|
98 |
initItemsTemplates: function () {
|
99 |
var $items = nodes.$itemsWrapper.find('> .item');
|
100 |
+
|
101 |
if ($items.length > 0) {
|
102 |
$items.each(function () {
|
103 |
utils.editItem($(this), JSON.parse($(this).find('input').val()));
|
104 |
});
|
105 |
}
|
106 |
},
|
107 |
+
|
108 |
createItem: function (values) {
|
109 |
var $clonedItem = nodes.getDefaultItem(),
|
110 |
$clonedInput = $clonedItem.find('.input-wrapper');
|
111 |
|
112 |
var $inputTemplate = $(
|
113 |
$.trim($clonedInput.html())
|
114 |
+
.split(
|
115 |
+
nodes.$addButton.attr('data-increment-placeholder')
|
116 |
+
)
|
117 |
+
.join(utils.countItems())
|
118 |
);
|
|
|
119 |
|
120 |
+
$inputTemplate.find('input').attr('value', JSON.stringify(values));
|
121 |
+
|
122 |
+
$clonedInput.children().first().replaceWith($inputTemplate);
|
123 |
|
124 |
var template = '';
|
125 |
|
126 |
try {
|
127 |
/**
|
128 |
+
* may throw error in in template is used an option id
|
129 |
+
* added after some items was already saved
|
130 |
*/
|
131 |
values._context = $clonedItem.find('.content');
|
132 |
|
147 |
|
148 |
return $clonedItem;
|
149 |
},
|
150 |
+
|
151 |
addNewItem: function (values) {
|
152 |
nodes.$itemsWrapper.append(utils.createItem(values));
|
153 |
},
|
154 |
+
|
155 |
editItem: function (item, values) {
|
156 |
item.replaceWith(utils.createItem(values));
|
157 |
}
|
162 |
e.preventDefault();
|
163 |
$(this).closest('.item').remove();
|
164 |
utils.toogleNodes();
|
|
|
165 |
nodes.$optionWrapper.trigger('change'); // for customizer
|
166 |
+
fw.options.trigger.changeForEl(nodes.$optionWrapper);
|
167 |
+
});
|
168 |
+
|
169 |
+
nodes.$itemsWrapper.on('click', '.clone-item', function (e) {
|
170 |
+
e.stopPropagation();
|
171 |
+
var $item = $(this).closest('.item');
|
172 |
+
var $vals = JSON.parse($($item).find('input').val());
|
173 |
+
utils.addNewItem($vals);
|
174 |
+
utils.toogleNodes();
|
175 |
+
nodes.$optionWrapper.trigger('change'); // for customizer
|
176 |
+
fw.options.trigger.changeForEl(nodes.$optionWrapper);
|
177 |
});
|
178 |
|
179 |
nodes.$itemsWrapper.on('click', '> .item', function (e) {
|
207 |
}
|
208 |
|
209 |
nodes.$optionWrapper.trigger('change'); // for customizer
|
210 |
+
fw.options.trigger.changeForEl(nodes.$optionWrapper);
|
211 |
});
|
212 |
|
213 |
_.map(
|
241 |
.addClass('fw-option-initialized');
|
242 |
});
|
243 |
|
244 |
+
fw.options.register('addable-popup', {
|
245 |
+
getValue: function (optionDescriptor) {
|
246 |
+
var promise = $.Deferred();
|
247 |
+
|
248 |
+
// TODO: refactor that!!!
|
249 |
+
if (jQuery.when.all===undefined) {
|
250 |
+
jQuery.when.all = function(deferreds) {
|
251 |
+
var deferred = new jQuery.Deferred();
|
252 |
+
$.when.apply(jQuery, deferreds).then(
|
253 |
+
function() {
|
254 |
+
deferred.resolve(Array.prototype.slice.call(arguments));
|
255 |
+
},
|
256 |
+
function() {
|
257 |
+
deferred.fail(Array.prototype.slice.call(arguments));
|
258 |
+
});
|
259 |
+
|
260 |
+
return deferred;
|
261 |
+
}
|
262 |
+
}
|
263 |
+
|
264 |
+
jQuery.when.all(
|
265 |
+
$(optionDescriptor.el).find(
|
266 |
+
'> .fw-option-type-addable-popup > .items-wrapper'
|
267 |
+
).first().find(
|
268 |
+
'> .item.fw-backend-options-virtual-context'
|
269 |
+
).toArray().map(fw.options.getContextValue)
|
270 |
+
).then(function (valuesAsArray) {
|
271 |
+
promise.resolve({
|
272 |
+
value: _.map(
|
273 |
+
valuesAsArray,
|
274 |
+
_.compose(JSON.parse, _.first, _.values, _.property('value'))
|
275 |
+
),
|
276 |
+
|
277 |
+
optionDescriptor: optionDescriptor
|
278 |
+
})
|
279 |
+
});
|
280 |
+
|
281 |
+
return promise;
|
282 |
+
},
|
283 |
+
|
284 |
+
startListeningForChanges: $.noop
|
285 |
+
});
|
286 |
+
|
287 |
})(jQuery, _, fwEvents, window);
|
framework/includes/option-types/addable-popup/view.php
CHANGED
@@ -24,7 +24,7 @@ $increment_placeholder = '###-addable-popup-increment-'. fw_rand_md5() .'-###';
|
|
24 |
)); ?>
|
25 |
<div class="items-wrapper">
|
26 |
<?php foreach ($data['value'] as $key => $value): ?>
|
27 |
-
<div class="item">
|
28 |
<div class="input-wrapper">
|
29 |
<?php echo fw()->backend->option_type('hidden')->render('', array('value' => json_encode($value)), array(
|
30 |
'id_prefix' => $data['id_prefix'] . $id . '-' . $key . '-',
|
@@ -35,10 +35,11 @@ $increment_placeholder = '###-addable-popup-increment-'. fw_rand_md5() .'-###';
|
|
35 |
|
36 |
<div class="content"><!-- will be populated from js --></div>
|
37 |
<a href="#" class="dashicons fw-x delete-item"></a>
|
|
|
38 |
</div>
|
39 |
<?php endforeach; ?>
|
40 |
</div>
|
41 |
-
<div class="default-item">
|
42 |
<div class="input-wrapper">
|
43 |
<?php echo fw()->backend->option_type('hidden')->render('', array('value' => '[]'), array(
|
44 |
'id_prefix' => $data['id_prefix'] . $id . '-' . $increment_placeholder,
|
@@ -49,6 +50,7 @@ $increment_placeholder = '###-addable-popup-increment-'. fw_rand_md5() .'-###';
|
|
49 |
|
50 |
<div class="content"></div>
|
51 |
<a href="#" class="dashicons fw-x delete-item"></a>
|
|
|
52 |
</div>
|
53 |
<?php
|
54 |
echo fw_html_tag('button', array(
|
24 |
)); ?>
|
25 |
<div class="items-wrapper">
|
26 |
<?php foreach ($data['value'] as $key => $value): ?>
|
27 |
+
<div class="item fw-backend-options-virtual-context">
|
28 |
<div class="input-wrapper">
|
29 |
<?php echo fw()->backend->option_type('hidden')->render('', array('value' => json_encode($value)), array(
|
30 |
'id_prefix' => $data['id_prefix'] . $id . '-' . $key . '-',
|
35 |
|
36 |
<div class="content"><!-- will be populated from js --></div>
|
37 |
<a href="#" class="dashicons fw-x delete-item"></a>
|
38 |
+
<small class="dashicons dashicons-admin-page clone-item" title="<?php echo __('Clone','fw') ?>"></small>
|
39 |
</div>
|
40 |
<?php endforeach; ?>
|
41 |
</div>
|
42 |
+
<div class="default-item fw-backend-options-virtual-context">
|
43 |
<div class="input-wrapper">
|
44 |
<?php echo fw()->backend->option_type('hidden')->render('', array('value' => '[]'), array(
|
45 |
'id_prefix' => $data['id_prefix'] . $id . '-' . $increment_placeholder,
|
50 |
|
51 |
<div class="content"></div>
|
52 |
<a href="#" class="dashicons fw-x delete-item"></a>
|
53 |
+
<small class="dashicons dashicons-admin-page clone-item" title="<?php echo __('Clone','fw') ?>"></small>
|
54 |
</div>
|
55 |
<?php
|
56 |
echo fw_html_tag('button', array(
|
framework/includes/option-types/background-image/class-fw-option-type-background-image.php
CHANGED
@@ -21,6 +21,10 @@ class FW_Option_Type_Background_Image extends FW_Option_Type {
|
|
21 |
);
|
22 |
}
|
23 |
|
|
|
|
|
|
|
|
|
24 |
/**
|
25 |
* @internal
|
26 |
* {@inheritdoc}
|
21 |
);
|
22 |
}
|
23 |
|
24 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
25 |
+
return false;
|
26 |
+
}
|
27 |
+
|
28 |
/**
|
29 |
* @internal
|
30 |
* {@inheritdoc}
|
framework/includes/option-types/background-image/static/js/scripts.js
CHANGED
@@ -2,34 +2,104 @@ jQuery(document).ready(function ($) {
|
|
2 |
var optionTypeClass = 'fw-option-type-background-image';
|
3 |
var eventNamePrefix = 'fw:option-type:background-image:';
|
4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
fwEvents.on('fw:options:init', function (data) {
|
6 |
var $options = data.$elements.find('.'+ optionTypeClass +':not(.initialized)');
|
7 |
|
8 |
-
$options.
|
9 |
-
|
10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
});
|
20 |
|
21 |
// route inner image-picker events as this option events
|
22 |
{
|
23 |
-
$options.on(
|
24 |
-
|
25 |
-
|
|
|
|
|
|
|
|
|
26 |
|
27 |
-
$options.on(
|
28 |
-
|
29 |
-
|
|
|
|
|
|
|
|
|
30 |
}
|
31 |
|
32 |
$options.addClass('initialized');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
});
|
34 |
|
35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
var optionTypeClass = 'fw-option-type-background-image';
|
3 |
var eventNamePrefix = 'fw:option-type:background-image:';
|
4 |
|
5 |
+
fw.options.register('background-image', {
|
6 |
+
startListeningForChanges: jQuery.noop,
|
7 |
+
getValue: function (optionDescriptor) {
|
8 |
+
return {
|
9 |
+
value: getValueForEl(optionDescriptor.el),
|
10 |
+
optionDescriptor: optionDescriptor
|
11 |
+
}
|
12 |
+
}
|
13 |
+
});
|
14 |
+
|
15 |
fwEvents.on('fw:options:init', function (data) {
|
16 |
var $options = data.$elements.find('.'+ optionTypeClass +':not(.initialized)');
|
17 |
|
18 |
+
$options.toArray().map(function (el) {
|
19 |
+
/**
|
20 |
+
* Here we start listening to events triggered by inner option
|
21 |
+
* types. We may receive events from 3 nested option types here:
|
22 |
+
*
|
23 |
+
* 1. radio
|
24 |
+
* 2. image-picker
|
25 |
+
* 3. upload
|
26 |
+
*/
|
27 |
+
fw.options.on.changeByContext(el, function (optionDescriptor) {
|
28 |
+
if (optionDescriptor.type === 'radio') {
|
29 |
+
var $predefined = $(
|
30 |
+
optionDescriptor.el
|
31 |
+
).closest('.fw-inner').find('.predefined');
|
32 |
|
33 |
+
var $custom = $(
|
34 |
+
optionDescriptor.el
|
35 |
+
).closest('.fw-inner').find('.custom');
|
36 |
+
|
37 |
+
getValueForEl(el).then(function (value) {
|
38 |
+
var type = value.type
|
39 |
+
|
40 |
+
if (type === 'custom') {
|
41 |
+
$predefined.hide();
|
42 |
+
$custom.show();
|
43 |
+
} else {
|
44 |
+
$predefined.show();
|
45 |
+
$custom.hide();
|
46 |
+
}
|
47 |
+
})
|
48 |
+
|
49 |
+
}
|
50 |
+
|
51 |
+
triggerChangeAndInferValueFor(
|
52 |
+
// Here we refer to the optionDescriptor.context
|
53 |
+
// as to the `background-image` option type container
|
54 |
+
optionDescriptor.context
|
55 |
+
)
|
56 |
+
});
|
57 |
});
|
58 |
|
59 |
// route inner image-picker events as this option events
|
60 |
{
|
61 |
+
$options.on(
|
62 |
+
'fw:option-type:image-picker:clicked',
|
63 |
+
'.fw-option-type-image-picker',
|
64 |
+
function(e, data) {
|
65 |
+
jQuery(this).trigger(eventNamePrefix + 'clicked', data);
|
66 |
+
}
|
67 |
+
);
|
68 |
|
69 |
+
$options.on(
|
70 |
+
'fw:option-type:image-picker:changed',
|
71 |
+
'.fw-option-type-image-picker',
|
72 |
+
function(e, data) {
|
73 |
+
jQuery(this).trigger(eventNamePrefix + 'changed', data);
|
74 |
+
}
|
75 |
+
);
|
76 |
}
|
77 |
|
78 |
$options.addClass('initialized');
|
79 |
+
|
80 |
+
function triggerChangeAndInferValueFor (el) {
|
81 |
+
getValueForEl(el).then(function (value) {
|
82 |
+
fw.options.trigger.changeForEl(el, {
|
83 |
+
value: value
|
84 |
+
});
|
85 |
+
})
|
86 |
+
|
87 |
+
}
|
88 |
+
|
89 |
});
|
90 |
|
91 |
+
function getValueForEl (el) {
|
92 |
+
var promise = $.Deferred();
|
93 |
+
|
94 |
+
var optionDescriptor = fw.options.getOptionDescriptor(el);
|
95 |
+
|
96 |
+
fw.options.getContextValue(
|
97 |
+
optionDescriptor.el
|
98 |
+
).then(function (value) {
|
99 |
+
promise.resolve(value.value);
|
100 |
+
});
|
101 |
+
|
102 |
+
return promise;
|
103 |
+
}
|
104 |
+
|
105 |
+
});
|
framework/includes/option-types/datetime-picker/class-fw-option-type-datetime-picker.php
CHANGED
@@ -11,6 +11,10 @@ class FW_Option_Type_Datetime_Picker extends FW_Option_Type {
|
|
11 |
return 'fixed';
|
12 |
}
|
13 |
|
|
|
|
|
|
|
|
|
14 |
/**
|
15 |
* Detetime-picker options on http://xdsoft.net/jqplugins/datetimepicker/ excepts: [value]
|
16 |
* Additional options:
|
@@ -62,9 +66,11 @@ class FW_Option_Type_Datetime_Picker extends FW_Option_Type {
|
|
62 |
$option['datetime-picker']['lang'] = substr(get_locale(), 0, 2);
|
63 |
$option['attr']['data-moment-format'] = $moment_format;
|
64 |
|
65 |
-
|
66 |
-
|
67 |
-
|
|
|
|
|
68 |
}
|
69 |
|
70 |
/**
|
@@ -153,4 +159,4 @@ class FW_Option_Type_Datetime_Picker extends FW_Option_Type {
|
|
153 |
return false;
|
154 |
}
|
155 |
|
156 |
-
}
|
11 |
return 'fixed';
|
12 |
}
|
13 |
|
14 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
15 |
+
return false;
|
16 |
+
}
|
17 |
+
|
18 |
/**
|
19 |
* Detetime-picker options on http://xdsoft.net/jqplugins/datetimepicker/ excepts: [value]
|
20 |
* Additional options:
|
66 |
$option['datetime-picker']['lang'] = substr(get_locale(), 0, 2);
|
67 |
$option['attr']['data-moment-format'] = $moment_format;
|
68 |
|
69 |
+
$html = '<div ' . fw_attr_to_html($wrapper_attr) .' >';
|
70 |
+
$html .= fw()->backend->option_type( 'text' )->render( $id, $option, $data );
|
71 |
+
$html .= '</div>';
|
72 |
+
|
73 |
+
return $html;
|
74 |
}
|
75 |
|
76 |
/**
|
159 |
return false;
|
160 |
}
|
161 |
|
162 |
+
}
|
framework/includes/option-types/datetime-picker/static/js/script.js
CHANGED
@@ -11,9 +11,29 @@
|
|
11 |
};
|
12 |
|
13 |
fwe.trigger('fw:options:datetime-picker:before-init', data);
|
14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
};
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
fwe.on('fw:options:init', function(data) {
|
18 |
data.$elements
|
19 |
.find('.fw-option-type-datetime-picker').each(init)
|
11 |
};
|
12 |
|
13 |
fwe.trigger('fw:options:datetime-picker:before-init', data);
|
14 |
+
|
15 |
+
$input.datetimepicker(data.options)
|
16 |
+
.on('change', function (e) {
|
17 |
+
fw.options.trigger.changeForEl(
|
18 |
+
jQuery(e.target).closest('[data-fw-option-type="datetime-picker"]'), {
|
19 |
+
value: e.target.value
|
20 |
+
}
|
21 |
+
)
|
22 |
+
});
|
23 |
};
|
24 |
|
25 |
+
fw.options.register('datetime-picker', {
|
26 |
+
startListeningForChanges: $.noop,
|
27 |
+
getValue: function (optionDescriptor) {
|
28 |
+
return {
|
29 |
+
value: $(optionDescriptor.el).find(
|
30 |
+
'[data-fw-option-type="text"]'
|
31 |
+
).find('> input').val(),
|
32 |
+
optionDescriptor: optionDescriptor
|
33 |
+
}
|
34 |
+
}
|
35 |
+
})
|
36 |
+
|
37 |
fwe.on('fw:options:init', function(data) {
|
38 |
data.$elements
|
39 |
.find('.fw-option-type-datetime-picker').each(init)
|
framework/includes/option-types/datetime-range/class-fw-option-type-datetime-range.php
CHANGED
@@ -15,6 +15,10 @@ class FW_Option_Type_Datetime_Range extends FW_Option_Type {
|
|
15 |
return 'auto';
|
16 |
}
|
17 |
|
|
|
|
|
|
|
|
|
18 |
/**
|
19 |
* Avaible options on http://xdsoft.net/jqplugins/datetimepicker/ excepts: [value, format]
|
20 |
* @internal
|
@@ -114,4 +118,4 @@ class FW_Option_Type_Datetime_Range extends FW_Option_Type {
|
|
114 |
}
|
115 |
|
116 |
|
117 |
-
}
|
15 |
return 'auto';
|
16 |
}
|
17 |
|
18 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
19 |
+
return false;
|
20 |
+
}
|
21 |
+
|
22 |
/**
|
23 |
* Avaible options on http://xdsoft.net/jqplugins/datetimepicker/ excepts: [value, format]
|
24 |
* @internal
|
118 |
}
|
119 |
|
120 |
|
121 |
+
}
|
framework/includes/option-types/datetime-range/static/css/styles.css
CHANGED
@@ -3,12 +3,9 @@
|
|
3 |
margin: 0 10px;
|
4 |
}
|
5 |
|
6 |
-
.fw-option-type-datetime-range .fw-option-
|
7 |
-
.fw-option-type-datetime-range .fw-option-
|
8 |
-
.fw-option-type-datetime-range .delimiter
|
9 |
-
.fw-backend-option-input-type-datetime-range .fw-option-type-datetime-picker.from,
|
10 |
-
.fw-backend-option-input-type-datetime-range .fw-option-type-datetime-picker.to,
|
11 |
-
.fw-backend-option-input-type-datetime-range .delimiter {
|
12 |
display: inline-block;
|
13 |
}
|
14 |
|
3 |
margin: 0 10px;
|
4 |
}
|
5 |
|
6 |
+
.fw-option-type-datetime-range .fw-backend-option-descriptor[data-fw-option-id=from],
|
7 |
+
.fw-option-type-datetime-range .fw-backend-option-descriptor[data-fw-option-id=to],
|
8 |
+
.fw-option-type-datetime-range .delimiter {
|
|
|
|
|
|
|
9 |
display: inline-block;
|
10 |
}
|
11 |
|
framework/includes/option-types/datetime-range/static/js/script.js
CHANGED
@@ -158,8 +158,15 @@
|
|
158 |
//fwe.trigger('fw:datetime-range:first:open', { dateTimePicker: dateTimeFirstPicker, dateTimeInput: $dateTimeFirstInput }); ????
|
159 |
});
|
160 |
|
161 |
-
$dateTimeFirstInput.on('change',
|
162 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
|
164 |
dateTimeLastPicker.on('open.xdsoft', function(e){
|
165 |
var firstInputMomentFormat = $dateTimeFirstInput.data('moment-format'),
|
@@ -265,6 +272,39 @@
|
|
265 |
.addClass('fw-option-initialized');
|
266 |
});
|
267 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
268 |
});
|
269 |
|
270 |
})(jQuery, fwEvents);
|
158 |
//fwe.trigger('fw:datetime-range:first:open', { dateTimePicker: dateTimeFirstPicker, dateTimeInput: $dateTimeFirstInput }); ????
|
159 |
});
|
160 |
|
161 |
+
$dateTimeFirstInput.on('change', function () {
|
162 |
+
setMaxTimeLimit();
|
163 |
+
triggerChangeFor(this);
|
164 |
+
});
|
165 |
+
|
166 |
+
$dateTimeLastInput.on('change', function () {
|
167 |
+
setMinTimeLimit();
|
168 |
+
triggerChangeFor(this);
|
169 |
+
});
|
170 |
|
171 |
dateTimeLastPicker.on('open.xdsoft', function(e){
|
172 |
var firstInputMomentFormat = $dateTimeFirstInput.data('moment-format'),
|
272 |
.addClass('fw-option-initialized');
|
273 |
});
|
274 |
|
275 |
+
fw.options.register('datetime-range', {
|
276 |
+
startListeningForChanges: $.noop,
|
277 |
+
getValue: function (optionDescriptor) {
|
278 |
+
return {
|
279 |
+
value: getValueForEl(optionDescriptor.el),
|
280 |
+
optionDescriptor: optionDescriptor
|
281 |
+
};
|
282 |
+
}
|
283 |
+
});
|
284 |
+
|
285 |
+
function triggerChangeFor ($container) {
|
286 |
+
$container = $($container).closest(
|
287 |
+
'[data-fw-option-type="datetime-range"]'
|
288 |
+
);
|
289 |
+
|
290 |
+
fw.options.trigger.changeForEl($container, {
|
291 |
+
value: getValueForEl($container)
|
292 |
+
});
|
293 |
+
}
|
294 |
+
|
295 |
+
function getValueForEl (el) {
|
296 |
+
return {
|
297 |
+
from: $(el).find(
|
298 |
+
'[data-fw-option-id="from"] input'
|
299 |
+
).val(),
|
300 |
+
|
301 |
+
to: $(el).find(
|
302 |
+
'[data-fw-option-id="to"] input'
|
303 |
+
).val()
|
304 |
+
}
|
305 |
+
}
|
306 |
+
|
307 |
+
|
308 |
});
|
309 |
|
310 |
})(jQuery, fwEvents);
|
framework/includes/option-types/icon-v2/class-fw-option-type-icon-v2.php
CHANGED
@@ -12,6 +12,10 @@ class FW_Option_Type_Icon_v2 extends FW_Option_Type
|
|
12 |
return 'icon-v2';
|
13 |
}
|
14 |
|
|
|
|
|
|
|
|
|
15 |
public function _init()
|
16 |
{
|
17 |
/**
|
@@ -32,7 +36,7 @@ class FW_Option_Type_Icon_v2 extends FW_Option_Type
|
|
32 |
protected function _enqueue_static($id, $option, $data)
|
33 |
{
|
34 |
add_action(
|
35 |
-
'
|
36 |
array($this, 'load_templates')
|
37 |
);
|
38 |
|
12 |
return 'icon-v2';
|
13 |
}
|
14 |
|
15 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
16 |
+
return false;
|
17 |
+
}
|
18 |
+
|
19 |
public function _init()
|
20 |
{
|
21 |
/**
|
36 |
protected function _enqueue_static($id, $option, $data)
|
37 |
{
|
38 |
add_action(
|
39 |
+
'admin_print_footer_scripts',
|
40 |
array($this, 'load_templates')
|
41 |
);
|
42 |
|
framework/includes/option-types/icon-v2/static/js/icon-picker-v2.js
CHANGED
@@ -214,8 +214,8 @@ window.fwOptionTypeIconV2Picker = fw.Modal.extend({
|
|
214 |
},
|
215 |
|
216 |
attachEvents: function() {
|
217 |
-
fwEvents.on('fw:option-type:upload:change', this.setAttachment, this);
|
218 |
-
fwEvents.on('fw:option-type:upload:clear', this.setAttachment, this);
|
219 |
},
|
220 |
|
221 |
setHtml: function() {
|
214 |
},
|
215 |
|
216 |
attachEvents: function() {
|
217 |
+
fwEvents.on('fw:option-type:upload:change', _.bind(this.setAttachment, this));
|
218 |
+
fwEvents.on('fw:option-type:upload:clear', _.bind(this.setAttachment, this));
|
219 |
},
|
220 |
|
221 |
setHtml: function() {
|
framework/includes/option-types/icon-v2/static/js/render-icon-previews.js
CHANGED
@@ -199,22 +199,39 @@
|
|
199 |
function setDataForRoot ($root, data) {
|
200 |
var currentData = getDataForRoot($root);
|
201 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
202 |
$root.find('input').val(
|
203 |
-
JSON.stringify(
|
204 |
-
_.omit(
|
205 |
-
_.extend(
|
206 |
-
{},
|
207 |
-
currentData,
|
208 |
-
data
|
209 |
-
),
|
210 |
-
|
211 |
-
'attachment'
|
212 |
-
)
|
213 |
-
)
|
214 |
).trigger('change');
|
215 |
|
216 |
refreshSinglePreview($root);
|
217 |
}
|
218 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
219 |
}(jQuery));
|
220 |
|
199 |
function setDataForRoot ($root, data) {
|
200 |
var currentData = getDataForRoot($root);
|
201 |
|
202 |
+
var actualValue = _.omit(
|
203 |
+
_.extend(
|
204 |
+
{},
|
205 |
+
currentData,
|
206 |
+
data
|
207 |
+
),
|
208 |
+
|
209 |
+
'attachment'
|
210 |
+
);
|
211 |
+
|
212 |
+
fw.options.trigger.changeForEl($root, {
|
213 |
+
value: actualValue
|
214 |
+
});
|
215 |
+
|
216 |
$root.find('input').val(
|
217 |
+
JSON.stringify(actualValue)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
218 |
).trigger('change');
|
219 |
|
220 |
refreshSinglePreview($root);
|
221 |
}
|
222 |
|
223 |
+
fw.options.register('icon-v2', {
|
224 |
+
startListeningForChanges: $.noop,
|
225 |
+
getValue: function (optionDescriptor) {
|
226 |
+
return {
|
227 |
+
value: JSON.parse(
|
228 |
+
$(optionDescriptor.el).find('input').val()
|
229 |
+
),
|
230 |
+
|
231 |
+
optionDescriptor: optionDescriptor
|
232 |
+
}
|
233 |
+
}
|
234 |
+
})
|
235 |
+
|
236 |
}(jQuery));
|
237 |
|
framework/includes/option-types/image-picker/class-fw-option-type-image-picker.php
CHANGED
@@ -41,6 +41,10 @@ class Fw_Option_Type_Image_Picker extends FW_Option_Type
|
|
41 |
);
|
42 |
}
|
43 |
|
|
|
|
|
|
|
|
|
44 |
/**
|
45 |
* @internal
|
46 |
* {@inheritdoc}
|
@@ -201,4 +205,4 @@ class Fw_Option_Type_Image_Picker extends FW_Option_Type
|
|
201 |
{
|
202 |
return 'auto';
|
203 |
}
|
204 |
-
}
|
41 |
);
|
42 |
}
|
43 |
|
44 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
45 |
+
return false;
|
46 |
+
}
|
47 |
+
|
48 |
/**
|
49 |
* @internal
|
50 |
* {@inheritdoc}
|
205 |
{
|
206 |
return 'auto';
|
207 |
}
|
208 |
+
}
|
framework/includes/option-types/image-picker/static/js/scripts.js
CHANGED
@@ -2,6 +2,16 @@
|
|
2 |
var optionTypeClass = 'fw-option-type-image-picker';
|
3 |
var eventNamePrefix = 'fw:option-type:image-picker:';
|
4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
jQuery(document).ready(function ($) {
|
6 |
/** Init image_picker options */
|
7 |
fwEvents.on('fw:options:init', function (data) {
|
@@ -27,6 +37,10 @@
|
|
27 |
changed: function (oldValues, newValues) {
|
28 |
var $this = $(this);
|
29 |
|
|
|
|
|
|
|
|
|
30 |
$this.closest('.'+ optionTypeClass).trigger(eventNamePrefix +'changed', {
|
31 |
oldValues : oldValues,
|
32 |
newValues : newValues
|
2 |
var optionTypeClass = 'fw-option-type-image-picker';
|
3 |
var eventNamePrefix = 'fw:option-type:image-picker:';
|
4 |
|
5 |
+
fw.options.register('image-picker', {
|
6 |
+
startListeningForChanges: jQuery.noop,
|
7 |
+
getValue: function (optionDescriptor) {
|
8 |
+
return {
|
9 |
+
value: optionDescriptor.el.querySelector('select').value,
|
10 |
+
optionDescriptor: optionDescriptor
|
11 |
+
}
|
12 |
+
}
|
13 |
+
});
|
14 |
+
|
15 |
jQuery(document).ready(function ($) {
|
16 |
/** Init image_picker options */
|
17 |
fwEvents.on('fw:options:init', function (data) {
|
37 |
changed: function (oldValues, newValues) {
|
38 |
var $this = $(this);
|
39 |
|
40 |
+
fw.options.trigger.changeForEl($this[0], {
|
41 |
+
value: newValues[0]
|
42 |
+
});
|
43 |
+
|
44 |
$this.closest('.'+ optionTypeClass).trigger(eventNamePrefix +'changed', {
|
45 |
oldValues : oldValues,
|
46 |
newValues : newValues
|
framework/includes/option-types/map/class-fw-option-type-map.php
CHANGED
@@ -27,6 +27,7 @@ class FW_Option_Type_Map extends FW_Option_Type {
|
|
27 |
'1.0',
|
28 |
true
|
29 |
);
|
|
|
30 |
wp_localize_script(
|
31 |
$this->get_type() . '-scripts',
|
32 |
'_fw_option_type_map',
|
@@ -49,21 +50,26 @@ class FW_Option_Type_Map extends FW_Option_Type {
|
|
49 |
? json_encode($data['value']['coordinates'])
|
50 |
: '';
|
51 |
|
52 |
-
$path = fw_get_framework_directory(
|
|
|
|
|
53 |
|
54 |
-
return fw_render_view(
|
55 |
'id' => $id,
|
56 |
'option' => $option,
|
57 |
'data' => $data
|
58 |
-
)
|
|
|
|
|
|
|
|
|
59 |
}
|
60 |
|
61 |
/**
|
62 |
* @internal
|
63 |
*/
|
64 |
protected function _get_value_from_input( $option, $input_value ) {
|
65 |
-
|
66 |
-
if ( ! is_array( $input_value ) || empty( $input_value ) ) {
|
67 |
$input_value = $option['value'];
|
68 |
}
|
69 |
|
@@ -102,4 +108,4 @@ class FW_Option_Type_Map extends FW_Option_Type {
|
|
102 |
public static function api_key() {
|
103 |
return FW_Option_Type_GMap_Key::get_key();
|
104 |
}
|
105 |
-
}
|
27 |
'1.0',
|
28 |
true
|
29 |
);
|
30 |
+
|
31 |
wp_localize_script(
|
32 |
$this->get_type() . '-scripts',
|
33 |
'_fw_option_type_map',
|
50 |
? json_encode($data['value']['coordinates'])
|
51 |
: '';
|
52 |
|
53 |
+
$path = fw_get_framework_directory(
|
54 |
+
'/includes/option-types/' . $this->get_type() . '/views/view.php'
|
55 |
+
);
|
56 |
|
57 |
+
return fw_render_view($path, array(
|
58 |
'id' => $id,
|
59 |
'option' => $option,
|
60 |
'data' => $data
|
61 |
+
));
|
62 |
+
}
|
63 |
+
|
64 |
+
public function _get_data_for_js($id, $option, $data = array()) {
|
65 |
+
return false;
|
66 |
}
|
67 |
|
68 |
/**
|
69 |
* @internal
|
70 |
*/
|
71 |
protected function _get_value_from_input( $option, $input_value ) {
|
72 |
+
if (! is_array( $input_value ) || empty( $input_value )) {
|
|
|
73 |
$input_value = $option['value'];
|
74 |
}
|
75 |
|
108 |
public static function api_key() {
|
109 |
return FW_Option_Type_GMap_Key::get_key();
|
110 |
}
|
111 |
+
}
|
framework/includes/option-types/map/static/js/scripts.js
CHANGED
@@ -1,26 +1,22 @@
|
|
1 |
-
|
2 |
-
* Script file that will manage the "map" option
|
3 |
-
*/
|
4 |
|
5 |
-
|
6 |
-
(function(
|
7 |
-
jQuery( document ).ready( function( ) {
|
8 |
$.fn.pressEnter = function(fn) {
|
9 |
return this.each(function() {
|
10 |
$(this).bind('enterPress', fn);
|
11 |
-
|
12 |
-
|
13 |
-
{
|
14 |
-
$(this).trigger(
|
15 |
}
|
16 |
-
})
|
17 |
});
|
18 |
};
|
19 |
|
20 |
-
function fw_option_map_initialize(
|
21 |
-
|
22 |
-
|
23 |
-
data.find( '.fw-option-map-inputs').attr( 'readonly', 'readonly' );
|
24 |
return;
|
25 |
}
|
26 |
|
@@ -28,271 +24,354 @@
|
|
28 |
|
29 |
// Define map option
|
30 |
var option = {
|
31 |
-
fields
|
32 |
-
location
|
33 |
-
element
|
34 |
-
value
|
35 |
},
|
36 |
-
venue
|
37 |
-
element
|
38 |
-
value
|
39 |
},
|
40 |
-
address
|
41 |
-
element
|
42 |
-
value
|
43 |
},
|
44 |
-
city
|
45 |
-
element
|
46 |
-
value
|
47 |
},
|
48 |
-
state
|
49 |
-
element
|
50 |
-
value
|
51 |
},
|
52 |
-
country
|
53 |
-
element
|
54 |
-
value
|
55 |
},
|
56 |
-
zipCode
|
57 |
-
element
|
58 |
-
value
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
},
|
60 |
-
coordinates : {
|
61 |
-
element : data.find( '.map-coordinates' ),
|
62 |
-
value : jQuery.parseJSON( data.find( '.map-coordinates').attr('value') )
|
63 |
-
}
|
64 |
},
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
|
|
71 |
},
|
72 |
-
|
73 |
-
|
74 |
-
|
|
|
75 |
},
|
76 |
-
|
77 |
-
|
78 |
-
|
|
|
79 |
},
|
80 |
|
81 |
getComputedLongAddress: function() {
|
82 |
var longAddress = '';
|
83 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
//join array without empty fields
|
85 |
-
longAddress = _.reduce(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
function(a, b) {
|
87 |
-
return b = b.trim(), b &&
|
88 |
-
|
|
|
|
|
|
|
89 |
}
|
90 |
|
91 |
return longAddress;
|
92 |
},
|
93 |
|
94 |
-
refreshMap: function()
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
|
|
|
|
|
|
|
|
99 |
|
100 |
var mapOptions = {
|
101 |
-
center
|
102 |
-
zoom
|
103 |
mapTypeControl: false,
|
104 |
-
streetViewControl: false
|
105 |
};
|
106 |
|
107 |
-
if (_.isEmpty(this.map.object.map)){
|
108 |
-
this.map.object.map = new google.maps.Map(
|
|
|
|
|
|
|
109 |
}
|
110 |
|
111 |
-
if (_.isEmpty(this.map.object.marker)){
|
112 |
this.map.object.marker = new google.maps.Marker({
|
113 |
position: googleMapsPos,
|
114 |
map: option.map.object.map,
|
115 |
-
draggable: true
|
116 |
});
|
117 |
}
|
118 |
|
119 |
this.map.object.map.setCenter(googleMapsPos);
|
120 |
|
121 |
-
google.maps.event.addListener(
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
130 |
},
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
|
|
|
|
137 |
},
|
|
|
138 |
updateMapCoords: function(geoObject) {
|
139 |
-
if(
|
140 |
-
return;
|
141 |
|
142 |
option.map.object.map.panTo(geoObject.geometry.location);
|
143 |
-
option.map.object.marker.setPosition(
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
148 |
},
|
149 |
-
|
150 |
-
|
151 |
-
option.setValue(
|
152 |
-
option.setValue(
|
153 |
-
option.setValue(
|
154 |
-
option.setValue(
|
155 |
-
option.setValue(
|
156 |
-
option.setValue(
|
157 |
-
option.setValue(
|
158 |
-
option.setValue(
|
159 |
-
|
160 |
-
if(
|
161 |
-
return;
|
162 |
|
163 |
option.updateMapCoords(geoObject);
|
164 |
|
165 |
-
for(
|
|
|
|
|
|
|
|
|
166 |
var current = geoObject.address_components[i];
|
167 |
|
168 |
-
|
169 |
/*if ( current.types[0] == "establishment" )
|
170 |
option.setValue( 'venue', current.long_name );*/
|
171 |
|
172 |
-
if (
|
173 |
-
option.setValue(
|
174 |
-
|
175 |
-
if (
|
176 |
-
option.setValue(
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
if (
|
182 |
-
option.setValue(
|
183 |
-
|
184 |
-
if (
|
185 |
-
option.setValue(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
186 |
}
|
187 |
|
188 |
//option.setValue('location', geoObject.formatted_address.trim() );
|
189 |
-
option.setValue(
|
190 |
-
|
|
|
|
|
191 |
|
192 |
-
if (
|
193 |
option.setValue('venue', geoObject.name);
|
194 |
}
|
195 |
},
|
196 |
-
|
197 |
-
|
198 |
-
|
|
|
199 |
};
|
200 |
|
201 |
-
//Create google map
|
202 |
var geocoder = new google.maps.Geocoder();
|
203 |
option.refreshMap();
|
204 |
|
205 |
-
data.on(
|
206 |
-
|
207 |
-
|
208 |
-
|
|
|
|
|
|
|
|
|
209 |
|
210 |
// Define autocomplete
|
211 |
-
var autocomplete = new google.maps.places.Autocomplete(
|
|
|
|
|
|
|
212 |
autocomplete.bindTo('bounds', option.map.object.map);
|
213 |
|
214 |
// Add events
|
215 |
-
google.maps.event.addListener(
|
216 |
-
|
217 |
-
|
218 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
219 |
}
|
220 |
-
|
221 |
-
option.updateFields( place );
|
222 |
-
setTimeout( function() {
|
223 |
-
option.toggles.expand.trigger( 'click' );
|
224 |
-
}, 200 );
|
225 |
-
});
|
226 |
|
227 |
-
$(
|
228 |
-
if(e.keyCode === 13){
|
229 |
return false;
|
230 |
}
|
231 |
});
|
232 |
|
233 |
var handleGeoCoder = function(address) {
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
243 |
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
lng: 0
|
248 |
-
}, true );
|
249 |
}
|
|
|
|
|
250 |
|
251 |
-
|
252 |
-
option.refreshMap();
|
253 |
-
}, 200 );
|
254 |
-
|
255 |
-
});
|
256 |
-
}
|
257 |
-
|
258 |
-
$( option.fields.location.element).pressEnter( function(e) {
|
259 |
var address = option.getFreshValue('location');
|
260 |
-
geocoder.geocode(
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
267 |
}
|
268 |
-
setTimeout( function() {
|
269 |
-
option.toggles.expand.trigger( 'click' );
|
270 |
-
}, 200 );
|
271 |
-
option.updateFields( responses[0] );
|
272 |
-
setTimeout( function() {
|
273 |
-
option.setValue('location', option.getComputedLongAddress());
|
274 |
-
}, 200 );
|
275 |
-
|
276 |
}
|
277 |
-
|
278 |
return false;
|
279 |
});
|
280 |
|
281 |
-
option.toggles.expand.on(
|
282 |
e.preventDefault();
|
283 |
option.tabs.first.hide().addClass('closed');
|
284 |
option.tabs.second.show().removeClass('closed');
|
285 |
google.maps.event.trigger(option.map.object.map, 'resize');
|
286 |
option.refreshMap();
|
287 |
});
|
288 |
-
option.toggles.reset.on(
|
289 |
e.preventDefault();
|
290 |
-
option.updateFields(
|
291 |
option.tabs.second.hide().addClass('closed');
|
292 |
option.tabs.first.show().removeClass('closed');
|
293 |
});
|
294 |
|
295 |
-
if (option.fields.location.value){
|
296 |
//open map
|
297 |
option.toggles.expand.trigger('click');
|
298 |
}
|
@@ -300,16 +379,21 @@
|
|
300 |
|
301 |
var pendingInit = [];
|
302 |
|
303 |
-
fwe.on('fw:options:init', function
|
304 |
-
|
305 |
-
|
|
|
306 |
|
307 |
if (!obj.length) {
|
308 |
return;
|
309 |
}
|
310 |
|
311 |
-
if (
|
312 |
-
|
|
|
|
|
|
|
|
|
313 |
pendingInit.push(obj);
|
314 |
} else {
|
315 |
pendingInit.push(obj);
|
@@ -319,24 +403,27 @@
|
|
319 |
* Fixes https://github.com/ThemeFuse/Unyson/issues/1675
|
320 |
*/
|
321 |
$.ajax({
|
322 |
-
type:
|
323 |
url: localized.google_maps_js_uri,
|
324 |
-
dataType:
|
325 |
-
cache: true
|
326 |
-
})
|
327 |
-
|
328 |
-
|
329 |
-
|
|
|
|
|
330 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
331 |
});
|
332 |
-
pendingInit = [];
|
333 |
-
}).fail(function(){
|
334 |
-
console.error('Failed to load Google Maps script');
|
335 |
-
pendingInit = [];
|
336 |
-
});
|
337 |
}
|
338 |
} else {
|
339 |
-
obj.each(function(){
|
340 |
fw_option_map_initialize($(this));
|
341 |
});
|
342 |
}
|
@@ -345,4 +432,24 @@
|
|
345 |
});
|
346 |
});
|
347 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
348 |
})(jQuery, _, fwEvents, _fw_option_type_map);
|
1 |
+
'use strict';
|
|
|
|
|
2 |
|
3 |
+
(function($, _, fwe, localized) {
|
4 |
+
jQuery(document).ready(function() {
|
|
|
5 |
$.fn.pressEnter = function(fn) {
|
6 |
return this.each(function() {
|
7 |
$(this).bind('enterPress', fn);
|
8 |
+
|
9 |
+
$(this).keyup(function(e) {
|
10 |
+
if (e.keyCode == 13) {
|
11 |
+
$(this).trigger('enterPress');
|
12 |
}
|
13 |
+
});
|
14 |
});
|
15 |
};
|
16 |
|
17 |
+
function fw_option_map_initialize(data) {
|
18 |
+
if (typeof google === 'undefined') {
|
19 |
+
data.find('.fw-option-map-inputs').attr('readonly', 'readonly');
|
|
|
20 |
return;
|
21 |
}
|
22 |
|
24 |
|
25 |
// Define map option
|
26 |
var option = {
|
27 |
+
fields: {
|
28 |
+
location: {
|
29 |
+
element: data.find('.map-location'),
|
30 |
+
value: data.find('.map-location').attr('value'),
|
31 |
},
|
32 |
+
venue: {
|
33 |
+
element: data.find('.map-venue'),
|
34 |
+
value: data.find('.map-venue').attr('value'),
|
35 |
},
|
36 |
+
address: {
|
37 |
+
element: data.find('.map-address'),
|
38 |
+
value: data.find('.map-address').attr('value'),
|
39 |
},
|
40 |
+
city: {
|
41 |
+
element: data.find('.map-city'),
|
42 |
+
value: data.find('.map-city').attr('value'),
|
43 |
},
|
44 |
+
state: {
|
45 |
+
element: data.find('.map-state'),
|
46 |
+
value: data.find('.map-state').attr('value'),
|
47 |
},
|
48 |
+
country: {
|
49 |
+
element: data.find('.map-country'),
|
50 |
+
value: data.find('.map-country').attr('value'),
|
51 |
},
|
52 |
+
zipCode: {
|
53 |
+
element: data.find('.map-zip'),
|
54 |
+
value: data.find('.map-zip').attr('value'),
|
55 |
+
},
|
56 |
+
coordinates: {
|
57 |
+
element: data.find('.map-coordinates'),
|
58 |
+
value: jQuery.parseJSON(
|
59 |
+
data.find('.map-coordinates').attr('value')
|
60 |
+
),
|
61 |
},
|
|
|
|
|
|
|
|
|
62 |
},
|
63 |
+
|
64 |
+
map: {
|
65 |
+
container: data.find('.map-googlemap'),
|
66 |
+
object: {
|
67 |
+
map: {},
|
68 |
+
marker: {},
|
69 |
+
},
|
70 |
},
|
71 |
+
|
72 |
+
toggles: {
|
73 |
+
expand: data.find('.fw-option-maps-expand'),
|
74 |
+
reset: data.find('.fw-option-maps-close'),
|
75 |
},
|
76 |
+
|
77 |
+
tabs: {
|
78 |
+
first: data.find('.fw-option-maps-tab.first'),
|
79 |
+
second: data.find('.fw-option-maps-tab.second'),
|
80 |
},
|
81 |
|
82 |
getComputedLongAddress: function() {
|
83 |
var longAddress = '';
|
84 |
+
|
85 |
+
if (
|
86 |
+
option.getFreshValue('zipCode') ||
|
87 |
+
option.getFreshValue('venue') ||
|
88 |
+
option.getFreshValue('address') ||
|
89 |
+
option.getFreshValue('city') ||
|
90 |
+
option.getFreshValue('state') ||
|
91 |
+
option.getFreshValue('country')
|
92 |
+
) {
|
93 |
//join array without empty fields
|
94 |
+
longAddress = _.reduce(
|
95 |
+
[
|
96 |
+
option.getFreshValue('venue'),
|
97 |
+
option.getFreshValue('address'),
|
98 |
+
option.getFreshValue('city'),
|
99 |
+
option.getFreshValue('state'),
|
100 |
+
option.getFreshValue('country'),
|
101 |
+
option.getFreshValue('zipCode'),
|
102 |
+
],
|
103 |
function(a, b) {
|
104 |
+
return (b = b.trim()), b &&
|
105 |
+
(a = a ? a + ', ' + b : b), a;
|
106 |
+
},
|
107 |
+
''
|
108 |
+
);
|
109 |
}
|
110 |
|
111 |
return longAddress;
|
112 |
},
|
113 |
|
114 |
+
refreshMap: function() {
|
115 |
+
var googleMapsPos =
|
116 |
+
typeof this.fields.coordinates.value === 'object' &&
|
117 |
+
this.fields.coordinates.value != null
|
118 |
+
? new google.maps.LatLng(
|
119 |
+
this.fields.coordinates.value.lat,
|
120 |
+
this.fields.coordinates.value.lng
|
121 |
+
)
|
122 |
+
: new google.maps.LatLng(-34, 150);
|
123 |
|
124 |
var mapOptions = {
|
125 |
+
center: googleMapsPos,
|
126 |
+
zoom: 15,
|
127 |
mapTypeControl: false,
|
128 |
+
streetViewControl: false,
|
129 |
};
|
130 |
|
131 |
+
if (_.isEmpty(this.map.object.map)) {
|
132 |
+
this.map.object.map = new google.maps.Map(
|
133 |
+
option.map.container[0],
|
134 |
+
mapOptions
|
135 |
+
);
|
136 |
}
|
137 |
|
138 |
+
if (_.isEmpty(this.map.object.marker)) {
|
139 |
this.map.object.marker = new google.maps.Marker({
|
140 |
position: googleMapsPos,
|
141 |
map: option.map.object.map,
|
142 |
+
draggable: true,
|
143 |
});
|
144 |
}
|
145 |
|
146 |
this.map.object.map.setCenter(googleMapsPos);
|
147 |
|
148 |
+
google.maps.event.addListener(
|
149 |
+
this.map.object.marker,
|
150 |
+
'dragend',
|
151 |
+
function() {
|
152 |
+
geocoder.geocode(
|
153 |
+
{
|
154 |
+
latLng: this.getPosition(),
|
155 |
+
},
|
156 |
+
function(responses) {
|
157 |
+
if (responses && responses.length > 0) {
|
158 |
+
option.updateFields(responses[0]);
|
159 |
+
}
|
160 |
+
}
|
161 |
+
);
|
162 |
+
}
|
163 |
+
);
|
164 |
},
|
165 |
+
|
166 |
+
setValue: function(property, value, encode) {
|
167 |
+
this.fields[property].value = value;
|
168 |
+
if (encode)
|
169 |
+
this.fields[property].element.val(
|
170 |
+
JSON.stringify(value)
|
171 |
+
);
|
172 |
+
else this.fields[property].element.val(value);
|
173 |
},
|
174 |
+
|
175 |
updateMapCoords: function(geoObject) {
|
176 |
+
if (geoObject == null) return;
|
|
|
177 |
|
178 |
option.map.object.map.panTo(geoObject.geometry.location);
|
179 |
+
option.map.object.marker.setPosition(
|
180 |
+
geoObject.geometry.location
|
181 |
+
);
|
182 |
+
option.setValue(
|
183 |
+
'coordinates',
|
184 |
+
{
|
185 |
+
lat: geoObject.geometry.location.lat(),
|
186 |
+
lng: geoObject.geometry.location.lng(),
|
187 |
+
},
|
188 |
+
true
|
189 |
+
);
|
190 |
},
|
191 |
+
|
192 |
+
updateFields: function(geoObject) {
|
193 |
+
option.setValue('location', '');
|
194 |
+
option.setValue('state', '');
|
195 |
+
option.setValue('country', '');
|
196 |
+
option.setValue('city', '');
|
197 |
+
option.setValue('address', '');
|
198 |
+
option.setValue('zipCode', '');
|
199 |
+
option.setValue('venue', '');
|
200 |
+
option.setValue('coordinates', '');
|
201 |
+
|
202 |
+
if (geoObject == null) return;
|
|
|
203 |
|
204 |
option.updateMapCoords(geoObject);
|
205 |
|
206 |
+
for (
|
207 |
+
var i = 0;
|
208 |
+
i < geoObject.address_components.length;
|
209 |
+
i++
|
210 |
+
) {
|
211 |
var current = geoObject.address_components[i];
|
212 |
|
|
|
213 |
/*if ( current.types[0] == "establishment" )
|
214 |
option.setValue( 'venue', current.long_name );*/
|
215 |
|
216 |
+
if (current.types[0] == 'administrative_area_level_1')
|
217 |
+
option.setValue('state', current.long_name.trim());
|
218 |
+
|
219 |
+
if (current.types[0] == 'country')
|
220 |
+
option.setValue(
|
221 |
+
'country',
|
222 |
+
current.long_name.trim()
|
223 |
+
);
|
224 |
+
|
225 |
+
if (current.types[0] == 'locality')
|
226 |
+
option.setValue('city', current.long_name.trim());
|
227 |
+
|
228 |
+
if (current.types[0] == 'route')
|
229 |
+
option.setValue(
|
230 |
+
'address',
|
231 |
+
current.long_name.trim()
|
232 |
+
);
|
233 |
+
|
234 |
+
if (current.types[0] == 'postal_code')
|
235 |
+
option.setValue(
|
236 |
+
'zipCode',
|
237 |
+
current.long_name.trim()
|
238 |
+
);
|
239 |
}
|
240 |
|
241 |
//option.setValue('location', geoObject.formatted_address.trim() );
|
242 |
+
option.setValue(
|
243 |
+
'location',
|
244 |
+
option.getComputedLongAddress()
|
245 |
+
);
|
246 |
|
247 |
+
if (typeof geoObject.name != 'undefined') {
|
248 |
option.setValue('venue', geoObject.name);
|
249 |
}
|
250 |
},
|
251 |
+
|
252 |
+
getFreshValue: function(property) {
|
253 |
+
return this.fields[property].element.val();
|
254 |
+
},
|
255 |
};
|
256 |
|
257 |
+
// Create google map
|
258 |
var geocoder = new google.maps.Geocoder();
|
259 |
option.refreshMap();
|
260 |
|
261 |
+
data.on(
|
262 |
+
'blur',
|
263 |
+
'.map-city, .map-address, .map-state, .map-country, .map-zip, .map-venue',
|
264 |
+
function() {
|
265 |
+
var address = option.getComputedLongAddress();
|
266 |
+
handleGeoCoder(address);
|
267 |
+
}
|
268 |
+
);
|
269 |
|
270 |
// Define autocomplete
|
271 |
+
var autocomplete = new google.maps.places.Autocomplete(
|
272 |
+
option.fields.location.element[0]
|
273 |
+
);
|
274 |
+
|
275 |
autocomplete.bindTo('bounds', option.map.object.map);
|
276 |
|
277 |
// Add events
|
278 |
+
google.maps.event.addListener(
|
279 |
+
autocomplete,
|
280 |
+
'place_changed',
|
281 |
+
function() {
|
282 |
+
var place = autocomplete.getPlace();
|
283 |
+
if (!place.geometry) {
|
284 |
+
return;
|
285 |
+
}
|
286 |
+
used_autocomplete = true;
|
287 |
+
option.updateFields(place);
|
288 |
+
setTimeout(function() {
|
289 |
+
option.toggles.expand.trigger('click');
|
290 |
+
}, 200);
|
291 |
}
|
292 |
+
);
|
|
|
|
|
|
|
|
|
|
|
293 |
|
294 |
+
$(option.fields.location.element).keydown(function(e) {
|
295 |
+
if (e.keyCode === 13) {
|
296 |
return false;
|
297 |
}
|
298 |
});
|
299 |
|
300 |
var handleGeoCoder = function(address) {
|
301 |
+
'undefined' == typeof geocoder &&
|
302 |
+
(geocoder = new google.maps.Geocoder());
|
303 |
+
geocoder.geocode(
|
304 |
+
{
|
305 |
+
address: address,
|
306 |
+
},
|
307 |
+
function(responses, status) {
|
308 |
+
if (responses.length > 0 && status === 'OK') {
|
309 |
+
option.updateMapCoords(responses[0]);
|
310 |
+
option.setValue(
|
311 |
+
'location',
|
312 |
+
option.getComputedLongAddress()
|
313 |
+
);
|
314 |
+
} else {
|
315 |
+
option.setValue(
|
316 |
+
'coordinates',
|
317 |
+
{
|
318 |
+
lat: 0,
|
319 |
+
lng: 0,
|
320 |
+
},
|
321 |
+
true
|
322 |
+
);
|
323 |
+
}
|
324 |
|
325 |
+
setTimeout(function() {
|
326 |
+
option.refreshMap();
|
327 |
+
}, 200);
|
|
|
|
|
328 |
}
|
329 |
+
);
|
330 |
+
};
|
331 |
|
332 |
+
$(option.fields.location.element).pressEnter(function(e) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
333 |
var address = option.getFreshValue('location');
|
334 |
+
geocoder.geocode(
|
335 |
+
{
|
336 |
+
address: address,
|
337 |
+
},
|
338 |
+
function(responses) {
|
339 |
+
if (responses.length > 0) {
|
340 |
+
if (used_autocomplete) {
|
341 |
+
used_autocomplete = false;
|
342 |
+
return;
|
343 |
+
}
|
344 |
+
setTimeout(function() {
|
345 |
+
option.toggles.expand.trigger('click');
|
346 |
+
}, 200);
|
347 |
+
option.updateFields(responses[0]);
|
348 |
+
setTimeout(function() {
|
349 |
+
option.setValue(
|
350 |
+
'location',
|
351 |
+
option.getComputedLongAddress()
|
352 |
+
);
|
353 |
+
}, 200);
|
354 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
355 |
}
|
356 |
+
);
|
357 |
return false;
|
358 |
});
|
359 |
|
360 |
+
option.toggles.expand.on('click', function(e) {
|
361 |
e.preventDefault();
|
362 |
option.tabs.first.hide().addClass('closed');
|
363 |
option.tabs.second.show().removeClass('closed');
|
364 |
google.maps.event.trigger(option.map.object.map, 'resize');
|
365 |
option.refreshMap();
|
366 |
});
|
367 |
+
option.toggles.reset.on('click', function(e) {
|
368 |
e.preventDefault();
|
369 |
+
option.updateFields(null);
|
370 |
option.tabs.second.hide().addClass('closed');
|
371 |
option.tabs.first.show().removeClass('closed');
|
372 |
});
|
373 |
|
374 |
+
if (option.fields.location.value) {
|
375 |
//open map
|
376 |
option.toggles.expand.trigger('click');
|
377 |
}
|
379 |
|
380 |
var pendingInit = [];
|
381 |
|
382 |
+
fwe.on('fw:options:init', function(data) {
|
383 |
+
var obj = data.$elements.find(
|
384 |
+
'.fw-option-type-map:not(.initialized)'
|
385 |
+
);
|
386 |
|
387 |
if (!obj.length) {
|
388 |
return;
|
389 |
}
|
390 |
|
391 |
+
if (
|
392 |
+
typeof google == 'undefined' ||
|
393 |
+
typeof google.maps == 'undefined'
|
394 |
+
) {
|
395 |
+
if (pendingInit.length) {
|
396 |
+
// already in process of loading the script
|
397 |
pendingInit.push(obj);
|
398 |
} else {
|
399 |
pendingInit.push(obj);
|
403 |
* Fixes https://github.com/ThemeFuse/Unyson/issues/1675
|
404 |
*/
|
405 |
$.ajax({
|
406 |
+
type: 'GET',
|
407 |
url: localized.google_maps_js_uri,
|
408 |
+
dataType: 'script',
|
409 |
+
cache: true,
|
410 |
+
})
|
411 |
+
.done(function() {
|
412 |
+
$.each(pendingInit, function(i, obj) {
|
413 |
+
obj.each(function() {
|
414 |
+
fw_option_map_initialize($(this));
|
415 |
+
});
|
416 |
});
|
417 |
+
|
418 |
+
pendingInit = [];
|
419 |
+
})
|
420 |
+
.fail(function() {
|
421 |
+
console.error('Failed to load Google Maps script');
|
422 |
+
pendingInit = [];
|
423 |
});
|
|
|
|
|
|
|
|
|
|
|
424 |
}
|
425 |
} else {
|
426 |
+
obj.each(function() {
|
427 |
fw_option_map_initialize($(this));
|
428 |
});
|
429 |
}
|
432 |
});
|
433 |
});
|
434 |
|
435 |
+
fw.options.register('map', {
|
436 |
+
getValue: function (optionDescriptor) {
|
437 |
+
var promise = $.Deferred()
|
438 |
+
|
439 |
+
fw.options
|
440 |
+
.getContextValue(optionDescriptor.el)
|
441 |
+
.then(function (result) {
|
442 |
+
result.value.coordinates = JSON.parse(
|
443 |
+
result.value.coordinates
|
444 |
+
);
|
445 |
+
|
446 |
+
promise.resolve({
|
447 |
+
value: result.value,
|
448 |
+
optionDescriptor: optionDescriptor
|
449 |
+
});
|
450 |
+
});
|
451 |
+
|
452 |
+
return promise;
|
453 |
+
}
|
454 |
+
})
|
455 |
})(jQuery, _, fwEvents, _fw_option_type_map);
|
framework/includes/option-types/multi-picker/class-fw-option-type-multi-picker.php
CHANGED
@@ -65,6 +65,17 @@ class FW_Option_Type_Multi_Picker extends FW_Option_Type
|
|
65 |
return true;
|
66 |
}
|
67 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
/**
|
69 |
* @internal
|
70 |
* {@inheritdoc}
|
@@ -81,12 +92,22 @@ class FW_Option_Type_Multi_Picker extends FW_Option_Type
|
|
81 |
$option['attr']['class'] .= ' fw-option-type-multi-picker-without-borders';
|
82 |
}
|
83 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
/**
|
85 |
* Leave only select choice options to be rendered in the browser
|
86 |
* the rest move to attr[data-options-template] to be rendered on choice change.
|
87 |
* This should improve page loading speed.
|
88 |
*/
|
89 |
-
{
|
90 |
{
|
91 |
reset($option['picker']);
|
92 |
$picker_key = key($option['picker']);
|
@@ -157,7 +178,9 @@ class FW_Option_Type_Multi_Picker extends FW_Option_Type
|
|
157 |
* @param string $picker_type
|
158 |
* @return array( 'choice_id' => array( Choice Options ) )
|
159 |
*/
|
160 |
-
private function get_picker_choices($option
|
|
|
|
|
161 |
switch($picker_type) {
|
162 |
case 'switch':
|
163 |
$picker_choices = array_intersect_key($option['choices'], array(
|
@@ -220,17 +243,9 @@ class FW_Option_Type_Multi_Picker extends FW_Option_Type
|
|
220 |
*/
|
221 |
$option = $this->prepare_choices($option);
|
222 |
|
223 |
-
{
|
224 |
-
reset($option['picker']);
|
225 |
-
$picker_key = key($option['picker']);
|
226 |
-
$picker = $option['picker'][$picker_key];
|
227 |
-
$picker_type = $picker['type'];
|
228 |
-
}
|
229 |
|
230 |
$picker_choices = $this->get_picker_choices(
|
231 |
-
$option
|
232 |
-
$picker,
|
233 |
-
$picker_type
|
234 |
);
|
235 |
|
236 |
$hide_picker = '';
|
@@ -255,6 +270,7 @@ class FW_Option_Type_Multi_Picker extends FW_Option_Type
|
|
255 |
}
|
256 |
|
257 |
$choices_groups = array();
|
|
|
258 |
foreach ($picker_choices as $key => $set) {
|
259 |
if (!empty($set)) {
|
260 |
$choices_groups[$id . '-' . $key] = array(
|
@@ -276,17 +292,29 @@ class FW_Option_Type_Multi_Picker extends FW_Option_Type
|
|
276 |
}
|
277 |
}
|
278 |
|
279 |
-
$picker_group =
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
'
|
284 |
-
|
285 |
-
'
|
286 |
-
|
287 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
288 |
|
289 |
-
return array_merge($picker_group, $choices_groups);
|
290 |
}
|
291 |
|
292 |
/**
|
@@ -306,6 +334,7 @@ class FW_Option_Type_Multi_Picker extends FW_Option_Type
|
|
306 |
if (is_array($settings['for'])) {
|
307 |
// Insert location: after/before.
|
308 |
$location = fw_akg('location', $settings, 'before');
|
|
|
309 |
foreach ($settings['for'] as $name) {
|
310 |
if (isset($choices[$name])) {
|
311 |
if ('before' === $location) {
|
@@ -318,7 +347,19 @@ class FW_Option_Type_Multi_Picker extends FW_Option_Type
|
|
318 |
);
|
319 |
}
|
320 |
} else {
|
321 |
-
$result[$name]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
322 |
}
|
323 |
}
|
324 |
}
|
@@ -330,7 +371,9 @@ class FW_Option_Type_Multi_Picker extends FW_Option_Type
|
|
330 |
}
|
331 |
}
|
332 |
|
|
|
333 |
fw_aks('choices', $result, $option);
|
|
|
334 |
return $option;
|
335 |
}
|
336 |
|
@@ -339,13 +382,6 @@ class FW_Option_Type_Multi_Picker extends FW_Option_Type
|
|
339 |
*/
|
340 |
protected function _get_value_from_input($option, $input_value)
|
341 |
{
|
342 |
-
{
|
343 |
-
reset($option['picker']);
|
344 |
-
$picker_key = key($option['picker']);
|
345 |
-
$picker_type = $option['picker'][$picker_key]['type'];
|
346 |
-
$picker = $option['picker'][$picker_key];
|
347 |
-
}
|
348 |
-
|
349 |
$value = array();
|
350 |
|
351 |
/**
|
@@ -353,20 +389,25 @@ class FW_Option_Type_Multi_Picker extends FW_Option_Type
|
|
353 |
*/
|
354 |
$option = $this->prepare_choices($option);
|
355 |
|
356 |
-
if (
|
357 |
-
$
|
358 |
-
|
359 |
-
$
|
360 |
-
|
361 |
-
|
362 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
363 |
}
|
364 |
|
365 |
foreach (
|
366 |
$this->get_picker_choices(
|
367 |
-
$option
|
368 |
-
$picker,
|
369 |
-
$picker_type
|
370 |
)
|
371 |
as $choice_id => $choice_options
|
372 |
) {
|
65 |
return true;
|
66 |
}
|
67 |
|
68 |
+
public function _get_data_for_js($id, $option, $data = array()) {
|
69 |
+
return false;
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Hide label for each multi-picker by default
|
74 |
+
*/
|
75 |
+
public function _default_label($id, $option) {
|
76 |
+
return false;
|
77 |
+
}
|
78 |
+
|
79 |
/**
|
80 |
* @internal
|
81 |
* {@inheritdoc}
|
92 |
$option['attr']['class'] .= ' fw-option-type-multi-picker-without-borders';
|
93 |
}
|
94 |
|
95 |
+
$option['attr']['class'] .= is_array(
|
96 |
+
$option['picker']
|
97 |
+
) ? '' : ' fw-option-type-multi-picker-dynamic';
|
98 |
+
|
99 |
+
// Allow picker to be another option in the same context
|
100 |
+
// JS will watch its changes accordingly
|
101 |
+
if (is_string($option['picker'])) {
|
102 |
+
$option['attr']['data-fw-dynamic-picker-path'] = $option['picker'];
|
103 |
+
}
|
104 |
+
|
105 |
/**
|
106 |
* Leave only select choice options to be rendered in the browser
|
107 |
* the rest move to attr[data-options-template] to be rendered on choice change.
|
108 |
* This should improve page loading speed.
|
109 |
*/
|
110 |
+
if (is_array($option['picker'])) {
|
111 |
{
|
112 |
reset($option['picker']);
|
113 |
$picker_key = key($option['picker']);
|
178 |
* @param string $picker_type
|
179 |
* @return array( 'choice_id' => array( Choice Options ) )
|
180 |
*/
|
181 |
+
private function get_picker_choices($option) {
|
182 |
+
return $option['choices'];
|
183 |
+
|
184 |
switch($picker_type) {
|
185 |
case 'switch':
|
186 |
$picker_choices = array_intersect_key($option['choices'], array(
|
243 |
*/
|
244 |
$option = $this->prepare_choices($option);
|
245 |
|
|
|
|
|
|
|
|
|
|
|
|
|
246 |
|
247 |
$picker_choices = $this->get_picker_choices(
|
248 |
+
$option
|
|
|
|
|
249 |
);
|
250 |
|
251 |
$hide_picker = '';
|
270 |
}
|
271 |
|
272 |
$choices_groups = array();
|
273 |
+
|
274 |
foreach ($picker_choices as $key => $set) {
|
275 |
if (!empty($set)) {
|
276 |
$choices_groups[$id . '-' . $key] = array(
|
292 |
}
|
293 |
}
|
294 |
|
295 |
+
$picker_group = null;
|
296 |
+
|
297 |
+
if (is_array($option['picker'])) {
|
298 |
+
{
|
299 |
+
reset($option['picker']);
|
300 |
+
$picker_key = key($option['picker']);
|
301 |
+
$picker = $option['picker'][$picker_key];
|
302 |
+
$picker_type = $picker['type'];
|
303 |
+
}
|
304 |
+
|
305 |
+
$picker_group = array(
|
306 |
+
$id . '-picker' => array(
|
307 |
+
'type' => 'group',
|
308 |
+
'desc' => false,
|
309 |
+
'label' => false,
|
310 |
+
'attr' => array('class' => $show_borders .' '. $hide_picker .' picker-group picker-type-'. $picker_type),
|
311 |
+
'options' => array($picker_key => $picker)
|
312 |
+
)
|
313 |
+
);
|
314 |
+
|
315 |
+
}
|
316 |
|
317 |
+
return $picker_group ? array_merge($picker_group, $choices_groups) : $choices_groups;
|
318 |
}
|
319 |
|
320 |
/**
|
334 |
if (is_array($settings['for'])) {
|
335 |
// Insert location: after/before.
|
336 |
$location = fw_akg('location', $settings, 'before');
|
337 |
+
|
338 |
foreach ($settings['for'] as $name) {
|
339 |
if (isset($choices[$name])) {
|
340 |
if ('before' === $location) {
|
347 |
);
|
348 |
}
|
349 |
} else {
|
350 |
+
if (isset($result[$name])) {
|
351 |
+
if ('before' === $location) {
|
352 |
+
$result[$name] = array_merge(
|
353 |
+
$settings['options'], $result[$name]
|
354 |
+
);
|
355 |
+
} else {
|
356 |
+
$result[$name] = array_merge(
|
357 |
+
$result[$name], $settings['options']
|
358 |
+
);
|
359 |
+
}
|
360 |
+
} else {
|
361 |
+
$result[$name] = $settings['options'];
|
362 |
+
}
|
363 |
}
|
364 |
}
|
365 |
}
|
371 |
}
|
372 |
}
|
373 |
|
374 |
+
// Replace old `choices` with new structure.
|
375 |
fw_aks('choices', $result, $option);
|
376 |
+
|
377 |
return $option;
|
378 |
}
|
379 |
|
382 |
*/
|
383 |
protected function _get_value_from_input($option, $input_value)
|
384 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
385 |
$value = array();
|
386 |
|
387 |
/**
|
389 |
*/
|
390 |
$option = $this->prepare_choices($option);
|
391 |
|
392 |
+
if (is_array($option['picker'])) {
|
393 |
+
reset($option['picker']);
|
394 |
+
$picker_key = key($option['picker']);
|
395 |
+
$picker_type = $option['picker'][$picker_key]['type'];
|
396 |
+
$picker = $option['picker'][$picker_key];
|
397 |
+
|
398 |
+
if (is_null($input_value) && isset($option['value'][$picker_key])) {
|
399 |
+
$value[$picker_key] = $option['value'][$picker_key];
|
400 |
+
} else {
|
401 |
+
$value[$picker_key] = fw()->backend->option_type($picker_type)->get_value_from_input(
|
402 |
+
$picker,
|
403 |
+
isset($input_value[$picker_key]) ? $input_value[$picker_key] : null
|
404 |
+
);
|
405 |
+
}
|
406 |
}
|
407 |
|
408 |
foreach (
|
409 |
$this->get_picker_choices(
|
410 |
+
$option
|
|
|
|
|
411 |
)
|
412 |
as $choice_id => $choice_options
|
413 |
) {
|
framework/includes/option-types/multi-picker/static/js/multi-picker.js
CHANGED
@@ -1,78 +1,176 @@
|
|
1 |
(function($, fwe) {
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
|
27 |
-
|
28 |
$choicesToReveal.addClass('chosen');
|
29 |
|
30 |
if ($choicesToReveal.length) {
|
31 |
-
$
|
32 |
} else {
|
33 |
-
$
|
34 |
-
}
|
35 |
-
},
|
36 |
-
pickerType = elements.$pickerGroup.attr('class').match(/picker-type-(\S+)/)[1],
|
37 |
-
flows = {
|
38 |
-
'switch': function() {
|
39 |
-
elements.$pickerGroup.find(':checkbox').on('change', function() {
|
40 |
-
var $this = $(this),
|
41 |
-
checked = $(this).is(':checked'),
|
42 |
-
value = JSON.parse($this.attr('data-switch-'+ (checked ? 'right' : 'left') +'-value-json'));
|
43 |
-
|
44 |
-
chooseGroup(value);
|
45 |
-
}).trigger('change');
|
46 |
-
},
|
47 |
-
'select': function() {
|
48 |
-
elements.$pickerGroup.find('select').on('change', function() {
|
49 |
-
chooseGroup(this.value);
|
50 |
-
}).trigger('change');
|
51 |
-
},
|
52 |
-
'short-select': function() {
|
53 |
-
this.select();
|
54 |
-
},
|
55 |
-
'radio': function() {
|
56 |
-
elements.$pickerGroup.find(':radio').on('change', function() {
|
57 |
-
chooseGroup(this.value);
|
58 |
-
}).filter(':checked').trigger('change');
|
59 |
-
},
|
60 |
-
'image-picker': function() {
|
61 |
-
elements.$pickerGroup.find('select').on('change', function() {
|
62 |
-
chooseGroup(this.value);
|
63 |
-
}).trigger('change');
|
64 |
-
},
|
65 |
-
'icon-v2': function () {
|
66 |
-
var iconV2Selector = '.fw-option-type-icon-v2 > input';
|
67 |
-
|
68 |
-
elements.$pickerGroup.find(iconV2Selector).on('change', function() {
|
69 |
-
var type = JSON.parse(this.value)['type'];
|
70 |
-
chooseGroup(type);
|
71 |
-
}).trigger('change');
|
72 |
}
|
73 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
|
75 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
console.error('unknown multi-picker type:', pickerType);
|
77 |
} else {
|
78 |
if (flows[pickerType]) {
|
@@ -92,9 +190,7 @@
|
|
92 |
}
|
93 |
};
|
94 |
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
.addClass('fw-option-initialized');
|
99 |
-
});
|
100 |
})(jQuery, fwEvents);
|
1 |
(function($, fwe) {
|
2 |
+
|
3 |
+
fwe.on('fw:options:init', function(data) {
|
4 |
+
|
5 |
+
data.$elements
|
6 |
+
.find(
|
7 |
+
'.fw-option-type-multi-picker:not(.fw-option-initialized)'
|
8 |
+
)
|
9 |
+
.not(
|
10 |
+
'.fw-option-type-multi-picker-dynamic'
|
11 |
+
)
|
12 |
+
.each(initSimpleMultiPicker)
|
13 |
+
.addClass('fw-option-initialized');
|
14 |
+
|
15 |
+
data.$elements
|
16 |
+
.find(
|
17 |
+
'.fw-option-type-multi-picker.fw-option-type-multi-picker-dynamic'
|
18 |
+
)
|
19 |
+
.not(
|
20 |
+
'.fw-option-initialized'
|
21 |
+
)
|
22 |
+
.each(initDynamicMultiPicker)
|
23 |
+
.addClass('fw-option-initialized');
|
24 |
+
|
25 |
+
});
|
26 |
+
|
27 |
+
fwe.on('fw:options:teardown', function (data) {
|
28 |
+
|
29 |
+
data.$elements
|
30 |
+
.find(
|
31 |
+
'.fw-option-type-multi-picker.fw-option-type-multi-picker-dynamic'
|
32 |
+
).filter('.fw-option-initialized')
|
33 |
+
.each(function () {
|
34 |
+
if ($(this).data().fwPickerListener) {
|
35 |
+
fw.options.off.change($(this).data().fwPickerListener);
|
36 |
}
|
37 |
+
})
|
38 |
+
})
|
39 |
+
|
40 |
+
function initDynamicMultiPicker () {
|
41 |
+
var $container = $(this);
|
42 |
+
|
43 |
+
$container.addClass('fw-option-initialized');
|
44 |
+
|
45 |
+
var optionDescriptor = fw.options.getOptionDescriptor($container[0]);
|
46 |
+
|
47 |
+
var pickerDescriptor = fw.options.findOptionInSameContextFor(
|
48 |
+
optionDescriptor.el,
|
49 |
+
$container.attr('data-fw-dynamic-picker-path')
|
50 |
+
);
|
51 |
+
|
52 |
+
$container.find('> .choice-group').first().addClass('chosen');
|
53 |
+
|
54 |
+
$container.data('fw-picker-listener', handleChange);
|
55 |
+
|
56 |
+
fw.options.on.change($container.data().fwPickerListener);
|
57 |
+
|
58 |
+
chooseGroupForOptionDescriptor(pickerDescriptor);
|
59 |
+
|
60 |
+
function handleChange (optionDescriptor) {
|
61 |
+
if (pickerDescriptor.el === optionDescriptor.el) {
|
62 |
+
chooseGroupForOptionDescriptor(optionDescriptor);
|
63 |
+
}
|
64 |
+
}
|
65 |
+
|
66 |
+
function chooseGroupForOptionDescriptor (optionDescriptor) {
|
67 |
+
fw.options.getValueForEl(pickerDescriptor.el).then(function (value) {
|
68 |
+
if (! _.isString(value.value)) {
|
69 |
+
throw "Your picker returned a non-string value. In order for it to work with multi-pickers it should yield string values";
|
70 |
+
}
|
71 |
+
|
72 |
+
chooseGroup(value.value);
|
73 |
+
});
|
74 |
+
|
75 |
+
function chooseGroup(groupId) {
|
76 |
+
var $choicesGroups = $container.find('> .choice-group');
|
77 |
+
|
78 |
+
var $choicesToReveal = $container.find(
|
79 |
+
'.choice-group[data-choice-key="'+ groupId +'"]'
|
80 |
+
);
|
81 |
|
82 |
+
$choicesGroups.removeClass('chosen');
|
83 |
$choicesToReveal.addClass('chosen');
|
84 |
|
85 |
if ($choicesToReveal.length) {
|
86 |
+
$container.addClass('has-choice');
|
87 |
} else {
|
88 |
+
$container.removeClass('has-choice');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
}
|
90 |
};
|
91 |
+
}
|
92 |
+
|
93 |
+
}
|
94 |
+
|
95 |
+
function initSimpleMultiPicker() {
|
96 |
+
var $this = $(this);
|
97 |
+
|
98 |
+
var elements = {
|
99 |
+
$pickerGroup: $this.find('> .picker-group'),
|
100 |
+
$choicesGroups: $this.find('> .choice-group')
|
101 |
+
};
|
102 |
+
|
103 |
+
var chooseGroup = function(groupId) {
|
104 |
+
var $choicesToReveal = elements.$choicesGroups.filter('.choice-group[data-choice-key="'+ groupId +'"]');
|
105 |
+
|
106 |
+
/**
|
107 |
+
* The group options html was rendered in an attribute to make page load faster.
|
108 |
+
* Move the html from attribute in group and init options with js.
|
109 |
+
*/
|
110 |
+
if ($choicesToReveal.attr('data-options-template')) {
|
111 |
+
$choicesToReveal.html(
|
112 |
+
$choicesToReveal.attr('data-options-template')
|
113 |
+
);
|
114 |
+
|
115 |
+
$choicesToReveal.removeAttr('data-options-template');
|
116 |
+
|
117 |
+
fwEvents.trigger('fw:options:init', {
|
118 |
+
$elements: $choicesToReveal
|
119 |
+
});
|
120 |
+
}
|
121 |
+
|
122 |
+
elements.$choicesGroups.removeClass('chosen');
|
123 |
+
$choicesToReveal.addClass('chosen');
|
124 |
+
|
125 |
+
if ($choicesToReveal.length) {
|
126 |
+
$this.addClass('has-choice');
|
127 |
+
} else {
|
128 |
+
$this.removeClass('has-choice');
|
129 |
+
}
|
130 |
+
};
|
131 |
|
132 |
+
|
133 |
+
var pickerType = elements.$pickerGroup.attr('class').match(/picker-type-(\S+)/)[1];
|
134 |
+
|
135 |
+
var flows = {
|
136 |
+
'switch': function() {
|
137 |
+
elements.$pickerGroup.find(':checkbox').on('change', function() {
|
138 |
+
var $this = $(this),
|
139 |
+
checked = $(this).is(':checked'),
|
140 |
+
value = JSON.parse($this.attr('data-switch-'+ (checked ? 'right' : 'left') +'-value-json'));
|
141 |
+
|
142 |
+
chooseGroup(value);
|
143 |
+
}).trigger('change');
|
144 |
+
},
|
145 |
+
'select': function() {
|
146 |
+
elements.$pickerGroup.find('select').on('change', function() {
|
147 |
+
chooseGroup(this.value);
|
148 |
+
}).trigger('change');
|
149 |
+
},
|
150 |
+
'short-select': function() {
|
151 |
+
this.select();
|
152 |
+
},
|
153 |
+
'radio': function() {
|
154 |
+
elements.$pickerGroup.find(':radio').on('change', function() {
|
155 |
+
chooseGroup(this.value);
|
156 |
+
}).filter(':checked').trigger('change');
|
157 |
+
},
|
158 |
+
'image-picker': function() {
|
159 |
+
elements.$pickerGroup.find('select').on('change', function() {
|
160 |
+
chooseGroup(this.value);
|
161 |
+
}).trigger('change');
|
162 |
+
},
|
163 |
+
'icon-v2': function () {
|
164 |
+
var iconV2Selector = '.fw-option-type-icon-v2 > input';
|
165 |
+
|
166 |
+
elements.$pickerGroup.find(iconV2Selector).on('change', function() {
|
167 |
+
var type = JSON.parse(this.value)['type'];
|
168 |
+
chooseGroup(type);
|
169 |
+
}).trigger('change');
|
170 |
+
}
|
171 |
+
};
|
172 |
+
|
173 |
+
if (! pickerType) {
|
174 |
console.error('unknown multi-picker type:', pickerType);
|
175 |
} else {
|
176 |
if (flows[pickerType]) {
|
190 |
}
|
191 |
};
|
192 |
|
193 |
+
fw.options.register('multi-picker', {
|
194 |
+
getValue: fw.options.get('multi').getValue
|
195 |
+
})
|
|
|
|
|
196 |
})(jQuery, fwEvents);
|
framework/includes/option-types/multi-select/class-fw-option-type-multi-select.php
CHANGED
@@ -48,6 +48,10 @@ if ( ! class_exists( 'FW_Option_Type_Multi_Select' ) ):
|
|
48 |
* Set maximum items number that can be selected
|
49 |
*/
|
50 |
'limit' => 100,
|
|
|
|
|
|
|
|
|
51 |
);
|
52 |
}
|
53 |
|
@@ -68,41 +72,31 @@ if ( ! class_exists( 'FW_Option_Type_Multi_Select' ) ):
|
|
68 |
);
|
69 |
}
|
70 |
|
71 |
-
private static function query_posts(array $
|
72 |
$limits = array_merge(array(
|
73 |
'type' => array(
|
74 |
'post' => true,
|
75 |
'page' => true,
|
76 |
),
|
77 |
'title' => '',
|
78 |
-
|
79 |
-
|
80 |
-
), $limits);
|
81 |
-
|
82 |
-
$limits['limit'] = max($limits['limit'], 1);
|
83 |
|
84 |
/** @var WPDB $wpdb */
|
85 |
global $wpdb;
|
86 |
|
87 |
-
$sql = "SELECT ID
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
|
92 |
{
|
93 |
$prepare = array();
|
94 |
|
95 |
-
if ($limits['id']) {
|
96 |
-
$sql .= " AND ID IN ( "
|
97 |
-
. implode( ', ', array_fill( 1, count( $limits['id'] ), '%d' ) )
|
98 |
-
. " ) ";
|
99 |
-
$prepare = array_merge($prepare, $limits['id']);
|
100 |
-
}
|
101 |
-
|
102 |
if ($limits['type']) {
|
103 |
$sql .= " AND post_type IN ( "
|
104 |
-
|
105 |
-
|
106 |
$prepare = array_merge($prepare, array_keys($limits['type']));
|
107 |
}
|
108 |
|
@@ -112,17 +106,45 @@ if ( ! class_exists( 'FW_Option_Type_Multi_Select' ) ):
|
|
112 |
}
|
113 |
}
|
114 |
|
115 |
-
$
|
116 |
-
|
117 |
-
return $wpdb->get_results(
|
118 |
$prepare
|
119 |
? $wpdb->prepare($sql, $prepare)
|
120 |
: $sql,
|
121 |
ARRAY_A
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
);
|
123 |
}
|
124 |
|
125 |
-
private static function query_terms(array $
|
126 |
$limits = array_merge(array(
|
127 |
'taxonomy' => array(
|
128 |
'category' => true,
|
@@ -130,31 +152,23 @@ if ( ! class_exists( 'FW_Option_Type_Multi_Select' ) ):
|
|
130 |
'title' => '',
|
131 |
'id' => array( /* 1, 7, 120 */ ),
|
132 |
'limit' => 100,
|
133 |
-
), $
|
134 |
-
|
135 |
-
$limits['limit'] = max($limits['limit'], 1);
|
136 |
|
137 |
/** @var WPDB $wpdb */
|
138 |
global $wpdb;
|
139 |
|
140 |
-
$sql = "SELECT terms.term_id
|
141 |
-
|
142 |
-
|
143 |
|
144 |
{
|
145 |
$prepare = array();
|
146 |
|
147 |
-
if ($limits['id']) {
|
148 |
-
$sql .= " AND terms.term_id IN ( "
|
149 |
-
. implode( ', ', array_fill( 1, count( $limits['id'] ), '%d' ) )
|
150 |
-
. " ) ";
|
151 |
-
$prepare = array_merge($prepare, $limits['id']);
|
152 |
-
}
|
153 |
-
|
154 |
if ($limits['taxonomy']) {
|
155 |
$sql .= " AND taxonomies.taxonomy IN ( "
|
156 |
-
|
157 |
-
|
158 |
$prepare = array_merge($prepare, array_keys($limits['taxonomy']));
|
159 |
}
|
160 |
|
@@ -164,13 +178,51 @@ if ( ! class_exists( 'FW_Option_Type_Multi_Select' ) ):
|
|
164 |
}
|
165 |
}
|
166 |
|
167 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
168 |
|
169 |
-
return $
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
);
|
175 |
}
|
176 |
|
@@ -190,25 +242,25 @@ if ( ! class_exists( 'FW_Option_Type_Multi_Select' ) ):
|
|
190 |
global $wpdb;
|
191 |
|
192 |
$sql = "SELECT DISTINCT users.ID AS val, users.user_nicename AS title"
|
193 |
-
|
194 |
-
|
195 |
|
196 |
{
|
197 |
$prepare = array();
|
198 |
|
199 |
if ($limits['id']) {
|
200 |
$sql .= " AND users.ID IN ( "
|
201 |
-
|
202 |
-
|
203 |
$prepare = array_merge($prepare, $limits['id']);
|
204 |
}
|
205 |
|
206 |
if ($limits['role']) {
|
207 |
$sql .= " AND usermeta.meta_key = '{$wpdb->prefix}capabilities' "
|
208 |
-
|
209 |
-
|
210 |
array_fill( 1, count( $limits['role'] ), 'usermeta.meta_value LIKE %s' ) ) .
|
211 |
-
|
212 |
|
213 |
foreach ( $limits['role'] as $name => $filter_by ) {
|
214 |
$prepare[] = ( $filter_by ) ? '%' . $wpdb->esc_like( $name ) . '%' : '';
|
@@ -242,21 +294,33 @@ if ( ! class_exists( 'FW_Option_Type_Multi_Select' ) ):
|
|
242 |
$type = FW_Request::POST( 'data/type' );
|
243 |
$names = ($names = json_decode( FW_Request::POST( 'data/names' ), true )) ? $names : array();
|
244 |
$title = FW_Request::POST( 'data/string' );
|
|
|
245 |
|
246 |
$items = array();
|
247 |
|
248 |
switch ( $type ) {
|
249 |
case 'posts':
|
250 |
-
$items = self::query_posts(array(
|
251 |
-
'type'
|
252 |
'title' => $title,
|
253 |
-
));
|
|
|
|
|
|
|
|
|
|
|
254 |
break;
|
255 |
case 'taxonomy':
|
256 |
$items = self::query_terms(array(
|
257 |
'taxonomy' => array_fill_keys($names, true),
|
258 |
'title' => $title,
|
259 |
));
|
|
|
|
|
|
|
|
|
|
|
|
|
260 |
break;
|
261 |
case 'users':
|
262 |
$items = self::query_users(array(
|
@@ -283,6 +347,7 @@ if ( ! class_exists( 'FW_Option_Type_Multi_Select' ) ):
|
|
283 |
$population = $option['population'];
|
284 |
$source = array();
|
285 |
$items = array();
|
|
|
286 |
|
287 |
if ( isset( $option['population'] ) ) {
|
288 |
switch ( $option['population'] ) {
|
@@ -299,22 +364,61 @@ if ( ! class_exists( 'FW_Option_Type_Multi_Select' ) ):
|
|
299 |
case 'posts' :
|
300 |
if ( isset( $option['source'] ) ) {
|
301 |
$source = is_array( $option['source'] ) ? $option['source'] : array( $option['source'] );
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
307 |
}
|
|
|
|
|
|
|
|
|
|
|
308 |
break;
|
309 |
case 'taxonomy' :
|
310 |
if ( isset( $option['source'] ) ) {
|
311 |
$source = is_array( $option['source'] ) ? $option['source'] : array( $option['source'] );
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
317 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
318 |
break;
|
319 |
case 'users' :
|
320 |
if ( isset( $option['source'] ) && ! empty( $option['source'] ) ) {
|
@@ -333,10 +437,11 @@ if ( ! class_exists( 'FW_Option_Type_Multi_Select' ) ):
|
|
333 |
return '(Invalid <code>population</code> parameter)';
|
334 |
}
|
335 |
|
336 |
-
$option['attr']['data-options']
|
337 |
-
$option['attr']['data-population']
|
338 |
-
$option['attr']['data-
|
339 |
-
$option['attr']['data-
|
|
|
340 |
} else {
|
341 |
return '(The <code>population</code> parameter is required)';
|
342 |
}
|
@@ -384,8 +489,28 @@ if ( ! class_exists( 'FW_Option_Type_Multi_Select' ) ):
|
|
384 |
|
385 |
return empty( $input_value ) ? array() : $value;
|
386 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
387 |
}
|
388 |
|
389 |
add_action( 'wp_ajax_fw_option_type_multi_select_autocomplete',
|
390 |
array( "FW_Option_Type_Multi_Select", '_ajax_autocomplete' ) );
|
391 |
-
endif;
|
48 |
* Set maximum items number that can be selected
|
49 |
*/
|
50 |
'limit' => 100,
|
51 |
+
/**
|
52 |
+
* Show the post type or term taxonomy
|
53 |
+
*/
|
54 |
+
'show-type' => false
|
55 |
);
|
56 |
}
|
57 |
|
72 |
);
|
73 |
}
|
74 |
|
75 |
+
private static function query_posts(array $options) {
|
76 |
$limits = array_merge(array(
|
77 |
'type' => array(
|
78 |
'post' => true,
|
79 |
'page' => true,
|
80 |
),
|
81 |
'title' => '',
|
82 |
+
), $options);
|
83 |
+
fw_aku('limit', $limits);
|
|
|
|
|
|
|
84 |
|
85 |
/** @var WPDB $wpdb */
|
86 |
global $wpdb;
|
87 |
|
88 |
+
$sql = "SELECT ID"
|
89 |
+
." FROM $wpdb->posts"
|
90 |
+
." WHERE post_status IN ( 'publish', 'private' )";
|
91 |
+
//." AND NULLIF(post_password, '') IS NULL"; todo: review
|
92 |
|
93 |
{
|
94 |
$prepare = array();
|
95 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
if ($limits['type']) {
|
97 |
$sql .= " AND post_type IN ( "
|
98 |
+
. implode( ', ', array_fill( 1, count( $limits['type'] ), '%s' ) )
|
99 |
+
. " ) ";
|
100 |
$prepare = array_merge($prepare, array_keys($limits['type']));
|
101 |
}
|
102 |
|
106 |
}
|
107 |
}
|
108 |
|
109 |
+
$ids = wp_list_pluck($wpdb->get_results(
|
|
|
|
|
110 |
$prepare
|
111 |
? $wpdb->prepare($sql, $prepare)
|
112 |
: $sql,
|
113 |
ARRAY_A
|
114 |
+
), 'ID');
|
115 |
+
|
116 |
+
return self::get_posts( $ids, max( fw_akg( 'limit', $options, 100 ), 1 ) );
|
117 |
+
}
|
118 |
+
|
119 |
+
protected static function get_posts( $ids, $limit = 100 ) {
|
120 |
+
if ( empty( $ids ) ) {
|
121 |
+
return array();
|
122 |
+
}
|
123 |
+
|
124 |
+
$query = new WP_Query( array(
|
125 |
+
'post_type' => 'any',
|
126 |
+
'post__in' => $ids,
|
127 |
+
'posts_per_page' => $limit,
|
128 |
+
'fields' => 'ids'
|
129 |
+
) );
|
130 |
+
|
131 |
+
return $query->get_posts();
|
132 |
+
}
|
133 |
+
|
134 |
+
protected static function build_post( $id, $show_type ) {
|
135 |
+
$title = get_the_title( $id );
|
136 |
+
|
137 |
+
return $show_type ? array(
|
138 |
+
'val' => $id,
|
139 |
+
'title' => $title,
|
140 |
+
'type' => self::get_post_type_name( get_post_type( $id ) ),
|
141 |
+
) : array(
|
142 |
+
'val' => $id,
|
143 |
+
'title' => $title
|
144 |
);
|
145 |
}
|
146 |
|
147 |
+
private static function query_terms(array $options) {
|
148 |
$limits = array_merge(array(
|
149 |
'taxonomy' => array(
|
150 |
'category' => true,
|
152 |
'title' => '',
|
153 |
'id' => array( /* 1, 7, 120 */ ),
|
154 |
'limit' => 100,
|
155 |
+
), $options);
|
156 |
+
fw_aku('limit', $limits);
|
|
|
157 |
|
158 |
/** @var WPDB $wpdb */
|
159 |
global $wpdb;
|
160 |
|
161 |
+
$sql = "SELECT terms.term_id"
|
162 |
+
." FROM $wpdb->terms AS terms, $wpdb->term_taxonomy AS taxonomies"
|
163 |
+
." WHERE terms.term_id = taxonomies.term_id AND taxonomies.term_id = taxonomies.term_taxonomy_id";
|
164 |
|
165 |
{
|
166 |
$prepare = array();
|
167 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
168 |
if ($limits['taxonomy']) {
|
169 |
$sql .= " AND taxonomies.taxonomy IN ( "
|
170 |
+
. implode( ', ', array_fill( 1, count( $limits['taxonomy'] ), '%s' ) )
|
171 |
+
. " ) ";
|
172 |
$prepare = array_merge($prepare, array_keys($limits['taxonomy']));
|
173 |
}
|
174 |
|
178 |
}
|
179 |
}
|
180 |
|
181 |
+
$ids = wp_list_pluck(
|
182 |
+
$wpdb->get_results(
|
183 |
+
$prepare
|
184 |
+
? $wpdb->prepare( $sql, $prepare )
|
185 |
+
: $sql,
|
186 |
+
ARRAY_A
|
187 |
+
),
|
188 |
+
'term_id'
|
189 |
+
);
|
190 |
|
191 |
+
return self::get_terms( $ids, array_keys($limits['taxonomy']), max( fw_akg( 'limit', $options, 100 ), 1 ) );
|
192 |
+
}
|
193 |
+
|
194 |
+
protected static function get_terms( $ids, $taxonomy = array(), $limit = 100 ) {
|
195 |
+
if ( empty( $ids ) ) {
|
196 |
+
return array();
|
197 |
+
}
|
198 |
+
|
199 |
+
$terms = get_terms( array(
|
200 |
+
'taxonomy' => $taxonomy,
|
201 |
+
'hide_empty' => false,
|
202 |
+
'include' => $ids,
|
203 |
+
'number' => $limit,
|
204 |
+
'fields' => 'ids'
|
205 |
+
) );
|
206 |
+
|
207 |
+
return is_wp_error( $terms ) ? array() : $terms;
|
208 |
+
}
|
209 |
+
|
210 |
+
protected static function build_term( $id, $show_type ) {
|
211 |
+
$term = get_term( $id );
|
212 |
+
|
213 |
+
if ( is_wp_error( $term ) ) {
|
214 |
+
return null;
|
215 |
+
}
|
216 |
+
|
217 |
+
$title = $term->name;
|
218 |
+
|
219 |
+
return $show_type ? array(
|
220 |
+
'val' => $id,
|
221 |
+
'title' => $title,
|
222 |
+
'type' => self::get_tax_name( $term->taxonomy ),
|
223 |
+
) : array(
|
224 |
+
'val' => $id,
|
225 |
+
'title' => $title
|
226 |
);
|
227 |
}
|
228 |
|
242 |
global $wpdb;
|
243 |
|
244 |
$sql = "SELECT DISTINCT users.ID AS val, users.user_nicename AS title"
|
245 |
+
." FROM $wpdb->users AS users, $wpdb->usermeta AS usermeta"
|
246 |
+
." WHERE usermeta.user_id = users.ID";
|
247 |
|
248 |
{
|
249 |
$prepare = array();
|
250 |
|
251 |
if ($limits['id']) {
|
252 |
$sql .= " AND users.ID IN ( "
|
253 |
+
. implode( ', ', array_fill( 1, count( $limits['id'] ), '%d' ) )
|
254 |
+
. " ) ";
|
255 |
$prepare = array_merge($prepare, $limits['id']);
|
256 |
}
|
257 |
|
258 |
if ($limits['role']) {
|
259 |
$sql .= " AND usermeta.meta_key = '{$wpdb->prefix}capabilities' "
|
260 |
+
. "AND ( "
|
261 |
+
. implode( ' OR ',
|
262 |
array_fill( 1, count( $limits['role'] ), 'usermeta.meta_value LIKE %s' ) ) .
|
263 |
+
" ) ";
|
264 |
|
265 |
foreach ( $limits['role'] as $name => $filter_by ) {
|
266 |
$prepare[] = ( $filter_by ) ? '%' . $wpdb->esc_like( $name ) . '%' : '';
|
294 |
$type = FW_Request::POST( 'data/type' );
|
295 |
$names = ($names = json_decode( FW_Request::POST( 'data/names' ), true )) ? $names : array();
|
296 |
$title = FW_Request::POST( 'data/string' );
|
297 |
+
$show = FW_Request::POST( 'data/show-type', false );
|
298 |
|
299 |
$items = array();
|
300 |
|
301 |
switch ( $type ) {
|
302 |
case 'posts':
|
303 |
+
$items = self::query_posts( array(
|
304 |
+
'type' => array_fill_keys( $names, true ),
|
305 |
'title' => $title,
|
306 |
+
) );
|
307 |
+
$items = array_map(
|
308 |
+
array( __CLASS__, 'build_post' ),
|
309 |
+
$items,
|
310 |
+
array_fill( 0, count($items), $show )
|
311 |
+
);
|
312 |
break;
|
313 |
case 'taxonomy':
|
314 |
$items = self::query_terms(array(
|
315 |
'taxonomy' => array_fill_keys($names, true),
|
316 |
'title' => $title,
|
317 |
));
|
318 |
+
|
319 |
+
$items = array_map(
|
320 |
+
array( __CLASS__, 'build_term' ),
|
321 |
+
$items,
|
322 |
+
array_fill( 1, count( $items ), $show )
|
323 |
+
);
|
324 |
break;
|
325 |
case 'users':
|
326 |
$items = self::query_users(array(
|
347 |
$population = $option['population'];
|
348 |
$source = array();
|
349 |
$items = array();
|
350 |
+
$show = fw_akg( 'show-type', $option, false );
|
351 |
|
352 |
if ( isset( $option['population'] ) ) {
|
353 |
switch ( $option['population'] ) {
|
364 |
case 'posts' :
|
365 |
if ( isset( $option['source'] ) ) {
|
366 |
$source = is_array( $option['source'] ) ? $option['source'] : array( $option['source'] );
|
367 |
+
|
368 |
+
$items = self::get_posts( $data['value'] );
|
369 |
+
|
370 |
+
if ( count( $items ) < $option['prepopulate'] ) {
|
371 |
+
foreach (
|
372 |
+
self::query_posts( array(
|
373 |
+
'type' => array_fill_keys( $source, true ),
|
374 |
+
'limit' => $option['prepopulate'],
|
375 |
+
) ) as $item
|
376 |
+
) {
|
377 |
+
if ( ! in_array( $item, $items ) ) {
|
378 |
+
array_push( $items, $item );
|
379 |
+
}
|
380 |
+
|
381 |
+
if ( count( $items ) == $option['prepopulate'] ) {
|
382 |
+
break;
|
383 |
+
}
|
384 |
+
}
|
385 |
+
}
|
386 |
}
|
387 |
+
$items = array_map(
|
388 |
+
array( $this, 'build_post' ),
|
389 |
+
$items,
|
390 |
+
array_fill( 1, count( $items ), $show )
|
391 |
+
);
|
392 |
break;
|
393 |
case 'taxonomy' :
|
394 |
if ( isset( $option['source'] ) ) {
|
395 |
$source = is_array( $option['source'] ) ? $option['source'] : array( $option['source'] );
|
396 |
+
|
397 |
+
$items = self::get_terms( $data['value'], $source );
|
398 |
+
|
399 |
+
if ( count( $items ) < $option['prepopulate'] ) {
|
400 |
+
foreach (
|
401 |
+
self::query_terms( array(
|
402 |
+
'taxonomy' => array_fill_keys( $source, true ),
|
403 |
+
'limit' => $option['prepopulate'],
|
404 |
+
) ) as $item
|
405 |
+
) {
|
406 |
+
if ( ! in_array( $item, $items ) ) {
|
407 |
+
array_push( $items, $item );
|
408 |
+
}
|
409 |
+
|
410 |
+
if ( count( $items ) == $option['prepopulate'] ) {
|
411 |
+
break;
|
412 |
+
}
|
413 |
+
}
|
414 |
+
}
|
415 |
}
|
416 |
+
|
417 |
+
$items = array_map(
|
418 |
+
array( $this, 'build_term' ),
|
419 |
+
$items,
|
420 |
+
array_fill( 1, count( $items ), $show )
|
421 |
+
);
|
422 |
break;
|
423 |
case 'users' :
|
424 |
if ( isset( $option['source'] ) && ! empty( $option['source'] ) ) {
|
437 |
return '(Invalid <code>population</code> parameter)';
|
438 |
}
|
439 |
|
440 |
+
$option['attr']['data-options'] = json_encode( $items );
|
441 |
+
$option['attr']['data-population'] = $population;
|
442 |
+
$option['attr']['data-show-type'] = (int)fw_akg( 'show-type', $option, false );
|
443 |
+
$option['attr']['data-source'] = json_encode( $source );
|
444 |
+
$option['attr']['data-limit'] = ( intval( $option['limit'] ) > 0 ) ? $option['limit'] : 0;
|
445 |
} else {
|
446 |
return '(The <code>population</code> parameter is required)';
|
447 |
}
|
489 |
|
490 |
return empty( $input_value ) ? array() : $value;
|
491 |
}
|
492 |
+
|
493 |
+
private static function get_post_type_name( $type ) {
|
494 |
+
static $names = array();
|
495 |
+
|
496 |
+
if ( ! isset( $names[ $type ] ) ) {
|
497 |
+
$names[$type]=fw_akg( 'labels/name', get_post_type_object( $type ), _x( 'Unknown', 'unknown-post-type', 'fw' ) );
|
498 |
+
}
|
499 |
+
|
500 |
+
return $names[ $type ];
|
501 |
+
}
|
502 |
+
|
503 |
+
private static function get_tax_name( $tax ) {
|
504 |
+
static $names = array();
|
505 |
+
|
506 |
+
if ( ! isset( $names[ $tax ] ) ) {
|
507 |
+
$names[$tax]=fw_akg( 'labels/name', get_taxonomy( $tax ), _x( 'Unknown', 'unknown-post-type', 'fw' ) );
|
508 |
+
}
|
509 |
+
|
510 |
+
return $names[ $tax ];
|
511 |
+
}
|
512 |
}
|
513 |
|
514 |
add_action( 'wp_ajax_fw_option_type_multi_select_autocomplete',
|
515 |
array( "FW_Option_Type_Multi_Select", '_ajax_autocomplete' ) );
|
516 |
+
endif;
|
framework/includes/option-types/multi-select/static/css/style.css
CHANGED
@@ -9,4 +9,23 @@
|
|
9 |
|
10 |
.fw-backend-option-input-type-multi-select .fw-option-help-in-input {
|
11 |
top: 4px !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
}
|
9 |
|
10 |
.fw-backend-option-input-type-multi-select .fw-option-help-in-input {
|
11 |
top: 4px !important;
|
12 |
+
}
|
13 |
+
|
14 |
+
.fw-backend-option-type-multi-select .selectize-control .selectize-dropdown .selectize-dropdown-content div > .type:before,
|
15 |
+
.fw-backend-option-type-multi-select .selectize-control .selectize-input > div > .type:before {
|
16 |
+
content: "(";
|
17 |
+
margin-right: 1px;
|
18 |
+
}
|
19 |
+
|
20 |
+
.fw-backend-option-type-multi-select .selectize-control .selectize-dropdown .selectize-dropdown-content div > .type:after,
|
21 |
+
.fw-backend-option-type-multi-select .selectize-control .selectize-input > div > .type:after {
|
22 |
+
content: ")";
|
23 |
+
margin-left: 1px;
|
24 |
+
}
|
25 |
+
|
26 |
+
.fw-backend-option-type-multi-select .selectize-control .selectize-dropdown .selectize-dropdown-content div > .type,
|
27 |
+
.fw-backend-option-type-multi-select .selectize-control .selectize-input > div > .type {
|
28 |
+
opacity: .5;
|
29 |
+
font-size: 80%;
|
30 |
+
margin-left: 5px;
|
31 |
}
|
framework/includes/option-types/multi-select/static/js/scripts.js
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
(function ($) {
|
2 |
var xhr,
|
3 |
optionsCache = {},
|
4 |
-
ajaxAutocompleteCallback = _.throttle(function(selectize, value, population, source, hash){
|
5 |
selectize.load(function(callback){
|
6 |
xhr && xhr.abort();
|
7 |
|
@@ -12,7 +12,8 @@
|
|
12 |
data: {
|
13 |
string: value,
|
14 |
type: population,
|
15 |
-
names: source
|
|
|
16 |
}
|
17 |
},
|
18 |
function (response) {
|
@@ -24,10 +25,10 @@
|
|
24 |
|
25 |
callback(response.data);
|
26 |
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
}
|
32 |
);
|
33 |
});
|
@@ -35,12 +36,12 @@
|
|
35 |
|
36 |
function init() {
|
37 |
var $this = $(this);
|
38 |
-
|
39 |
$this.one('fw:option-type:multi-select:init', function () {
|
40 |
var population = $this.attr('data-population'),
|
41 |
source = $this.attr('data-source'),
|
|
|
42 |
limit = parseInt($this.attr('data-limit')),
|
43 |
-
hash = fw.md5(JSON.stringify([population, source])),
|
44 |
options = (
|
45 |
typeof optionsCache[hash] == 'undefined'
|
46 |
? JSON.parse($this.attr('data-options'))
|
@@ -55,12 +56,24 @@
|
|
55 |
searchField: 'title',
|
56 |
options: options,
|
57 |
create: false,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
onType: function (value) {
|
59 |
if (population == 'array' || value.length < 2) {
|
60 |
return;
|
61 |
}
|
62 |
|
63 |
-
ajaxAutocompleteCallback(this, value, population, source, hash);
|
64 |
}
|
65 |
});
|
66 |
|
@@ -73,7 +86,7 @@
|
|
73 |
});
|
74 |
});
|
75 |
|
76 |
-
if ($this.val().length) { // there are values that needs to be show right away
|
77 |
$this.trigger('fw:option-type:multi-select:init');
|
78 |
} else {
|
79 |
$this.one('focus', function(){
|
1 |
(function ($) {
|
2 |
var xhr,
|
3 |
optionsCache = {},
|
4 |
+
ajaxAutocompleteCallback = _.throttle(function(selectize, value, population, source, show_type, hash){
|
5 |
selectize.load(function(callback){
|
6 |
xhr && xhr.abort();
|
7 |
|
12 |
data: {
|
13 |
string: value,
|
14 |
type: population,
|
15 |
+
names: source,
|
16 |
+
"show-type": show_type,
|
17 |
}
|
18 |
},
|
19 |
function (response) {
|
25 |
|
26 |
callback(response.data);
|
27 |
|
28 |
+
optionsCache[hash] = [] // transform object to array
|
29 |
+
$.each(selectize.options, function (i, o) {
|
30 |
+
optionsCache[hash].push(o)
|
31 |
+
})
|
32 |
}
|
33 |
);
|
34 |
});
|
36 |
|
37 |
function init() {
|
38 |
var $this = $(this);
|
|
|
39 |
$this.one('fw:option-type:multi-select:init', function () {
|
40 |
var population = $this.attr('data-population'),
|
41 |
source = $this.attr('data-source'),
|
42 |
+
show_type = !!parseInt($this.attr('data-show-type')),
|
43 |
limit = parseInt($this.attr('data-limit')),
|
44 |
+
hash = fw.md5(JSON.stringify([population, source, show_type])),
|
45 |
options = (
|
46 |
typeof optionsCache[hash] == 'undefined'
|
47 |
? JSON.parse($this.attr('data-options'))
|
56 |
searchField: 'title',
|
57 |
options: options,
|
58 |
create: false,
|
59 |
+
render: {
|
60 |
+
option: function (item) {
|
61 |
+
var title = '<span class="title">' + item.title + '</span>'
|
62 |
+
var type = item.type !== undefined ? '<span class="type">' + item.type + '</span>' : ''
|
63 |
+
return '<div>' + title + type + '</div>'
|
64 |
+
},
|
65 |
+
item: function (item) {
|
66 |
+
var title = '<span class="title">' + item.title + '</span>'
|
67 |
+
var type = item.type !== undefined ? '<span class="type">' + item.type + '</span>' : ''
|
68 |
+
return '<div>' + title + type + '</div>'
|
69 |
+
}
|
70 |
+
},
|
71 |
onType: function (value) {
|
72 |
if (population == 'array' || value.length < 2) {
|
73 |
return;
|
74 |
}
|
75 |
|
76 |
+
ajaxAutocompleteCallback(this, value, population, source, show_type, hash);
|
77 |
}
|
78 |
});
|
79 |
|
86 |
});
|
87 |
});
|
88 |
|
89 |
+
if ($this.val().length || $this.is(':focus')) { // there are values that needs to be show right away
|
90 |
$this.trigger('fw:option-type:multi-select:init');
|
91 |
} else {
|
92 |
$this.one('focus', function(){
|
framework/includes/option-types/multi-upload/class-fw-option-type-multi-upload.php
CHANGED
@@ -33,6 +33,10 @@ class FW_Option_Type_Multi_Upload extends FW_Option_Type
|
|
33 |
return 'auto';
|
34 |
}
|
35 |
|
|
|
|
|
|
|
|
|
36 |
/**
|
37 |
* @internal
|
38 |
*/
|
@@ -245,4 +249,4 @@ class FW_Option_Type_Multi_Upload extends FW_Option_Type
|
|
245 |
}
|
246 |
return $return_arr;
|
247 |
}
|
248 |
-
}
|
33 |
return 'auto';
|
34 |
}
|
35 |
|
36 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
37 |
+
return false;
|
38 |
+
}
|
39 |
+
|
40 |
/**
|
41 |
* @internal
|
42 |
*/
|
249 |
}
|
250 |
return $return_arr;
|
251 |
}
|
252 |
+
}
|
framework/includes/option-types/multi-upload/static/js/any-files.js
CHANGED
@@ -101,9 +101,12 @@
|
|
101 |
$element: elements.$container,
|
102 |
attachments: attachments
|
103 |
});
|
|
|
104 |
elements.$container.trigger('fw:option-type:multi-upload:change', {
|
105 |
attachments: attachments
|
106 |
});
|
|
|
|
|
107 |
});
|
108 |
};
|
109 |
|
@@ -125,6 +128,11 @@
|
|
125 |
fwe.trigger('fw:option-type:multi-upload:clear', {$element: elements.$container});
|
126 |
elements.$container.trigger('fw:option-type:multi-upload:clear');
|
127 |
|
|
|
|
|
|
|
|
|
|
|
128 |
e.preventDefault();
|
129 |
});
|
130 |
};
|
@@ -135,4 +143,18 @@
|
|
135 |
.addClass('fw-option-initialized');
|
136 |
});
|
137 |
|
138 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
101 |
$element: elements.$container,
|
102 |
attachments: attachments
|
103 |
});
|
104 |
+
|
105 |
elements.$container.trigger('fw:option-type:multi-upload:change', {
|
106 |
attachments: attachments
|
107 |
});
|
108 |
+
|
109 |
+
triggerChangeForIds(elements.$container, ids);
|
110 |
});
|
111 |
};
|
112 |
|
128 |
fwe.trigger('fw:option-type:multi-upload:clear', {$element: elements.$container});
|
129 |
elements.$container.trigger('fw:option-type:multi-upload:clear');
|
130 |
|
131 |
+
triggerChangeForIds(elements.$container, {
|
132 |
+
attachments: [],
|
133 |
+
value: {}
|
134 |
+
});
|
135 |
+
|
136 |
e.preventDefault();
|
137 |
});
|
138 |
};
|
143 |
.addClass('fw-option-initialized');
|
144 |
});
|
145 |
|
146 |
+
function triggerChangeForIds ($container, attachment_ids) {
|
147 |
+
fw.options.trigger.changeForEl($container, {
|
148 |
+
attachments: attachment_ids.map(wp.media.attachment),
|
149 |
+
value: attachment_ids.map(extractSingleAttachmentData)
|
150 |
+
});
|
151 |
+
|
152 |
+
function extractSingleAttachmentData (attachment_id) {
|
153 |
+
return {
|
154 |
+
attachment_id: attachment_id,
|
155 |
+
url: wp.media.attachment(attachment_id).get('url')
|
156 |
+
};
|
157 |
+
}
|
158 |
+
}
|
159 |
+
|
160 |
+
})(jQuery, fwEvents);
|
framework/includes/option-types/multi-upload/static/js/images-only.js
CHANGED
@@ -132,9 +132,12 @@
|
|
132 |
$element: elements.$container,
|
133 |
attachments: attachments
|
134 |
});
|
|
|
135 |
elements.$container.trigger('fw:option-type:multi-upload:change', {
|
136 |
attachments: attachments
|
137 |
});
|
|
|
|
|
138 |
});
|
139 |
};
|
140 |
|
@@ -170,6 +173,8 @@
|
|
170 |
elements.$container.trigger('fw:option-type:multi-upload:clear');
|
171 |
}
|
172 |
|
|
|
|
|
173 |
e.preventDefault();
|
174 |
});
|
175 |
|
@@ -178,6 +183,7 @@
|
|
178 |
update: function () {
|
179 |
var ids = collectThumbsIds();
|
180 |
elements.$input.val(JSON.stringify(ids));
|
|
|
181 |
}
|
182 |
});
|
183 |
};
|
@@ -188,4 +194,42 @@
|
|
188 |
.addClass('fw-option-initialized');
|
189 |
});
|
190 |
|
191 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
$element: elements.$container,
|
133 |
attachments: attachments
|
134 |
});
|
135 |
+
|
136 |
elements.$container.trigger('fw:option-type:multi-upload:change', {
|
137 |
attachments: attachments
|
138 |
});
|
139 |
+
|
140 |
+
triggerChangeForIds(elements.$container, ids);
|
141 |
});
|
142 |
};
|
143 |
|
173 |
elements.$container.trigger('fw:option-type:multi-upload:clear');
|
174 |
}
|
175 |
|
176 |
+
triggerChangeForIds(elements.$container, ids);
|
177 |
+
|
178 |
e.preventDefault();
|
179 |
});
|
180 |
|
183 |
update: function () {
|
184 |
var ids = collectThumbsIds();
|
185 |
elements.$input.val(JSON.stringify(ids));
|
186 |
+
triggerChangeForIds(elements.$container, ids);
|
187 |
}
|
188 |
});
|
189 |
};
|
194 |
.addClass('fw-option-initialized');
|
195 |
});
|
196 |
|
197 |
+
fw.options.register('multi-upload', {
|
198 |
+
startListeningForChanges: $.noop,
|
199 |
+
getValue: function (optionDescriptor) {
|
200 |
+
var ids = [];
|
201 |
+
|
202 |
+
$(optionDescriptor.el).find('.thumb').each(function () {
|
203 |
+
ids.push($(this).data('attid'));
|
204 |
+
});
|
205 |
+
|
206 |
+
var value = getValueForIds(ids);
|
207 |
+
value.optionDescriptor = optionDescriptor;
|
208 |
+
|
209 |
+
return value;
|
210 |
+
}
|
211 |
+
});
|
212 |
+
|
213 |
+
function getValueForIds (ids) {
|
214 |
+
return {
|
215 |
+
attachments: ids.map(wp.media.attachment),
|
216 |
+
value: ids.map(extractSingleAttachmentData)
|
217 |
+
};
|
218 |
+
|
219 |
+
function extractSingleAttachmentData (attachment_id) {
|
220 |
+
return {
|
221 |
+
attachment_id: attachment_id,
|
222 |
+
url: wp.media.attachment(attachment_id).get('url')
|
223 |
+
};
|
224 |
+
}
|
225 |
+
}
|
226 |
+
|
227 |
+
function triggerChangeForIds ($container, attachment_ids) {
|
228 |
+
fw.options.trigger.changeForEl(
|
229 |
+
$container,
|
230 |
+
getValueForIds(attachment_ids)
|
231 |
+
);
|
232 |
+
}
|
233 |
+
|
234 |
+
|
235 |
+
})(jQuery, _, fwEvents);
|
framework/includes/option-types/multi/class-fw-option-type-multi.php
CHANGED
@@ -54,6 +54,14 @@ class FW_Option_Type_Multi extends FW_Option_Type
|
|
54 |
'</div>';
|
55 |
}
|
56 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
/**
|
58 |
* @internal
|
59 |
*/
|
@@ -95,4 +103,4 @@ class FW_Option_Type_Multi extends FW_Option_Type
|
|
95 |
'value' => array(),
|
96 |
);
|
97 |
}
|
98 |
-
}
|
54 |
'</div>';
|
55 |
}
|
56 |
|
57 |
+
public function _get_data_for_js($id, $option, $data = array()) {
|
58 |
+
return false;
|
59 |
+
}
|
60 |
+
|
61 |
+
public function _default_label($id, $option) {
|
62 |
+
return false;
|
63 |
+
}
|
64 |
+
|
65 |
/**
|
66 |
* @internal
|
67 |
*/
|
103 |
'value' => array(),
|
104 |
);
|
105 |
}
|
106 |
+
}
|
framework/includes/option-types/popup/class-fw-option-type-popup.php
CHANGED
@@ -12,6 +12,10 @@ class FW_Option_Type_Popup extends FW_Option_Type {
|
|
12 |
return 'fixed';
|
13 |
}
|
14 |
|
|
|
|
|
|
|
|
|
15 |
/**
|
16 |
* @internal
|
17 |
* {@inheritdoc}
|
@@ -194,4 +198,4 @@ class FW_Option_Type_Popup extends FW_Option_Type {
|
|
194 |
);
|
195 |
}
|
196 |
|
197 |
-
}
|
12 |
return 'fixed';
|
13 |
}
|
14 |
|
15 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
16 |
+
return false;
|
17 |
+
}
|
18 |
+
|
19 |
/**
|
20 |
* @internal
|
21 |
* {@inheritdoc}
|
198 |
);
|
199 |
}
|
200 |
|
201 |
+
}
|
framework/includes/option-types/popup/static/js/popup.js
CHANGED
@@ -51,6 +51,10 @@
|
|
51 |
'change:values': function (modal, values) {
|
52 |
utils.editItem(utils.modal.get('itemRef'), values);
|
53 |
|
|
|
|
|
|
|
|
|
54 |
fwEvents.trigger('fw:option-type:popup:change', {
|
55 |
element: $this,
|
56 |
values: values
|
@@ -94,4 +98,17 @@
|
|
94 |
.find('.fw-option-type-popup:not(.fw-option-initialized)').each(popup)
|
95 |
.addClass('fw-option-initialized');
|
96 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
})(jQuery, _, fwEvents, window);
|
51 |
'change:values': function (modal, values) {
|
52 |
utils.editItem(utils.modal.get('itemRef'), values);
|
53 |
|
54 |
+
fw.options.trigger.changeForEl(utils.modal.get('itemRef'), {
|
55 |
+
value: values
|
56 |
+
});
|
57 |
+
|
58 |
fwEvents.trigger('fw:option-type:popup:change', {
|
59 |
element: $this,
|
60 |
values: values
|
98 |
.find('.fw-option-type-popup:not(.fw-option-initialized)').each(popup)
|
99 |
.addClass('fw-option-initialized');
|
100 |
});
|
101 |
+
|
102 |
+
fw.options.register('popup', {
|
103 |
+
startListeningForChanges: $.noop,
|
104 |
+
getValue: function (optionDescriptor) {
|
105 |
+
return {
|
106 |
+
value: JSON.parse(
|
107 |
+
$(optionDescriptor.el).find('[type="hidden"]').val()
|
108 |
+
),
|
109 |
+
|
110 |
+
optionDescriptor: optionDescriptor
|
111 |
+
}
|
112 |
+
}
|
113 |
+
});
|
114 |
})(jQuery, _, fwEvents, window);
|
framework/includes/option-types/range-slider/class-fw-option-type-range-slider.php
CHANGED
@@ -46,6 +46,10 @@ class FW_Option_Type_Range_Slider extends FW_Option_Type {
|
|
46 |
return 'range-slider';
|
47 |
}
|
48 |
|
|
|
|
|
|
|
|
|
49 |
/**
|
50 |
* @internal
|
51 |
*/
|
@@ -149,4 +153,4 @@ class FW_Option_Type_Range_Slider extends FW_Option_Type {
|
|
149 |
return $option;
|
150 |
}
|
151 |
|
152 |
-
}
|
46 |
return 'range-slider';
|
47 |
}
|
48 |
|
49 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
50 |
+
return false;
|
51 |
+
}
|
52 |
+
|
53 |
/**
|
54 |
* @internal
|
55 |
*/
|
153 |
return $option;
|
154 |
}
|
155 |
|
156 |
+
}
|
framework/includes/option-types/range-slider/static/js/scripts.js
CHANGED
@@ -7,7 +7,35 @@
|
|
7 |
data.$elements.find('.fw-option-type-range-slider:not(.initialized)').each(function () {
|
8 |
var options = JSON.parse($(this).attr('data-fw-irs-options'));
|
9 |
$(this).find('.fw-irs-range-slider').ionRangeSlider(_.defaults(options, defaults));
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
}).addClass('initialized');
|
11 |
});
|
12 |
|
13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
data.$elements.find('.fw-option-type-range-slider:not(.initialized)').each(function () {
|
8 |
var options = JSON.parse($(this).attr('data-fw-irs-options'));
|
9 |
$(this).find('.fw-irs-range-slider').ionRangeSlider(_.defaults(options, defaults));
|
10 |
+
|
11 |
+
$(this).find('.fw-irs-range-slider').on('change', _.throttle(function (e) {
|
12 |
+
fw.options.trigger.changeForEl(e.target, {
|
13 |
+
value: getValueForEl(e.target)
|
14 |
+
})
|
15 |
+
}, 300));
|
16 |
}).addClass('initialized');
|
17 |
});
|
18 |
|
19 |
+
fw.options.register('range-slider', {
|
20 |
+
startListeningForChanges: $.noop,
|
21 |
+
getValue: function (optionDescriptor) {
|
22 |
+
return {
|
23 |
+
value: getValueForEl(
|
24 |
+
$(optionDescriptor.el).find('[type="text"]')[0]
|
25 |
+
),
|
26 |
+
|
27 |
+
optionDescriptor: optionDescriptor
|
28 |
+
}
|
29 |
+
}
|
30 |
+
});
|
31 |
+
|
32 |
+
function getValueForEl (el) {
|
33 |
+
var rangeArray = el.value.split(';');
|
34 |
+
|
35 |
+
return {
|
36 |
+
from: rangeArray[0],
|
37 |
+
to: rangeArray[1]
|
38 |
+
}
|
39 |
+
}
|
40 |
+
|
41 |
+
})(jQuery, fwEvents);
|
framework/includes/option-types/rgba-color-picker/static/js/scripts.js
CHANGED
@@ -1,285 +1,266 @@
|
|
1 |
jQuery(function($){
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
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 |
-
.on('remove', function(){
|
267 |
-
$(document.body).off(eventNamespace);
|
268 |
-
})
|
269 |
-
.addClass(helpers.optionClass + '-with-reset-default')
|
270 |
-
.css('height', parseFloat($picker.css('height')) + 17);
|
271 |
-
|
272 |
-
return false;
|
273 |
-
}
|
274 |
-
});
|
275 |
-
|
276 |
-
$input.iris('show');
|
277 |
-
});
|
278 |
-
|
279 |
-
helpers.updatePreview($input, $input.val());
|
280 |
-
|
281 |
-
$input.addClass('initialized');
|
282 |
-
});
|
283 |
-
});
|
284 |
|
285 |
});
|
1 |
jQuery(function($){
|
2 |
+
Color.prototype.toStr = function (remove_alpha) {
|
3 |
+
if (remove_alpha == 'no-alpha') {
|
4 |
+
return this.toRgbaCSS(1).replace(/\s+/g, '');
|
5 |
+
}
|
6 |
+
|
7 |
+
return this.toRgbaCSS(this._alpha).replace(/\s+/g, '');
|
8 |
+
};
|
9 |
+
Color.prototype.toRgba = function (a) {
|
10 |
+
var rgb = this.toRgb();
|
11 |
+
rgb['a'] = a || 1
|
12 |
+
return rgb;
|
13 |
+
}
|
14 |
+
Color.prototype.toRgbaCSS = function (a) {
|
15 |
+
var rgba = this.toRgba(a);
|
16 |
+
return 'rgba(' + rgba.r + ',' + rgba.g + ',' + rgba.b + ',' + rgba.a +')';
|
17 |
+
}
|
18 |
+
|
19 |
+
var helpers = {
|
20 |
+
optionClass: 'fw-option-type-rgba-color-picker',
|
21 |
+
eventNamespace: '.fwOptionTypeRgbaColorPicker',
|
22 |
+
hexColorRegex: /^#([a-f0-9]{3}){1,2}$/i,
|
23 |
+
localized: window._fw_option_type_rgba_color_picker_localized,
|
24 |
+
increment: 0,
|
25 |
+
isColorDark: function(rgbaColor) {
|
26 |
+
var r, g, b, o = 1;
|
27 |
+
|
28 |
+
if (this.hexColorRegex.test(rgbaColor)) {
|
29 |
+
var color = rgbaColor.substring(1); // remove #
|
30 |
+
|
31 |
+
r = parseInt(color.substr(0,2),16);
|
32 |
+
g = parseInt(color.substr(2,2),16);
|
33 |
+
b = parseInt(color.substr(4,2),16);
|
34 |
+
} else {
|
35 |
+
var rgba = rgbaColor
|
36 |
+
.replace(/^(rgb|rgba)\(/, '')
|
37 |
+
.replace(/\)$/, '')
|
38 |
+
.replace(/\s/g, '')
|
39 |
+
.split(',');
|
40 |
+
|
41 |
+
r = rgba[0];
|
42 |
+
g = rgba[1];
|
43 |
+
b = rgba[2];
|
44 |
+
o = rgba[3] || 1;
|
45 |
+
}
|
46 |
+
|
47 |
+
var yiq = ((r*299)+(g*587)+(b*114))/1000;
|
48 |
+
|
49 |
+
return yiq < 128 && o > 0.4;
|
50 |
+
},
|
51 |
+
isColorValid: function(rgbaColor) {
|
52 |
+
return !Color(rgbaColor).error;
|
53 |
+
},
|
54 |
+
getInstance: function ($iris) {
|
55 |
+
return $iris.data('a8cIris');
|
56 |
+
},
|
57 |
+
updatePreview: function ($input, color) {
|
58 |
+
if (this.isColorValid(color)) {
|
59 |
+
$input.css({
|
60 |
+
'background-color': color,
|
61 |
+
'color': this.isColorDark(color) ? 'rgb(255,255,255)' : 'rgb(0,0,0)'
|
62 |
+
});
|
63 |
+
} else {
|
64 |
+
$input.css({
|
65 |
+
'background-color': '',
|
66 |
+
'color': ''
|
67 |
+
});
|
68 |
+
}
|
69 |
+
}
|
70 |
+
};
|
71 |
+
|
72 |
+
Color.prototype.toRgba()
|
73 |
+
|
74 |
+
fwEvents.on('fw:options:init', function (data) {
|
75 |
+
data.$elements.find('input.'+ helpers.optionClass +':not(.initialized)').each(function () {
|
76 |
+
var $input = $(this),
|
77 |
+
changeTimeoutId = 0,
|
78 |
+
eventNamespace = helpers.eventNamespace +'_'+ (++helpers.increment);
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Improvement: Initialized picker only on first focus
|
82 |
+
* Do not initialize all pickers on the page, for performance reasons, maybe none of them will be opened
|
83 |
+
*/
|
84 |
+
$input.one('focus', function(){
|
85 |
+
if (!$.trim($input.val()).length) { // If the input value is empty, there a glitches with opacity slider
|
86 |
+
$input.val('rgba(255,255,255,1)');
|
87 |
+
}
|
88 |
+
$input.iris({
|
89 |
+
palettes: JSON.parse($input.attr('data-palettes')),
|
90 |
+
defaultColor: false,
|
91 |
+
create: function () {
|
92 |
+
$(this).val(Color($(this).val()).toStr())
|
93 |
+
},
|
94 |
+
change: function (event, ui) {
|
95 |
+
var $transparency = $input.next('.iris-picker').find('.transparency');
|
96 |
+
$transparency.css('backgroundColor', ui.color.toStr('no-alpha'));
|
97 |
+
|
98 |
+
$alphaSlider.slider("option", "value", ui.color._alpha * 100);
|
99 |
+
|
100 |
+
clearTimeout(changeTimeoutId);
|
101 |
+
changeTimeoutId = setTimeout(function(){
|
102 |
+
$input.trigger('fw:option-type:rgba-color-picker:change', {
|
103 |
+
$element: $input,
|
104 |
+
iris: $input.data('a8cIris'),
|
105 |
+
alphaSlider: $alphaSlider.data('uiSlider')
|
106 |
+
});
|
107 |
+
$input.trigger('change');
|
108 |
+
}, 12);
|
109 |
+
}
|
110 |
+
});
|
111 |
+
|
112 |
+
var $picker = helpers.getInstance($input).picker;
|
113 |
+
|
114 |
+
$picker.addClass(helpers.optionClass +'-iris');
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Hide if clicked outside option
|
118 |
+
*/
|
119 |
+
{
|
120 |
+
$input.parent().attr('id', 'fw-rgba-color-picker-r-'+ (++helpers.increment));
|
121 |
+
|
122 |
+
var originalShowCallback = helpers.getInstance($input).show;
|
123 |
+
|
124 |
+
helpers.getInstance($input).show = function () {
|
125 |
+
$(document.body)
|
126 |
+
.off('click'+ eventNamespace)
|
127 |
+
.on('click'+ eventNamespace, function(e){
|
128 |
+
if (!$(e.target).closest('#'+ $input.parent().attr('id')).length) {
|
129 |
+
$(document.body).off('click'+ eventNamespace);
|
130 |
+
$input.iris('hide');
|
131 |
+
}
|
132 |
+
});
|
133 |
+
|
134 |
+
originalShowCallback.apply(this);
|
135 |
+
};
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* After the second hide the picker is not showing on the next focus (I don't know why)
|
140 |
+
* Show it manually
|
141 |
+
*/
|
142 |
+
$input.on('focus', function(){
|
143 |
+
if (!$picker.is(':visible')) {
|
144 |
+
$input.iris('show');
|
145 |
+
}
|
146 |
+
});
|
147 |
+
|
148 |
+
$input.on('change keyup blur', function () {
|
149 |
+
// iris::change is not triggered when the input is empty or color is wrong
|
150 |
+
$(this).val(Color($(this).val()).toStr())
|
151 |
+
helpers.updatePreview($input, $input.val());
|
152 |
+
});
|
153 |
+
|
154 |
+
$(''
|
155 |
+
+ '<div class="fw-alpha-container">'
|
156 |
+
+ /**/'<div class="slider-alpha"></div>'
|
157 |
+
+ /**/'<div class="transparency"></div>'
|
158 |
+
+ '</div>'
|
159 |
+
).appendTo($input.next('.iris-picker'));
|
160 |
+
|
161 |
+
var $alphaSlider = $input.next('.iris-picker:first').find('.slider-alpha');
|
162 |
+
|
163 |
+
$alphaSlider.slider({
|
164 |
+
value: Color($input.val())._alpha * 100,
|
165 |
+
range: "max",
|
166 |
+
step: 1,
|
167 |
+
min: 0,
|
168 |
+
max: 100,
|
169 |
+
slide: function (event, ui) {
|
170 |
+
$(this).find('.ui-slider-handle').text(ui.value);
|
171 |
+
|
172 |
+
$input.data('a8cIris')._color._alpha = parseFloat(ui.value) / 100.0;
|
173 |
+
|
174 |
+
var color = $input.iris('color', true)
|
175 |
+
var cssColor = color.toCSS('rgba', ui.value / 100)
|
176 |
+
|
177 |
+
$input.val(cssColor);
|
178 |
+
|
179 |
+
clearTimeout(changeTimeoutId);
|
180 |
+
changeTimeoutId = setTimeout(function(){
|
181 |
+
$input.trigger('fw:option-type:rgba-color-picker:change', {
|
182 |
+
$element: $input,
|
183 |
+
iris: $input.data('a8cIris'),
|
184 |
+
alphaSlider: $alphaSlider.data('uiSlider')
|
185 |
+
});
|
186 |
+
$input.trigger('change');
|
187 |
+
}, 12);
|
188 |
+
},
|
189 |
+
create: function (event, ui) {
|
190 |
+
var v = $(this).slider('value'),
|
191 |
+
$transparency = $input.next('.iris-picker:first').find('.transparency');
|
192 |
+
|
193 |
+
$(this).find('.ui-slider-handle').text(v);
|
194 |
+
|
195 |
+
$transparency.css('backgroundColor', Color($input.val()).toRgbaCSS(1));
|
196 |
+
},
|
197 |
+
change: function (event, ui) {
|
198 |
+
$(this).find('.ui-slider-handle').text(ui.value);
|
199 |
+
|
200 |
+
$input.data('a8cIris')._color._alpha = parseFloat(ui.value) / 100.0;
|
201 |
+
$input.val($input.iris('color', true).toRgbaCSS(ui.value / 100))
|
202 |
+
|
203 |
+
clearTimeout(changeTimeoutId);
|
204 |
+
changeTimeoutId = setTimeout(function(){
|
205 |
+
$input.trigger('fw:option-type:rgba-color-picker:change', {
|
206 |
+
$element: $input,
|
207 |
+
iris: $input.data('a8cIris'),
|
208 |
+
alphaSlider: $alphaSlider.data('uiSlider')
|
209 |
+
});
|
210 |
+
$input.trigger('change');
|
211 |
+
}, 12);
|
212 |
+
}
|
213 |
+
});
|
214 |
+
|
215 |
+
var $firstPalette = $picker.find('.iris-palette-container > .iris-palette:first-child');
|
216 |
+
|
217 |
+
/**
|
218 |
+
* "Reset" color button
|
219 |
+
*/
|
220 |
+
$.each([{
|
221 |
+
color: $input.attr('data-default'),
|
222 |
+
text: helpers.localized.l10n.reset_to_default
|
223 |
+
},{
|
224 |
+
color: $input.val(),
|
225 |
+
text: helpers.localized.l10n.reset_to_initial
|
226 |
+
}], function(i, data){
|
227 |
+
if (data.color && helpers.isColorValid(data.color)) {
|
228 |
+
$picker.find('> .iris-picker-inner').append(''
|
229 |
+
+ '<div class="' + helpers.optionClass + '-reset-default fw-pull-left">'
|
230 |
+
+ /**/'<a class="iris-palette" style="'
|
231 |
+
+ /**//**/'background-color:'+ data.color +';'
|
232 |
+
+ /**//**/'height:' + $firstPalette.css('height') + ';'
|
233 |
+
+ /**//**/'width:' + $firstPalette.css('width') + ';'
|
234 |
+
+ /**//**/'"></a>'
|
235 |
+
+ /**/'<span>' + data.text + '</span>'
|
236 |
+
+ '</div>'
|
237 |
+
);
|
238 |
+
|
239 |
+
$picker
|
240 |
+
.on(
|
241 |
+
'click',
|
242 |
+
'.' + helpers.optionClass + '-reset-default',
|
243 |
+
function(){
|
244 |
+
$input.iris('color', $(this).find('.iris-palette').css('background-color'));
|
245 |
+
}
|
246 |
+
)
|
247 |
+
.on('remove', function(){
|
248 |
+
$(document.body).off(eventNamespace);
|
249 |
+
})
|
250 |
+
.addClass(helpers.optionClass + '-with-reset-default')
|
251 |
+
.css('height', parseFloat($picker.css('height')) + 17);
|
252 |
+
|
253 |
+
return false;
|
254 |
+
}
|
255 |
+
});
|
256 |
+
|
257 |
+
$input.iris('show');
|
258 |
+
});
|
259 |
+
|
260 |
+
helpers.updatePreview($input, $input.val());
|
261 |
+
|
262 |
+
$input.addClass('initialized');
|
263 |
+
});
|
264 |
+
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
265 |
|
266 |
});
|
framework/includes/option-types/simple.php
CHANGED
@@ -12,6 +12,10 @@ class FW_Option_Type_Hidden extends FW_Option_Type {
|
|
12 |
return 'hidden';
|
13 |
}
|
14 |
|
|
|
|
|
|
|
|
|
15 |
/**
|
16 |
* @internal
|
17 |
* {@inheritdoc}
|
@@ -75,6 +79,10 @@ class FW_Option_Type_Text extends FW_Option_Type {
|
|
75 |
protected function _enqueue_static( $id, $option, $data ) {
|
76 |
}
|
77 |
|
|
|
|
|
|
|
|
|
78 |
/**
|
79 |
* @param string $id
|
80 |
* @param array $option
|
@@ -117,6 +125,10 @@ class FW_Option_Type_Short_Text extends FW_Option_Type_Text {
|
|
117 |
return 'short-text';
|
118 |
}
|
119 |
|
|
|
|
|
|
|
|
|
120 |
/**
|
121 |
* @param string $id
|
122 |
* @param array $option
|
@@ -153,6 +165,10 @@ class FW_Option_Type_Password extends FW_Option_Type {
|
|
153 |
protected function _enqueue_static( $id, $option, $data ) {
|
154 |
}
|
155 |
|
|
|
|
|
|
|
|
|
156 |
/**
|
157 |
* @param string $id
|
158 |
* @param array $option
|
@@ -202,6 +218,10 @@ class FW_Option_Type_Textarea extends FW_Option_Type {
|
|
202 |
protected function _enqueue_static( $id, $option, $data ) {
|
203 |
}
|
204 |
|
|
|
|
|
|
|
|
|
205 |
/**
|
206 |
* @param string $id
|
207 |
* @param array $option
|
@@ -258,6 +278,10 @@ class FW_Option_Type_Html extends FW_Option_Type {
|
|
258 |
protected function _enqueue_static( $id, $option, $data ) {
|
259 |
}
|
260 |
|
|
|
|
|
|
|
|
|
261 |
/**
|
262 |
* @param string $id
|
263 |
* @param array $option
|
@@ -365,6 +389,10 @@ class FW_Option_Type_Checkbox extends FW_Option_Type {
|
|
365 |
protected function _enqueue_static( $id, $option, $data ) {
|
366 |
}
|
367 |
|
|
|
|
|
|
|
|
|
368 |
/**
|
369 |
* @param string $id
|
370 |
* @param array $option
|
@@ -456,6 +484,10 @@ class FW_Option_Type_Checkboxes extends FW_Option_Type {
|
|
456 |
protected function _enqueue_static( $id, $option, $data ) {
|
457 |
}
|
458 |
|
|
|
|
|
|
|
|
|
459 |
/**
|
460 |
* @param string $id
|
461 |
* @param array $option
|
@@ -496,6 +528,7 @@ class FW_Option_Type_Checkboxes extends FW_Option_Type {
|
|
496 |
'name' => $option['attr']['name'] . '[' . $value . ']',
|
497 |
'value' => 'true',
|
498 |
'id' => $option['attr']['id'] . '-' . $value,
|
|
|
499 |
),
|
500 |
isset( $option['value'][ $value ] ) && $option['value'][ $value ]
|
501 |
? array('checked' => 'checked') : array()
|
@@ -586,6 +619,10 @@ class FW_Option_Type_Radio extends FW_Option_Type {
|
|
586 |
protected function _enqueue_static( $id, $option, $data ) {
|
587 |
}
|
588 |
|
|
|
|
|
|
|
|
|
589 |
/**
|
590 |
* @param string $id
|
591 |
* @param array $option
|
@@ -704,6 +741,10 @@ class FW_Option_Type_Select extends FW_Option_Type {
|
|
704 |
protected function _enqueue_static( $id, $option, $data ) {
|
705 |
}
|
706 |
|
|
|
|
|
|
|
|
|
707 |
/**
|
708 |
* @param string $id
|
709 |
* @param array $option
|
@@ -995,8 +1036,7 @@ class FW_Option_Type_Select_Multiple extends FW_Option_Type_Select {
|
|
995 |
}
|
996 |
}
|
997 |
|
998 |
-
class FW_Option_Type_Unique extends FW_Option_Type
|
999 |
-
{
|
1000 |
private static $ids = array();
|
1001 |
private static $should_do_regeneration = true;
|
1002 |
|
@@ -1005,6 +1045,10 @@ class FW_Option_Type_Unique extends FW_Option_Type
|
|
1005 |
return 'unique';
|
1006 |
}
|
1007 |
|
|
|
|
|
|
|
|
|
1008 |
protected function _get_defaults()
|
1009 |
{
|
1010 |
return array(
|
@@ -1205,4 +1249,4 @@ class FW_Option_Type_GMap_Key extends FW_Option_Type_Text {
|
|
1205 |
}
|
1206 |
return parent::_storage_save( $id, $option, $value, $params );
|
1207 |
}
|
1208 |
-
}
|
12 |
return 'hidden';
|
13 |
}
|
14 |
|
15 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
16 |
+
return false;
|
17 |
+
}
|
18 |
+
|
19 |
/**
|
20 |
* @internal
|
21 |
* {@inheritdoc}
|
79 |
protected function _enqueue_static( $id, $option, $data ) {
|
80 |
}
|
81 |
|
82 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
83 |
+
return false;
|
84 |
+
}
|
85 |
+
|
86 |
/**
|
87 |
* @param string $id
|
88 |
* @param array $option
|
125 |
return 'short-text';
|
126 |
}
|
127 |
|
128 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
129 |
+
return false;
|
130 |
+
}
|
131 |
+
|
132 |
/**
|
133 |
* @param string $id
|
134 |
* @param array $option
|
165 |
protected function _enqueue_static( $id, $option, $data ) {
|
166 |
}
|
167 |
|
168 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
169 |
+
return false;
|
170 |
+
}
|
171 |
+
|
172 |
/**
|
173 |
* @param string $id
|
174 |
* @param array $option
|
218 |
protected function _enqueue_static( $id, $option, $data ) {
|
219 |
}
|
220 |
|
221 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
222 |
+
return false;
|
223 |
+
}
|
224 |
+
|
225 |
/**
|
226 |
* @param string $id
|
227 |
* @param array $option
|
278 |
protected function _enqueue_static( $id, $option, $data ) {
|
279 |
}
|
280 |
|
281 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
282 |
+
return false;
|
283 |
+
}
|
284 |
+
|
285 |
/**
|
286 |
* @param string $id
|
287 |
* @param array $option
|
389 |
protected function _enqueue_static( $id, $option, $data ) {
|
390 |
}
|
391 |
|
392 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
393 |
+
return false;
|
394 |
+
}
|
395 |
+
|
396 |
/**
|
397 |
* @param string $id
|
398 |
* @param array $option
|
484 |
protected function _enqueue_static( $id, $option, $data ) {
|
485 |
}
|
486 |
|
487 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
488 |
+
return false;
|
489 |
+
}
|
490 |
+
|
491 |
/**
|
492 |
* @param string $id
|
493 |
* @param array $option
|
528 |
'name' => $option['attr']['name'] . '[' . $value . ']',
|
529 |
'value' => 'true',
|
530 |
'id' => $option['attr']['id'] . '-' . $value,
|
531 |
+
'data-fw-checkbox-id' => $value
|
532 |
),
|
533 |
isset( $option['value'][ $value ] ) && $option['value'][ $value ]
|
534 |
? array('checked' => 'checked') : array()
|
619 |
protected function _enqueue_static( $id, $option, $data ) {
|
620 |
}
|
621 |
|
622 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
623 |
+
return false;
|
624 |
+
}
|
625 |
+
|
626 |
/**
|
627 |
* @param string $id
|
628 |
* @param array $option
|
741 |
protected function _enqueue_static( $id, $option, $data ) {
|
742 |
}
|
743 |
|
744 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
745 |
+
return false;
|
746 |
+
}
|
747 |
+
|
748 |
/**
|
749 |
* @param string $id
|
750 |
* @param array $option
|
1036 |
}
|
1037 |
}
|
1038 |
|
1039 |
+
class FW_Option_Type_Unique extends FW_Option_Type {
|
|
|
1040 |
private static $ids = array();
|
1041 |
private static $should_do_regeneration = true;
|
1042 |
|
1045 |
return 'unique';
|
1046 |
}
|
1047 |
|
1048 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
1049 |
+
return false;
|
1050 |
+
}
|
1051 |
+
|
1052 |
protected function _get_defaults()
|
1053 |
{
|
1054 |
return array(
|
1249 |
}
|
1250 |
return parent::_storage_save( $id, $option, $value, $params );
|
1251 |
}
|
1252 |
+
}
|
framework/includes/option-types/slider/class-fw-option-type-slider.php
CHANGED
@@ -17,6 +17,10 @@ class FW_Option_Type_Slider extends FW_Option_Type {
|
|
17 |
return 'slider';
|
18 |
}
|
19 |
|
|
|
|
|
|
|
|
|
20 |
/**
|
21 |
* @internal
|
22 |
* {@inheritdoc}
|
@@ -111,4 +115,4 @@ class FW_Option_Type_Slider extends FW_Option_Type {
|
|
111 |
}
|
112 |
}
|
113 |
|
114 |
-
}
|
17 |
return 'slider';
|
18 |
}
|
19 |
|
20 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
21 |
+
return false;
|
22 |
+
}
|
23 |
+
|
24 |
/**
|
25 |
* @internal
|
26 |
* {@inheritdoc}
|
115 |
}
|
116 |
}
|
117 |
|
118 |
+
}
|
framework/includes/option-types/slider/static/js/scripts.js
CHANGED
@@ -10,4 +10,4 @@
|
|
10 |
}).addClass('initialized');
|
11 |
});
|
12 |
|
13 |
-
})(jQuery, fwEvents);
|
10 |
}).addClass('initialized');
|
11 |
});
|
12 |
|
13 |
+
})(jQuery, fwEvents);
|
framework/includes/option-types/switch/class-fw-option-type-switch.php
CHANGED
@@ -12,6 +12,10 @@ class FW_Option_Type_Switch extends FW_Option_Type
|
|
12 |
return 'switch';
|
13 |
}
|
14 |
|
|
|
|
|
|
|
|
|
15 |
/**
|
16 |
* @internal
|
17 |
* {@inheritdoc}
|
@@ -101,6 +105,7 @@ class FW_Option_Type_Switch extends FW_Option_Type
|
|
101 |
|
102 |
return '<div '. fw_attr_to_html($option['attr']) .'>'.
|
103 |
'<!-- note: value is json encoded, if want to use it in js, do: var val = JSON.parse($input.val()); -->'.
|
|
|
104 |
($checked ? '' : fw_html_tag('input', array(
|
105 |
'type' => 'hidden',
|
106 |
'name' => $input_attr['name'],
|
@@ -167,4 +172,4 @@ class FW_Option_Type_Switch extends FW_Option_Type
|
|
167 |
),
|
168 |
);
|
169 |
}
|
170 |
-
}
|
12 |
return 'switch';
|
13 |
}
|
14 |
|
15 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
16 |
+
return false;
|
17 |
+
}
|
18 |
+
|
19 |
/**
|
20 |
* @internal
|
21 |
* {@inheritdoc}
|
105 |
|
106 |
return '<div '. fw_attr_to_html($option['attr']) .'>'.
|
107 |
'<!-- note: value is json encoded, if want to use it in js, do: var val = JSON.parse($input.val()); -->'.
|
108 |
+
'<!-- deprecated: use reactive options for extracting the current value of the switch -->'.
|
109 |
($checked ? '' : fw_html_tag('input', array(
|
110 |
'type' => 'hidden',
|
111 |
'name' => $input_attr['name'],
|
172 |
),
|
173 |
);
|
174 |
}
|
175 |
+
}
|
framework/includes/option-types/switch/static/js/scripts.js
CHANGED
@@ -29,6 +29,10 @@ jQuery(document).ready(function ($) {
|
|
29 |
$this.closest('.'+ optionTypeClass).trigger(customEventPrefix +'change', {
|
30 |
value: JSON.parse(value)
|
31 |
});
|
|
|
|
|
|
|
|
|
32 |
})
|
33 |
.on('change update:color', function(){
|
34 |
var $this = $(this),
|
@@ -42,4 +46,16 @@ jQuery(document).ready(function ($) {
|
|
42 |
.adaptiveSwitch()
|
43 |
.trigger('update:color');
|
44 |
});
|
45 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
$this.closest('.'+ optionTypeClass).trigger(customEventPrefix +'change', {
|
30 |
value: JSON.parse(value)
|
31 |
});
|
32 |
+
|
33 |
+
fw.options.trigger.changeForEl(
|
34 |
+
$this.closest('.' + optionTypeClass)
|
35 |
+
);
|
36 |
})
|
37 |
.on('change update:color', function(){
|
38 |
var $this = $(this),
|
46 |
.adaptiveSwitch()
|
47 |
.trigger('update:color');
|
48 |
});
|
49 |
+
|
50 |
+
fw.options.register('switch', {
|
51 |
+
startListeningForChanges: $.noop,
|
52 |
+
getValue: function (optionDescriptor) {
|
53 |
+
return {
|
54 |
+
value: JSON.parse(
|
55 |
+
$(optionDescriptor.el).find('[type="checkbox"]').val()
|
56 |
+
),
|
57 |
+
optionDescriptor: optionDescriptor
|
58 |
+
}
|
59 |
+
}
|
60 |
+
})
|
61 |
+
});
|
framework/includes/option-types/typography-v2/class-fw-option-type-typography-v2.php
CHANGED
@@ -71,7 +71,10 @@ class FW_Option_Type_Typography_v2 extends FW_Option_Type {
|
|
71 |
"Impact",
|
72 |
"Serif"
|
73 |
) ),
|
74 |
-
'google' =>
|
|
|
|
|
|
|
75 |
);
|
76 |
|
77 |
FW_Cache::set($cache_key, $fonts);
|
71 |
"Impact",
|
72 |
"Serif"
|
73 |
) ),
|
74 |
+
'google' => apply_filters(
|
75 |
+
'fw_option_type_typography_v2_google_fonts',
|
76 |
+
json_decode( fw_get_google_fonts_v2(), true )
|
77 |
+
)
|
78 |
);
|
79 |
|
80 |
FW_Cache::set($cache_key, $fonts);
|
framework/includes/option-types/upload/class-fw-option-type-upload.php
CHANGED
@@ -25,6 +25,10 @@ class FW_Option_Type_Upload extends FW_Option_Type
|
|
25 |
);
|
26 |
}
|
27 |
|
|
|
|
|
|
|
|
|
28 |
/**
|
29 |
* @internal
|
30 |
*/
|
@@ -230,4 +234,4 @@ class FW_Option_Type_Upload extends FW_Option_Type
|
|
230 |
return $defaults['value'];
|
231 |
}
|
232 |
}
|
233 |
-
}
|
25 |
);
|
26 |
}
|
27 |
|
28 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
29 |
+
return false;
|
30 |
+
}
|
31 |
+
|
32 |
/**
|
33 |
* @internal
|
34 |
*/
|
234 |
return $defaults['value'];
|
235 |
}
|
236 |
}
|
237 |
+
}
|
framework/includes/option-types/upload/static/js/any-files.js
CHANGED
@@ -73,9 +73,11 @@
|
|
73 |
|
74 |
frame.on('select', function() {
|
75 |
var attachment = frame.state().get('selection').first();
|
|
|
76 |
elements.$input
|
77 |
.val(attachment.id)
|
78 |
.trigger('change'); // trigger Customizer update
|
|
|
79 |
performSelection(attachment);
|
80 |
});
|
81 |
};
|
@@ -124,6 +126,14 @@
|
|
124 |
|
125 |
fwe.trigger('fw:option-type:upload:clear', {$element: elements.$container});
|
126 |
elements.$container.trigger('fw:option-type:upload:clear');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
127 |
}
|
128 |
|
129 |
function performSelection (attachment) {
|
@@ -140,6 +150,13 @@
|
|
140 |
elements.$container.trigger('fw:option-type:upload:change', {
|
141 |
attachment: attachment
|
142 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
143 |
}
|
144 |
};
|
145 |
|
73 |
|
74 |
frame.on('select', function() {
|
75 |
var attachment = frame.state().get('selection').first();
|
76 |
+
|
77 |
elements.$input
|
78 |
.val(attachment.id)
|
79 |
.trigger('change'); // trigger Customizer update
|
80 |
+
|
81 |
performSelection(attachment);
|
82 |
});
|
83 |
};
|
126 |
|
127 |
fwe.trigger('fw:option-type:upload:clear', {$element: elements.$container});
|
128 |
elements.$container.trigger('fw:option-type:upload:clear');
|
129 |
+
|
130 |
+
fw.options.trigger.changeForEl(elements.$container, {
|
131 |
+
value: {}
|
132 |
+
});
|
133 |
+
|
134 |
+
fw.options.trigger.scopedByType('clear', elements.$container, {
|
135 |
+
value: {}
|
136 |
+
});
|
137 |
}
|
138 |
|
139 |
function performSelection (attachment) {
|
150 |
elements.$container.trigger('fw:option-type:upload:change', {
|
151 |
attachment: attachment
|
152 |
});
|
153 |
+
|
154 |
+
fw.options.trigger.changeForEl(elements.$container, {
|
155 |
+
value: {
|
156 |
+
attachment_id: attachment.get('id'),
|
157 |
+
url: attachment.get('url')
|
158 |
+
}
|
159 |
+
});
|
160 |
}
|
161 |
};
|
162 |
|
framework/includes/option-types/upload/static/js/images-only.js
CHANGED
@@ -143,6 +143,14 @@
|
|
143 |
|
144 |
fwe.trigger('fw:option-type:upload:clear', {$element: elements.$container});
|
145 |
elements.$container.trigger('fw:option-type:upload:clear');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
146 |
}
|
147 |
|
148 |
function performSelection (attachment) {
|
@@ -186,6 +194,13 @@
|
|
186 |
elements.$container.trigger('fw:option-type:upload:change', {
|
187 |
attachment: attachment
|
188 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
189 |
}
|
190 |
};
|
191 |
|
@@ -195,4 +210,43 @@
|
|
195 |
.addClass('fw-option-initialized');
|
196 |
});
|
197 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
198 |
})(jQuery, _, fwEvents);
|
143 |
|
144 |
fwe.trigger('fw:option-type:upload:clear', {$element: elements.$container});
|
145 |
elements.$container.trigger('fw:option-type:upload:clear');
|
146 |
+
|
147 |
+
fw.options.trigger.changeForEl(elements.$container, {
|
148 |
+
value: {}
|
149 |
+
});
|
150 |
+
|
151 |
+
fw.options.trigger.scopedByType('clear', elements.$container, {
|
152 |
+
value: {}
|
153 |
+
});
|
154 |
}
|
155 |
|
156 |
function performSelection (attachment) {
|
194 |
elements.$container.trigger('fw:option-type:upload:change', {
|
195 |
attachment: attachment
|
196 |
});
|
197 |
+
|
198 |
+
fw.options.trigger.changeForEl(elements.$container, {
|
199 |
+
value: {
|
200 |
+
attachment_id: attachment.get('id'),
|
201 |
+
url: attachment.get('url')
|
202 |
+
}
|
203 |
+
});
|
204 |
}
|
205 |
};
|
206 |
|
210 |
.addClass('fw-option-initialized');
|
211 |
});
|
212 |
|
213 |
+
fw.options.register('upload', {
|
214 |
+
startListeningForChanges: jQuery.noop,
|
215 |
+
getValue: function (optionDescriptor) {
|
216 |
+
var deferred = $.Deferred();
|
217 |
+
|
218 |
+
var attachmentId = $(optionDescriptor.el).find(
|
219 |
+
'[type="hidden"][name*="' + optionDescriptor.id + '"]'
|
220 |
+
).val()
|
221 |
+
|
222 |
+
if (! attachmentId) {
|
223 |
+
deferred.resolve({
|
224 |
+
value: {},
|
225 |
+
optionDescriptor: optionDescriptor
|
226 |
+
});
|
227 |
+
} else {
|
228 |
+
var attachment = wp.media.attachment(attachmentId);
|
229 |
+
|
230 |
+
if (! attachment.get('url')) {
|
231 |
+
attachment.fetch().then(function () {
|
232 |
+
resolveWithAttachment(attachment);
|
233 |
+
})
|
234 |
+
} else {
|
235 |
+
resolveWithAttachment(attachment)
|
236 |
+
}
|
237 |
+
}
|
238 |
+
|
239 |
+
return deferred;
|
240 |
+
|
241 |
+
function resolveWithAttachment (attachment) {
|
242 |
+
deferred.resolve({
|
243 |
+
value: {
|
244 |
+
attachment_id: attachmentId,
|
245 |
+
url: attachment.get('url')
|
246 |
+
}
|
247 |
+
});
|
248 |
+
}
|
249 |
+
}
|
250 |
+
});
|
251 |
+
|
252 |
})(jQuery, _, fwEvents);
|
framework/includes/option-types/wp-editor/class-fw-option-type-wp-editor.php
CHANGED
@@ -9,6 +9,10 @@ class FW_Option_Type_Wp_Editor extends FW_Option_Type {
|
|
9 |
return 'wp-editor';
|
10 |
}
|
11 |
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* @internal
|
14 |
*/
|
@@ -167,4 +171,4 @@ class FW_Option_Type_Wp_Editor extends FW_Option_Type {
|
|
167 |
public function _get_backend_width_type() {
|
168 |
return 'auto';
|
169 |
}
|
170 |
-
}
|
9 |
return 'wp-editor';
|
10 |
}
|
11 |
|
12 |
+
protected function _get_data_for_js($id, $option, $data = array()) {
|
13 |
+
return false;
|
14 |
+
}
|
15 |
+
|
16 |
/**
|
17 |
* @internal
|
18 |
*/
|
171 |
public function _get_backend_width_type() {
|
172 |
return 'auto';
|
173 |
}
|
174 |
+
}
|
framework/includes/option-types/wp-editor/static/scripts.js
CHANGED
@@ -153,6 +153,25 @@
|
|
153 |
.addClass('fw-option-initialized');
|
154 |
});
|
155 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
})(jQuery, fwEvents);
|
157 |
|
158 |
/**
|
153 |
.addClass('fw-option-initialized');
|
154 |
});
|
155 |
|
156 |
+
fw.options.register('wp-editor', {
|
157 |
+
startListeningForChanges: function (optionDescriptor) {
|
158 |
+
$(optionDescriptor.el).find('textarea.wp-editor-area')
|
159 |
+
.on('change', function (e) {
|
160 |
+
fw.options.trigger.changeForEl(e.target);
|
161 |
+
});
|
162 |
+
},
|
163 |
+
|
164 |
+
getValue: function (optionDescriptor) {
|
165 |
+
return {
|
166 |
+
value: $(optionDescriptor.el).find(
|
167 |
+
'textarea.wp-editor-area'
|
168 |
+
).val(),
|
169 |
+
|
170 |
+
optionDescriptor: optionDescriptor
|
171 |
+
}
|
172 |
+
}
|
173 |
+
});
|
174 |
+
|
175 |
})(jQuery, fwEvents);
|
176 |
|
177 |
/**
|
framework/manifest.php
CHANGED
@@ -4,4 +4,4 @@ $manifest = array();
|
|
4 |
|
5 |
$manifest['name'] = __('Unyson', 'fw');
|
6 |
|
7 |
-
$manifest['version'] = '2.
|
4 |
|
5 |
$manifest['name'] = __('Unyson', 'fw');
|
6 |
|
7 |
+
$manifest['version'] = '2.7.2';
|
framework/static/js/fw-events.js
CHANGED
@@ -2,43 +2,12 @@
|
|
2 |
* Listen and trigger custom events to communicate between javascript components
|
3 |
*/
|
4 |
var fwEvents = new (function(){
|
5 |
-
{
|
6 |
-
|
|
|
7 |
|
8 |
-
|
9 |
-
|
10 |
-
var log = function(message, data) {
|
11 |
-
if (!debug) {
|
12 |
-
return;
|
13 |
-
}
|
14 |
-
|
15 |
-
if (typeof data != 'undefined') {
|
16 |
-
console.log('[Event] ' + getIndentation() + message, '─', data);
|
17 |
-
} else {
|
18 |
-
console.log('[Event] ' + getIndentation() + message);
|
19 |
-
}
|
20 |
-
};
|
21 |
-
|
22 |
-
/**
|
23 |
-
* Indent logs that happens inside another event
|
24 |
-
*/
|
25 |
-
{
|
26 |
-
var getIndentation = function() {
|
27 |
-
return new Array(currentIndentation).join('│ ');
|
28 |
-
};
|
29 |
-
|
30 |
-
var currentIndentation = 1;
|
31 |
-
|
32 |
-
var changeIndentation = function(increment) {
|
33 |
-
if (typeof increment != 'undefined') {
|
34 |
-
currentIndentation += (increment > 0 ? +1 : -1);
|
35 |
-
}
|
36 |
-
|
37 |
-
if (currentIndentation < 0) {
|
38 |
-
currentIndentation = 0;
|
39 |
-
}
|
40 |
-
};
|
41 |
-
}
|
42 |
}
|
43 |
|
44 |
/**
|
@@ -61,21 +30,26 @@ var fwEvents = new (function(){
|
|
61 |
|
62 |
/**
|
63 |
* Add event listener
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
*/
|
65 |
-
this.on = function(
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
_.each(event, function(_callback, _event){
|
75 |
-
log('✚ '+ _event);
|
76 |
-
});
|
77 |
}
|
78 |
-
|
79 |
|
80 |
return this;
|
81 |
};
|
@@ -83,64 +57,134 @@ var fwEvents = new (function(){
|
|
83 |
/**
|
84 |
* Same as .on(), but callback will executed only once
|
85 |
*/
|
86 |
-
this.one = function(
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
_.each(event, function(_callback, _event){
|
96 |
-
log('✚ ['+ _event +']');
|
97 |
-
});
|
98 |
}
|
99 |
-
|
100 |
|
101 |
return this;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
};
|
103 |
|
104 |
/**
|
105 |
-
*
|
|
|
|
|
|
|
|
|
|
|
106 |
*/
|
107 |
-
this.off = function(
|
108 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
|
110 |
-
|
111 |
-
|
112 |
-
|
|
|
113 |
|
114 |
return this;
|
115 |
};
|
116 |
|
117 |
/**
|
118 |
-
* Trigger event
|
|
|
|
|
119 |
*
|
120 |
-
* @
|
121 |
-
* @param {
|
122 |
-
* @param {Object} [data]
|
123 |
*/
|
124 |
-
this.trigger = function(
|
125 |
-
|
|
|
|
|
|
|
126 |
|
127 |
-
|
128 |
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
|
|
|
|
|
|
|
|
133 |
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
138 |
|
139 |
-
|
140 |
|
141 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
|
143 |
return this;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
144 |
};
|
145 |
|
146 |
/**
|
@@ -148,11 +192,80 @@ var fwEvents = new (function(){
|
|
148 |
* @param {String} [event]
|
149 |
* @return {Boolean}
|
150 |
*/
|
151 |
-
this.hasListeners = function(
|
152 |
-
if (!
|
153 |
return false;
|
154 |
}
|
155 |
|
156 |
-
return
|
157 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
158 |
})();
|
2 |
* Listen and trigger custom events to communicate between javascript components
|
3 |
*/
|
4 |
var fwEvents = new (function(){
|
5 |
+
var _events = {};
|
6 |
+
var currentIndentation = 1;
|
7 |
+
var debug = false;
|
8 |
|
9 |
+
this.countAll = function (topic) {
|
10 |
+
return _events[topic];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
}
|
12 |
|
13 |
/**
|
30 |
|
31 |
/**
|
32 |
* Add event listener
|
33 |
+
*
|
34 |
+
* @param event {String | Object}
|
35 |
+
* Can be a:
|
36 |
+
* - single event: 'event1'
|
37 |
+
* - space separated event list: 'event1 event2 event2'
|
38 |
+
* - an object: {event1: function () {}, event2: function () {}}
|
39 |
+
*
|
40 |
+
* @param callback {Function}
|
41 |
*/
|
42 |
+
this.on = function(topicStringOrObject, listener) {
|
43 |
+
objectMap(
|
44 |
+
splitTopicStringOrObject(topicStringOrObject, listener),
|
45 |
+
function (eventName, listener) {
|
46 |
+
(_events[eventName] || (_events[eventName] = [])).push(
|
47 |
+
listener
|
48 |
+
);
|
49 |
+
|
50 |
+
debug && log('✚ ' + eventName);
|
|
|
|
|
|
|
51 |
}
|
52 |
+
);
|
53 |
|
54 |
return this;
|
55 |
};
|
57 |
/**
|
58 |
* Same as .on(), but callback will executed only once
|
59 |
*/
|
60 |
+
this.one = function(topicStringOrObject, listener) {
|
61 |
+
objectMap(
|
62 |
+
splitTopicStringOrObject(topicStringOrObject, listener),
|
63 |
+
function (eventName, listener) {
|
64 |
+
(_events[eventName] || (_events[eventName] = [])).push(
|
65 |
+
once(listener)
|
66 |
+
);
|
67 |
+
|
68 |
+
debug && log('✚ [' + eventName +']');
|
|
|
|
|
|
|
69 |
}
|
70 |
+
);
|
71 |
|
72 |
return this;
|
73 |
+
|
74 |
+
// https://github.com/jashkenas/underscore/blob/8fc7032295d60aff3620ef85d4aa6549a55688a0/underscore.js#L946
|
75 |
+
function once(func) {
|
76 |
+
var memo;
|
77 |
+
|
78 |
+
var times = 2;
|
79 |
+
|
80 |
+
return function() {
|
81 |
+
if (--times > 0) {
|
82 |
+
memo = func.apply(this, arguments);
|
83 |
+
}
|
84 |
+
|
85 |
+
if (times <= 1) func = null;
|
86 |
+
|
87 |
+
return memo;
|
88 |
+
};
|
89 |
+
};
|
90 |
};
|
91 |
|
92 |
/**
|
93 |
+
* In order to remove one single listener you should give as an argument
|
94 |
+
* the same callback function. If you want to remove *all* listeners from
|
95 |
+
* a particular event you should not pass the second argument.
|
96 |
+
*
|
97 |
+
* @param topicStringOrObject {String | Object}
|
98 |
+
* @param listener {Function | false}
|
99 |
*/
|
100 |
+
this.off = function(topicStringOrObject, listener) {
|
101 |
+
objectMap(
|
102 |
+
splitTopicStringOrObject(topicStringOrObject, listener),
|
103 |
+
function (eventName, listener) {
|
104 |
+
if (_events[eventName]) {
|
105 |
+
if (listener) {
|
106 |
+
_events[eventName].splice(
|
107 |
+
_events[eventName].indexOf(listener) >>> 0,
|
108 |
+
1
|
109 |
+
);
|
110 |
+
} else {
|
111 |
+
_events[eventName] = [];
|
112 |
+
}
|
113 |
|
114 |
+
debug && log('✖ ' + eventName);
|
115 |
+
}
|
116 |
+
}
|
117 |
+
);
|
118 |
|
119 |
return this;
|
120 |
};
|
121 |
|
122 |
/**
|
123 |
+
* Trigger an event. In case you provide multiple events via space-separated
|
124 |
+
* string or an object of events it will execute listeners for each event
|
125 |
+
* separatedly. You can use the "all" event to trigger all events.
|
126 |
*
|
127 |
+
* @param topicStringOrObject {String | Object}
|
128 |
+
* @param data {Object}
|
|
|
129 |
*/
|
130 |
+
this.trigger = function(eventName, data) {
|
131 |
+
objectMap(
|
132 |
+
splitTopicStringOrObject(eventName),
|
133 |
+
function (eventName) {
|
134 |
+
log('╭─ '+ eventName, data);
|
135 |
|
136 |
+
changeIndentation(+1);
|
137 |
|
138 |
+
try {
|
139 |
+
// TODO: REFACTOR THAT!!!!!!!!!
|
140 |
+
// Maybe this is an occasion for using 'all' event???
|
141 |
+
if (eventName === 'fw:options:init') {
|
142 |
+
fw.options.startListeningToEvents(
|
143 |
+
data.$elements || document.body
|
144 |
+
)
|
145 |
+
}
|
146 |
|
147 |
+
(_events[eventName] || []).map(dispatchSingleEvent);
|
148 |
+
(_events['all'] || []).map(dispatchSingleEvent);
|
149 |
+
} catch (e) {
|
150 |
+
console.log(
|
151 |
+
"%c [Events] Exception raised. Please contact support in https://github.com/ThemeFuse/Unyson/issues/new. Don't forget to attach this stack trace to the issue.",
|
152 |
+
"color: red; font-weight: bold;"
|
153 |
+
);
|
154 |
+
|
155 |
+
if (typeof console !== 'undefined') {
|
156 |
+
console.error(e)
|
157 |
+
} else {
|
158 |
+
throw e;
|
159 |
+
}
|
160 |
+
}
|
161 |
|
162 |
+
changeIndentation(-1);
|
163 |
|
164 |
+
log('╰─ '+ eventName, data);
|
165 |
+
|
166 |
+
function dispatchSingleEvent (listenerDescriptor) {
|
167 |
+
if (! listenerDescriptor) return;
|
168 |
+
|
169 |
+
listenerDescriptor.call(
|
170 |
+
window,
|
171 |
+
data
|
172 |
+
);
|
173 |
+
}
|
174 |
+
}
|
175 |
+
);
|
176 |
|
177 |
return this;
|
178 |
+
|
179 |
+
function changeIndentation(increment) {
|
180 |
+
if (typeof increment != 'undefined') {
|
181 |
+
currentIndentation += (increment > 0 ? +1 : -1);
|
182 |
+
}
|
183 |
+
|
184 |
+
if (currentIndentation < 0) {
|
185 |
+
currentIndentation = 0;
|
186 |
+
}
|
187 |
+
}
|
188 |
};
|
189 |
|
190 |
/**
|
192 |
* @param {String} [event]
|
193 |
* @return {Boolean}
|
194 |
*/
|
195 |
+
this.hasListeners = function(eventName) {
|
196 |
+
if (! _events) {
|
197 |
return false;
|
198 |
}
|
199 |
|
200 |
+
return (_events[eventName] || []).length > 0;
|
201 |
};
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Probably split string into general purpose object representation for
|
205 |
+
* event names and listeners. This function leaves objects un-modified.
|
206 |
+
*
|
207 |
+
* @param topicStringOrObject {String | Object}
|
208 |
+
* @param listener {Function | false}
|
209 |
+
*
|
210 |
+
* @returns {Object} {
|
211 |
+
* eventname: listener,
|
212 |
+
* otherevent: listener
|
213 |
+
* }
|
214 |
+
*/
|
215 |
+
function splitTopicStringOrObject (topicStringOrObject, listener) {
|
216 |
+
if (typeof topicStringOrObject !== 'string') {
|
217 |
+
return topicStringOrObject;
|
218 |
+
}
|
219 |
+
|
220 |
+
var arrayOfEvents = topicStringOrObject.replace(
|
221 |
+
/\s\s+/g, ' '
|
222 |
+
).trim().split(' ');
|
223 |
+
|
224 |
+
var len = arrayOfEvents.length;
|
225 |
+
|
226 |
+
var listenerDescriptor = Object.create(null);
|
227 |
+
|
228 |
+
for (var i = 0; i < len; i++) {
|
229 |
+
listenerDescriptor[arrayOfEvents[i]] = listener;
|
230 |
+
}
|
231 |
+
|
232 |
+
return listenerDescriptor;
|
233 |
+
}
|
234 |
+
|
235 |
+
/**
|
236 |
+
* returns a new object with the predicate applied to each value
|
237 |
+
* objectMap({a: 3, b: 5, c: 9}, (key, value) => value + 1); // {a: 4, b: 6, c: 10}
|
238 |
+
* objectMap({a: 3, b: 5, c: 9}, (key, value) => key); // {a: 'a', b: 'b', c: 'c'}
|
239 |
+
* objectMap({a: 3, b: 5, c: 9}, (key, value) => key + value); // {a: 'a3', b: 'b5', c: 'c9'}
|
240 |
+
*
|
241 |
+
* https://github.com/angus-c/just/tree/master/packages/object-map
|
242 |
+
*/
|
243 |
+
function objectMap(obj, predicate) {
|
244 |
+
var result = {};
|
245 |
+
var keys = Object.keys(obj);
|
246 |
+
var len = keys.length;
|
247 |
+
|
248 |
+
for (var i = 0; i < len; i++) {
|
249 |
+
var key = keys[i];
|
250 |
+
result[key] = predicate(key, obj[key]);
|
251 |
+
}
|
252 |
+
|
253 |
+
return result;
|
254 |
+
}
|
255 |
+
|
256 |
+
function log(message, data) {
|
257 |
+
if (! debug) {
|
258 |
+
return;
|
259 |
+
}
|
260 |
+
|
261 |
+
if (typeof data != 'undefined') {
|
262 |
+
console.log('[Event] ' + getIndentation() + message, '─', data);
|
263 |
+
} else {
|
264 |
+
console.log('[Event] ' + getIndentation() + message);
|
265 |
+
}
|
266 |
+
|
267 |
+
function getIndentation() {
|
268 |
+
return new Array(currentIndentation).join('│ ');
|
269 |
+
}
|
270 |
+
}
|
271 |
})();
|
framework/views/backend-option-design-customizer.php
CHANGED
@@ -7,7 +7,9 @@
|
|
7 |
|
8 |
{
|
9 |
if (!isset($option['label'])) {
|
10 |
-
$option['label'] =
|
|
|
|
|
11 |
}
|
12 |
|
13 |
if (!isset($option['desc'])) {
|
@@ -121,4 +123,4 @@
|
|
121 |
</div>
|
122 |
</div>
|
123 |
</div>
|
124 |
-
</div>
|
7 |
|
8 |
{
|
9 |
if (!isset($option['label'])) {
|
10 |
+
$option['label'] = fw()->backend->option_type($option['type'])->_default_label(
|
11 |
+
$id, $option
|
12 |
+
);
|
13 |
}
|
14 |
|
15 |
if (!isset($option['desc'])) {
|
123 |
</div>
|
124 |
</div>
|
125 |
</div>
|
126 |
+
</div>
|
framework/views/backend-option-design-default.php
CHANGED
@@ -7,7 +7,9 @@
|
|
7 |
|
8 |
{
|
9 |
if (!isset($option['label'])) {
|
10 |
-
$option['label'] =
|
|
|
|
|
11 |
}
|
12 |
|
13 |
if (!isset($option['desc'])) {
|
@@ -133,6 +135,7 @@ try {
|
|
133 |
$desc_under_label = apply_filters('fw:backend-option-view:design-default:desc-under-label', false)
|
134 |
);
|
135 |
}
|
|
|
136 |
?>
|
137 |
<div class="<?php echo esc_attr($classes['option']) ?>" id="fw-backend-option-<?php echo esc_attr($data['id_prefix'] . $id) ?>">
|
138 |
<?php if ($option['label'] !== false): ?>
|
@@ -157,4 +160,4 @@ try {
|
|
157 |
<div class="fw-inner"><?php echo ($option['desc'] ? $option['desc'] : '') ?></div>
|
158 |
</div>
|
159 |
<?php endif; ?>
|
160 |
-
</div>
|
7 |
|
8 |
{
|
9 |
if (!isset($option['label'])) {
|
10 |
+
$option['label'] = fw()->backend->option_type($option['type'])->_default_label(
|
11 |
+
$id, $option
|
12 |
+
);
|
13 |
}
|
14 |
|
15 |
if (!isset($option['desc'])) {
|
135 |
$desc_under_label = apply_filters('fw:backend-option-view:design-default:desc-under-label', false)
|
136 |
);
|
137 |
}
|
138 |
+
|
139 |
?>
|
140 |
<div class="<?php echo esc_attr($classes['option']) ?>" id="fw-backend-option-<?php echo esc_attr($data['id_prefix'] . $id) ?>">
|
141 |
<?php if ($option['label'] !== false): ?>
|
160 |
<div class="fw-inner"><?php echo ($option['desc'] ? $option['desc'] : '') ?></div>
|
161 |
</div>
|
162 |
<?php endif; ?>
|
163 |
+
</div>
|
readme.txt
CHANGED
@@ -2,8 +2,8 @@
|
|
2 |
Contributors: unyson
|
3 |
Tags: page builder, shortcodes, backup, seo, breadcrumbs, portfolio, framework
|
4 |
Requires at least: 4.4
|
5 |
-
Tested up to: 4.
|
6 |
-
Stable tag: 2.
|
7 |
License: GPLv2 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
|
@@ -85,7 +85,17 @@ Yes; Unyson will work with any theme.
|
|
85 |
|
86 |
== Changelog ==
|
87 |
|
88 |
-
= 2.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
* Fixed [#2490](https://github.com/ThemeFuse/Unyson/issues/2490), [#2450](https://github.com/ThemeFuse/Unyson/issues/2450), [#326](https://github.com/ThemeFuse/Unyson/issues/326)
|
90 |
|
91 |
= 2.6.15 =
|
2 |
Contributors: unyson
|
3 |
Tags: page builder, shortcodes, backup, seo, breadcrumbs, portfolio, framework
|
4 |
Requires at least: 4.4
|
5 |
+
Tested up to: 4.8
|
6 |
+
Stable tag: 2.7.2
|
7 |
License: GPLv2 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
|
85 |
|
86 |
== Changelog ==
|
87 |
|
88 |
+
= 2.7.2 =
|
89 |
+
* Bug fixes
|
90 |
+
|
91 |
+
= 2.7.1 =
|
92 |
+
* Bug fixes
|
93 |
+
|
94 |
+
= 2.7.0 =
|
95 |
+
* Fixed [#2460](https://github.com/ThemeFuse/Unyson/issues/2460),[#1775](https://github.com/ThemeFuse/Unyson/issues/1775#issuecomment-293581057),[#2516](https://github.com/ThemeFuse/Unyson/issues/2516)[#2536](https://github.com/ThemeFuse/Unyson/pull/2536)[#1419](https://github.com/ThemeFuse/Unyson/issues/1419)[#2563](https://github.com/ThemeFuse/Unyson/issues/2563)[#2587](https://github.com/ThemeFuse/Unyson/issues/2587)[#2591](https://github.com/ThemeFuse/Unyson/issues/2591)[#2604](https://github.com/ThemeFuse/Unyson/issues/2604)
|
96 |
+
* New feature. Introducing Reactive Option Types
|
97 |
+
|
98 |
+
= 2.6.15 =
|
99 |
* Fixed [#2490](https://github.com/ThemeFuse/Unyson/issues/2490), [#2450](https://github.com/ThemeFuse/Unyson/issues/2450), [#326](https://github.com/ThemeFuse/Unyson/issues/326)
|
100 |
|
101 |
= 2.6.15 =
|
unyson.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: Unyson
|
4 |
* Plugin URI: http://unyson.io/
|
5 |
* Description: A free drag & drop framework that comes with a bunch of built in extensions that will help you develop premium themes fast & easy.
|
6 |
-
* Version: 2.
|
7 |
* Author: ThemeFuse
|
8 |
* Author URI: http://themefuse.com
|
9 |
* License: GPL2+
|
3 |
* Plugin Name: Unyson
|
4 |
* Plugin URI: http://unyson.io/
|
5 |
* Description: A free drag & drop framework that comes with a bunch of built in extensions that will help you develop premium themes fast & easy.
|
6 |
+
* Version: 2.7.2
|
7 |
* Author: ThemeFuse
|
8 |
* Author URI: http://themefuse.com
|
9 |
* License: GPL2+
|