first commit
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
<?php if (!defined('FW')) die('Forbidden');
|
||||
|
||||
class FW_Container_Type_Box extends FW_Container_Type {
|
||||
public function get_type() {
|
||||
return 'box';
|
||||
}
|
||||
|
||||
protected function _get_defaults() {
|
||||
return array(
|
||||
'title' => '',
|
||||
);
|
||||
}
|
||||
|
||||
protected function _enqueue_static($id, $option, $values, $data) {
|
||||
//
|
||||
}
|
||||
|
||||
protected function _render($containers, $values, $data) {
|
||||
$html = '';
|
||||
|
||||
foreach ( $containers as $id => &$box ) {
|
||||
if (empty($box['options'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unset( $box['attr']['id'] ); // do not allow id overwrite, it is sent in first argument of render_box()
|
||||
|
||||
$html .= fw()->backend->render_box(
|
||||
'fw-options-box-' . $id,
|
||||
empty( $box['title'] ) ? ' ' : $box['title'],
|
||||
fw()->backend->render_options( $box['options'], $values, $data ),
|
||||
array(
|
||||
'attr' => $box['attr']
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!empty($html)) {
|
||||
$html =
|
||||
'<div class="fw-backend-postboxes metabox-holder">'
|
||||
. $html
|
||||
. '</div>';
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php if (!defined('FW')) die('Forbidden');
|
||||
|
||||
/**
|
||||
* This will be returned when tried to get a not existing container type
|
||||
* to prevent fatal errors for cases when just one container type was typed wrong
|
||||
* or any other minor bug that has no sense to crash the whole site
|
||||
*/
|
||||
class FW_Container_Type_Undefined extends FW_Container_Type {
|
||||
public function get_type() {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _enqueue_static($id, $option, $values, $data) {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _render($containers, $values, $data) {
|
||||
return '<p>/* Undefined Container Type */</p>';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _get_defaults() {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php if (!defined('FW')) die('Forbidden');
|
||||
|
||||
class FW_Container_Type_Popup extends FW_Container_Type {
|
||||
public function get_type() {
|
||||
return 'popup';
|
||||
}
|
||||
|
||||
protected function _get_defaults() {
|
||||
return array(
|
||||
'modal-size' => 'small', // small, medium, large
|
||||
'desc' => '',
|
||||
);
|
||||
}
|
||||
|
||||
protected function _enqueue_static($id, $option, $values, $data) {
|
||||
$uri = fw_get_framework_directory_uri('/includes/container-types/popup');
|
||||
|
||||
wp_enqueue_script(
|
||||
'fw-container-type-'. $this->get_type(),
|
||||
$uri .'/scripts.js',
|
||||
array('jquery', 'fw-events', 'fw'),
|
||||
fw()->manifest->get_version()
|
||||
);
|
||||
|
||||
wp_enqueue_style('fw');
|
||||
|
||||
wp_enqueue_style(
|
||||
'fw-container-type-'. $this->get_type(),
|
||||
$uri .'/styles.css',
|
||||
array(),
|
||||
fw()->manifest->get_version()
|
||||
);
|
||||
}
|
||||
|
||||
protected function _render($containers, $values, $data) {
|
||||
$html = '';
|
||||
|
||||
$defaults = $this->get_defaults();
|
||||
|
||||
foreach ($containers as $id => &$option) {
|
||||
{
|
||||
$attr = $option['attr'];
|
||||
|
||||
$attr['data-modal-title'] = $option['title'];
|
||||
|
||||
if (in_array($option['modal-size'], array('small', 'medium', 'large'))) {
|
||||
$attr['data-modal-size'] = $option['modal-size'];
|
||||
} else {
|
||||
$attr['data-modal-size'] = $defaults['modal-size'];
|
||||
}
|
||||
|
||||
$attr['id'] = $data['id_prefix'] . $id;
|
||||
}
|
||||
|
||||
$html .=
|
||||
'<div '. fw_attr_to_html($attr) .'>'
|
||||
. '<p class="popup-button-wrapper">'
|
||||
. fw_html_tag(
|
||||
'button',
|
||||
array(
|
||||
'type' => 'button',
|
||||
'class' => 'button button-secondary popup-button',
|
||||
),
|
||||
$option['title']
|
||||
)
|
||||
. '</p>'
|
||||
. (empty($option['desc']) ? '' : ('<div class="popup-desc">'. $option['desc'] .'</div>'))
|
||||
. '<div class="popup-options fw-hidden">'
|
||||
. fw()->backend->render_options($option['options'], $values, $data)
|
||||
. '</div>'
|
||||
. '</div>';
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
jQuery(function($){
|
||||
var optionTypeClass = '.fw-container-type-popup',
|
||||
optionsModals = {},
|
||||
getOptionsModal = function(id, data) {
|
||||
if (typeof optionsModals[id] == 'undefined') {
|
||||
var $option = data.$option,
|
||||
$options = data.$options,
|
||||
modal = optionsModals[id] = new fw.Modal({
|
||||
title: $option.attr('data-modal-title'),
|
||||
size: $option.attr('data-modal-size')
|
||||
}),
|
||||
onOpen = function(){
|
||||
$options.detach();
|
||||
|
||||
modal.content.$el.html('').append($options);
|
||||
|
||||
$options.removeClass('fw-hidden');
|
||||
},
|
||||
onClose = function(){
|
||||
$options.detach();
|
||||
|
||||
$options.addClass('fw-hidden');
|
||||
|
||||
$option.append($options);
|
||||
};
|
||||
|
||||
modal.frame.on('open', onOpen);
|
||||
modal.frame.on('close', onClose);
|
||||
}
|
||||
|
||||
return optionsModals[id];
|
||||
};
|
||||
|
||||
fwEvents.on('fw:options:init', function(data){
|
||||
data.$elements.find(optionTypeClass +':not(.initialized)').each(function(){
|
||||
var $option = $(this),
|
||||
$button = $option.find('> .popup-button-wrapper > .popup-button'),
|
||||
$options = $option.find('> .popup-options');
|
||||
|
||||
$button.on('click', function(){
|
||||
getOptionsModal($option.attr('id'), {
|
||||
$option: $option,
|
||||
$options: $options
|
||||
}).open();
|
||||
});
|
||||
}).addClass('initialized');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
.fw-container-type-popup {
|
||||
padding: 24px 27px 21px;
|
||||
|
||||
opacity: 0;
|
||||
transition: opacity ease 0.3s;
|
||||
-webkit-transition: opacity ease 0.3s;
|
||||
}
|
||||
|
||||
.fw-container-type-popup.initialized {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.fw-container-type-popup > .popup-desc {
|
||||
font-style: italic;
|
||||
color: #666;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php if (!defined('FW')) die('Forbidden');
|
||||
|
||||
class FW_Container_Type_Group extends FW_Container_Type {
|
||||
public function get_type() {
|
||||
return 'group';
|
||||
}
|
||||
|
||||
protected function _get_defaults() {
|
||||
return array();
|
||||
}
|
||||
|
||||
protected function _enqueue_static($id, $option, $values, $data) {
|
||||
//
|
||||
}
|
||||
|
||||
protected function _render($containers, $values, $data) {
|
||||
$html = '';
|
||||
|
||||
foreach ( $containers as $id => &$group ) {
|
||||
// prepare attributes
|
||||
{
|
||||
$attr = isset( $group['attr'] ) ? $group['attr'] : array();
|
||||
|
||||
$attr['id'] = 'fw-backend-options-group-' . $id;
|
||||
|
||||
if ( ! isset( $attr['class'] ) ) {
|
||||
$attr['class'] = 'fw-backend-options-group';
|
||||
} else {
|
||||
$attr['class'] = 'fw-backend-options-group ' . $attr['class'];
|
||||
}
|
||||
}
|
||||
|
||||
$html .= '<div ' . fw_attr_to_html( $attr ) . '>';
|
||||
$html .= fw()->backend->render_options( $group['options'], $values, $data );
|
||||
$html .= '</div>';
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php if (!defined('FW')) die('Forbidden');
|
||||
|
||||
class FW_Container_Type_Tab extends FW_Container_Type {
|
||||
public function get_type() {
|
||||
return 'tab';
|
||||
}
|
||||
|
||||
protected function _get_defaults() {
|
||||
return array(
|
||||
'title' => '',
|
||||
);
|
||||
}
|
||||
|
||||
protected function _enqueue_static($id, $option, $values, $data) {
|
||||
//
|
||||
}
|
||||
|
||||
protected function _render($containers, $values, $data) {
|
||||
return fw_render_view(
|
||||
dirname(__FILE__) .'/view.php',
|
||||
array(
|
||||
'tabs' => &$containers,
|
||||
'values' => &$values,
|
||||
'options_data' => &$data,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php if (!defined('FW')) die('Forbidden');
|
||||
/**
|
||||
* @var array $tabs
|
||||
* @var array $values
|
||||
* @var array $options_data
|
||||
*/
|
||||
|
||||
$global_lazy_tabs = fw()->theme->get_config('lazy_tabs');
|
||||
|
||||
?>
|
||||
<div class="fw-options-tabs-wrapper">
|
||||
<div class="fw-options-tabs-list">
|
||||
<ul>
|
||||
<?php foreach ($tabs as $tab_id => &$tab): ?>
|
||||
<li <?php echo isset($tab['li-attr']) ? fw_attr_to_html($tab['li-attr']) : ''; ?> >
|
||||
<a href="#fw-options-tab-<?php echo esc_attr($tab_id) ?>" class="nav-tab fw-wp-link" ><?php
|
||||
echo htmlspecialchars($tab['title'], ENT_COMPAT, 'UTF-8') ?></a>
|
||||
</li>
|
||||
<?php endforeach; unset($tab); ?>
|
||||
</ul>
|
||||
<div class="fw-clear"></div>
|
||||
</div>
|
||||
<div class="fw-options-tabs-contents metabox-holder">
|
||||
<div class="fw-inner">
|
||||
<?php
|
||||
foreach ($tabs as $tab_id => &$tab):
|
||||
// prepare attributes
|
||||
{
|
||||
$attr = isset($tab['attr']) ? $tab['attr'] : array();
|
||||
|
||||
$lazy_tabs = isset($tab['lazy_tabs']) ? $tab['lazy_tabs'] : $global_lazy_tabs;
|
||||
|
||||
$attr['id'] = 'fw-options-tab-'. esc_attr($tab_id);
|
||||
|
||||
if (!isset($attr['class'])) {
|
||||
$attr['class'] = 'fw-options-tab';
|
||||
} else {
|
||||
$attr['class'] = 'fw-options-tab '. $attr['class'];
|
||||
}
|
||||
|
||||
if ($lazy_tabs) {
|
||||
$attr['data-fw-tab-html'] = fw()->backend->render_options(
|
||||
$tab['options'], $values, $options_data
|
||||
);
|
||||
}
|
||||
}
|
||||
?><div <?php echo fw_attr_to_html($attr) ?>><?php
|
||||
echo $lazy_tabs ? '' : fw()->backend->render_options($tab['options'], $values, $options_data);
|
||||
?></div><?php
|
||||
unset($tabs[$tab_id]); // free memory after printed and not needed anymore
|
||||
endforeach;
|
||||
unset($tab);
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fw-clear"></div>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php if (!defined('FW')) die('Forbidden');
|
||||
|
||||
class _FW_Customizer_Control_Option_Wrapper extends WP_Customize_Control {
|
||||
public function render_content() {
|
||||
fw()->backend->_set_default_render_design('customizer');
|
||||
?>
|
||||
<div class="fw-backend-customizer-option">
|
||||
<input class="fw-backend-customizer-option-input" type="hidden" <?php $this->link() ?> />
|
||||
<div class="fw-backend-customizer-option-inner fw-force-xs">
|
||||
<?php
|
||||
echo fw()->backend->render_options(
|
||||
array($this->id => $this->setting->get_fw_option()),
|
||||
array($this->id => $this->value()),
|
||||
array(),
|
||||
'customizer'
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
fw()->backend->_set_default_render_design();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php if (!defined('FW')) die('Forbidden');
|
||||
|
||||
class _FW_Customizer_Setting_Option extends WP_Customize_Setting {
|
||||
/**
|
||||
* @var array
|
||||
* This is sent in args and set in parent construct
|
||||
*/
|
||||
protected $fw_option = array();
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* This is sent in args and set in parent construct
|
||||
*/
|
||||
protected $fw_option_id;
|
||||
|
||||
public function get_fw_option() {
|
||||
return $this->fw_option;
|
||||
}
|
||||
|
||||
public function sanitize($value) {
|
||||
if ( is_array( $value ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$value = json_decode($value, true);
|
||||
|
||||
if (is_null($value) || !is_array($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$POST = array();
|
||||
|
||||
foreach ($value as $var) {
|
||||
fw_aks(
|
||||
fw_html_attr_name_to_array_multi_key($var['name'], true),
|
||||
$var['value'],
|
||||
$POST
|
||||
);
|
||||
}
|
||||
|
||||
$value = fw()->backend->option_type($this->fw_option['type'])->get_value_from_input(
|
||||
$this->fw_option,
|
||||
fw_akg(fw_html_attr_name_to_array_multi_key($this->id), $POST)
|
||||
);
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function value() {
|
||||
return fw_db_option_storage_load(
|
||||
$this->fw_option_id,
|
||||
$this->fw_option,
|
||||
parent::value(),
|
||||
array('customizer' => true)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function update( $value ) {
|
||||
return parent::update(
|
||||
fw_db_option_storage_save(
|
||||
$this->fw_option_id,
|
||||
$this->fw_option,
|
||||
$value,
|
||||
array('customizer' => true)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
384
wp-content/plugins/unyson/framework/includes/hooks.php
Normal file
384
wp-content/plugins/unyson/framework/includes/hooks.php
Normal file
@@ -0,0 +1,384 @@
|
||||
<?php if ( ! defined( 'FW' ) ) {
|
||||
die( 'Forbidden' );
|
||||
}
|
||||
/**
|
||||
* Filters and Actions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Option types
|
||||
*/
|
||||
{
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
function _action_fw_init_option_types() {
|
||||
FW_Option_Type::register( 'FW_Option_Type_Hidden' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Text' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Short_Text' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Number' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Password' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Textarea' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Html' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Html_Fixed' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Html_Full' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Checkbox' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Checkboxes' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Radio' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Select' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Short_Select' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Select_Multiple' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Unique' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_GMap_Key' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Addable_Box' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Addable_Option' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Addable_Popup' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Addable_Popup_Full' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Background_Image' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Color_Picker' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Date_Picker' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Datetime_Picker' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Datetime_Range' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Gradient' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Icon' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Image_Picker' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Map' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Multi' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Multi_Picker' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Multi_Upload' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Popup' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Radio_Text' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Range_Slider' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Rgba_Color_Picker' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Slider' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Slider_Short' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Switch' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Typography' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Typography_v2' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Upload' );
|
||||
FW_Option_Type::register( 'FW_Option_Type_Wp_Editor' );
|
||||
|
||||
{
|
||||
$favorites = new FW_Icon_V2_Favorites_Manager();
|
||||
$favorites->attach_ajax_actions();
|
||||
|
||||
FW_Option_Type::register( 'FW_Option_Type_Icon_v2' );
|
||||
}
|
||||
|
||||
{
|
||||
FW_Option_Type::register( 'FW_Option_Type_Multi_Select' );
|
||||
}
|
||||
|
||||
{
|
||||
FW_Option_Type::register( 'FW_Option_Type_Oembed' );
|
||||
}
|
||||
}
|
||||
|
||||
add_action( 'fw_option_types_init', '_action_fw_init_option_types' );
|
||||
|
||||
/**
|
||||
* Some option-types have add_action('wp_ajax_...')
|
||||
* so init all option-types if current request is ajax
|
||||
* @since 2.6.1
|
||||
*/
|
||||
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
|
||||
function _action_fw_init_option_types_on_ajax() {
|
||||
foreach (fw()->backend->get_option_types() as $type) {
|
||||
fw()->backend->option_type($type);
|
||||
}
|
||||
}
|
||||
|
||||
add_action( 'fw_init', '_action_fw_init_option_types_on_ajax' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent Fatal Error if someone is registering option-types in old way (right away)
|
||||
* not in 'fw_option_types_init' action
|
||||
*
|
||||
* @param string $class
|
||||
*/
|
||||
function _fw_autoload_option_types( $class ) {
|
||||
if ( 'FW_Option_Type' === $class ) {
|
||||
if ( is_admin() && defined( 'WP_DEBUG' ) && WP_DEBUG ) {
|
||||
FW_Flash_Messages::add(
|
||||
'option-type-register-wrong',
|
||||
__( "Please register option-types on 'fw_option_types_init' action", 'fw' ),
|
||||
'warning'
|
||||
);
|
||||
}
|
||||
} elseif ( 'FW_Container_Type' === $class ) {
|
||||
if ( is_admin() && defined( 'WP_DEBUG' ) && WP_DEBUG ) {
|
||||
FW_Flash_Messages::add(
|
||||
'container-type-register-wrong',
|
||||
__( "Please register container-types on 'fw_container_types_init' action", 'fw' ),
|
||||
'warning'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spl_autoload_register( '_fw_autoload_option_types' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Container types
|
||||
*/
|
||||
{
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
function _action_fw_init_container_types() {
|
||||
FW_Container_Type::register( 'FW_Container_Type_Group' );
|
||||
FW_Container_Type::register( 'FW_Container_Type_Box' );
|
||||
FW_Container_Type::register( 'FW_Container_Type_Popup' );
|
||||
FW_Container_Type::register( 'FW_Container_Type_Tab' );
|
||||
}
|
||||
|
||||
add_action( 'fw_container_types_init', '_action_fw_init_container_types' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom Github API service
|
||||
* Provides the same responses but is "unlimited"
|
||||
* To prevent error: Github API rate limit exceeded 60 requests per hour
|
||||
* https://github.com/ThemeFuse/Unyson/issues/138
|
||||
* @internal
|
||||
*/
|
||||
function _fw_filter_github_api_url( $url ) {
|
||||
return 'https://github-api-cache.unyson.io';
|
||||
}
|
||||
|
||||
add_filter( 'fw_github_api_url', '_fw_filter_github_api_url' );
|
||||
|
||||
/**
|
||||
* Javascript events related to tinymce init
|
||||
* @since 2.6.0
|
||||
*/
|
||||
{
|
||||
add_action( 'wp_tiny_mce_init', '_fw_action_tiny_mce_init' );
|
||||
function _fw_action_tiny_mce_init( $mce_settings ) {
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
if (typeof fwEvents != 'undefined') {
|
||||
fwEvents.trigger('fw:tinymce:init:before');
|
||||
}
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
add_action( 'after_wp_tiny_mce', '_fw_action_after_wp_tiny_mce' );
|
||||
function _fw_action_after_wp_tiny_mce( $mce_settings ) {
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
if (typeof fwEvents != 'undefined') {
|
||||
fwEvents.trigger('fw:tinymce:init:after');
|
||||
}
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
// FW_Form hooks
|
||||
{
|
||||
if ( is_admin() ) {
|
||||
/**
|
||||
* Display form errors in admin side
|
||||
* @internal
|
||||
*/
|
||||
function _action_fw_form_show_errors_in_admin() {
|
||||
$form = FW_Form::get_submitted();
|
||||
|
||||
if ( ! $form || $form->is_valid() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $form->get_errors() as $input_name => $error_message ) {
|
||||
FW_Flash_Messages::add( 'fw-form-admin-' . $input_name, $error_message, 'error' );
|
||||
}
|
||||
}
|
||||
|
||||
add_action( 'wp_loaded', '_action_fw_form_show_errors_in_admin', 111 );
|
||||
} else {
|
||||
/**
|
||||
* to disable this use remove_action('wp_print_styles', '_action_fw_form_frontend_default_styles');
|
||||
* @internal
|
||||
*/
|
||||
function _action_fw_form_frontend_default_styles() {
|
||||
$form = FW_Form::get_submitted();
|
||||
|
||||
if ( ! $form || $form->is_valid() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
echo '<style type="text/css">.fw-form-errors { color: #bf0000; }</style>';
|
||||
}
|
||||
|
||||
add_action( 'wp_print_styles', '_action_fw_form_frontend_default_styles' );
|
||||
}
|
||||
}
|
||||
|
||||
// FW_Flash_Messages hooks
|
||||
{
|
||||
if ( is_admin() ) {
|
||||
/**
|
||||
* Start the session before the content is sent to prevent the "headers already sent" warning
|
||||
* @internal
|
||||
*/
|
||||
function _action_fw_flash_message_backend_prepare() {
|
||||
if ( apply_filters( 'fw_use_sessions', true ) && ! session_id() ) {
|
||||
session_start();
|
||||
}
|
||||
}
|
||||
|
||||
add_action( 'current_screen', '_action_fw_flash_message_backend_prepare', 9999 );
|
||||
|
||||
/**
|
||||
* Display flash messages in backend as notices
|
||||
*/
|
||||
add_action( 'admin_notices', array( 'FW_Flash_Messages', '_print_backend' ) );
|
||||
} else {
|
||||
/**
|
||||
* Start the session before the content is sent to prevent the "headers already sent" warning
|
||||
* @internal
|
||||
*/
|
||||
function _action_fw_flash_message_frontend_prepare() {
|
||||
if (
|
||||
apply_filters( 'fw_use_sessions', true )
|
||||
&&
|
||||
/**
|
||||
* In ajax it's not possible to call flash message after headers were sent,
|
||||
* so there will be no "headers already sent" warning.
|
||||
* Also in the Backups extension, are made many internal ajax request,
|
||||
* each creating a new independent request that don't remember/use session cookie from previous request,
|
||||
* thus on server side are created many (not used) new sessions.
|
||||
*/
|
||||
! ( defined( 'DOING_AJAX' ) && DOING_AJAX )
|
||||
&&
|
||||
! session_id()
|
||||
) {
|
||||
session_start();
|
||||
}
|
||||
}
|
||||
|
||||
add_action( 'send_headers', '_action_fw_flash_message_frontend_prepare', 9999 );
|
||||
|
||||
/**
|
||||
* Print flash messages in frontend if this has not been done from theme
|
||||
*/
|
||||
function _action_fw_flash_message_frontend_print() {
|
||||
if ( FW_Flash_Messages::_frontend_printed() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! FW_Flash_Messages::_print_frontend() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
(function () {
|
||||
if (typeof jQuery === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
jQuery(function ($) {
|
||||
var $container;
|
||||
|
||||
// Try to find the content element
|
||||
{
|
||||
var selector, selectors = [
|
||||
'#main #content',
|
||||
'#content #main',
|
||||
'#main',
|
||||
'#content',
|
||||
'#content-container',
|
||||
'#container',
|
||||
'.container:first'
|
||||
];
|
||||
|
||||
while (selector = selectors.shift()) {
|
||||
$container = $(selector);
|
||||
|
||||
if ($container.length) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$container.length) {
|
||||
// Try to find main page H1 container
|
||||
$container = $('h1:first').parent();
|
||||
}
|
||||
|
||||
if (!$container.length) {
|
||||
// If nothing found, just add to body
|
||||
$container = $(document.body);
|
||||
}
|
||||
|
||||
$(".fw-flash-messages").prependTo($container);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<style type="text/css">
|
||||
.fw-flash-messages .fw-flash-type-error {
|
||||
color: #f00;
|
||||
}
|
||||
|
||||
.fw-flash-messages .fw-flash-type-warning {
|
||||
color: #f70;
|
||||
}
|
||||
|
||||
.fw-flash-messages .fw-flash-type-success {
|
||||
color: #070;
|
||||
}
|
||||
|
||||
.fw-flash-messages .fw-flash-type-info {
|
||||
color: #07f;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
}
|
||||
|
||||
add_action( 'wp_footer', '_action_fw_flash_message_frontend_print', 9999 );
|
||||
}
|
||||
}
|
||||
|
||||
// FW_Resize hooks
|
||||
{
|
||||
if ( ! function_exists( 'fw_delete_resized_thumbnails' ) ) {
|
||||
function fw_delete_resized_thumbnails( $id ) {
|
||||
$images = wp_get_attachment_metadata( $id );
|
||||
if ( ! empty( $images['resizes'] ) ) {
|
||||
$uploads_dir = wp_upload_dir();
|
||||
foreach ( $images['resizes'] as $image ) {
|
||||
$file = $uploads_dir['basedir'] . '/' . $image;
|
||||
@unlink( $file );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
add_action( 'delete_attachment', 'fw_delete_resized_thumbnails' );
|
||||
}
|
||||
}
|
||||
|
||||
//WPML Hooks
|
||||
{
|
||||
if ( is_admin() ) {
|
||||
add_action( 'icl_save_term_translation', '_fw_action_wpml_duplicate_term_options', 20, 2 );
|
||||
function _fw_action_wpml_duplicate_term_options( $original, $translated ) {
|
||||
$original_options = fw_get_db_term_option(
|
||||
fw_akg( 'term_id', $original ),
|
||||
fw_akg( 'taxonomy', $original )
|
||||
);
|
||||
|
||||
if ( $original_options !== null ) {
|
||||
fw_set_db_term_option(
|
||||
fw_akg( 'term_id', $translated ),
|
||||
fw_akg( 'taxonomy', $original ),
|
||||
null,
|
||||
$original_options
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php if (!defined('FW')) die('Forbidden');
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class _FW_Option_Storage_Type_Register extends FW_Type_Register {
|
||||
protected function validate_type(FW_Type $type) {
|
||||
return $type instanceof FW_Option_Storage_Type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php if (!defined('FW')) die('Forbidden');
|
||||
|
||||
abstract class FW_Option_Storage_Type extends FW_Type {
|
||||
/**
|
||||
* Save the value in another place and return a value that will be save in regular place (same as before this feature)
|
||||
*
|
||||
* @param string $id
|
||||
* @param array $option
|
||||
* @param mixed $value Current option (regular) value
|
||||
* @param array $params
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* - if the save is fail
|
||||
*
|
||||
* <?php
|
||||
* return $value;
|
||||
*
|
||||
* - if the save is success, return a valid default/empty value from that option type,
|
||||
* so if the separately saved value is lost, will be used empty but valid $value
|
||||
* and there will be no notices/errors in scripts that are using it and expects a specific structure/format
|
||||
*
|
||||
* <?php
|
||||
* return return fw()->backend->option_type($option['type'])->get_value_from_input(array('type' => $option['type']), null);
|
||||
*/
|
||||
abstract protected function _save($id, array $option, $value, array $params);
|
||||
|
||||
/**
|
||||
* Load the value saved in custom place
|
||||
*
|
||||
* @param string $id
|
||||
* @param array $option
|
||||
* @param mixed $value Current option (regular) value
|
||||
* @param array $params
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract protected function _load($id, array $option, $value, array $params);
|
||||
|
||||
/**
|
||||
* @param string $id
|
||||
* @param array $option
|
||||
* @param mixed $value
|
||||
* @param array $params
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
final public function save($id, array $option, $value, array $params = array()) {
|
||||
if (
|
||||
!empty($option['fw-storage'])
|
||||
&&
|
||||
($storage = is_array($option['fw-storage'])
|
||||
? $option['fw-storage']
|
||||
: array('type' => $option['fw-storage'])
|
||||
)
|
||||
&&
|
||||
!empty($storage['type'])
|
||||
&&
|
||||
$storage['type'] === $this->get_type()
|
||||
) {
|
||||
$option['fw-storage'] = $storage;
|
||||
} else {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return $this->_save($id, $option, $value, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id
|
||||
* @param array $option
|
||||
* @param mixed $value
|
||||
* @param array $params
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
final public function load($id, array $option, $value, array $params = array()) {
|
||||
if (
|
||||
!empty($option['fw-storage'])
|
||||
&&
|
||||
($storage = is_array($option['fw-storage'])
|
||||
? $option['fw-storage']
|
||||
: array('type' => $option['fw-storage'])
|
||||
)
|
||||
&&
|
||||
!empty($storage['type'])
|
||||
&&
|
||||
$storage['type'] === $this->get_type()
|
||||
) {
|
||||
$option['fw-storage'] = $storage;
|
||||
} else {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return $this->_load($id, $option, $value, $params);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php if (!defined('FW')) die('Forbidden');
|
||||
|
||||
/**
|
||||
* array(
|
||||
* 'post-id' => 3 // optional // hardcoded post id
|
||||
* 'post-meta' => 'hello_world' // optional (default: 'fw:opt:{option_id}')
|
||||
* 'key' => 'option_id/sub_key' // optional @since 2.5.3
|
||||
* )
|
||||
*/
|
||||
class FW_Option_Storage_Type_Post_Meta extends FW_Option_Storage_Type {
|
||||
public function get_type() {
|
||||
return 'post-meta';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _save( $id, array $option, $value, array $params ) {
|
||||
if ($post_id = $this->get_post_id($option, $params)) {
|
||||
$meta_id = $this->get_meta_id($id, $option, $params);
|
||||
|
||||
if (isset($option['fw-storage']['key'])) {
|
||||
$meta_value = get_post_meta($post_id, $meta_id, true);
|
||||
|
||||
fw_aks($option['fw-storage']['key'], $value, $meta_value);
|
||||
|
||||
fw_update_post_meta($post_id, $meta_id, $meta_value);
|
||||
|
||||
unset($meta_value);
|
||||
} else {
|
||||
fw_update_post_meta($post_id, $meta_id, $value);
|
||||
}
|
||||
|
||||
return fw()->backend->option_type($option['type'])->get_value_from_input(
|
||||
array('type' => $option['type']), null
|
||||
);
|
||||
} else {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _load( $id, array $option, $value, array $params ) {
|
||||
if ($post_id = $this->get_post_id($option, $params)) {
|
||||
$meta_id = $this->get_meta_id($id, $option, $params);
|
||||
$meta_value = get_post_meta($post_id, $meta_id,
|
||||
/**
|
||||
* Do not set this to `true` because the below verification if value exists or not will be impossible
|
||||
* because if the value is not in db it will be an empty string '' instead of NULL
|
||||
* so we can't treat empty string as non value because the actual value can be an empty string
|
||||
*/
|
||||
false
|
||||
);
|
||||
|
||||
if (empty($meta_value)) {
|
||||
return $value;
|
||||
} else {
|
||||
$meta_value = $meta_value[0];
|
||||
}
|
||||
|
||||
if (isset($option['fw-storage']['key'])) {
|
||||
return fw_akg($option['fw-storage']['key'], $meta_value, $value);
|
||||
} else {
|
||||
return $meta_value;
|
||||
}
|
||||
} else {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
private function get_post_id($option, $params) {
|
||||
$post_id = null;
|
||||
|
||||
if (!empty($option['fw-storage']['post-id'])) {
|
||||
$post_id = $option['fw-storage']['post-id'];
|
||||
} elseif (!empty($params['post-id'])) {
|
||||
$post_id = $params['post-id'];
|
||||
}
|
||||
|
||||
$post_id = intval($post_id);
|
||||
|
||||
if ($post_id > 0) {
|
||||
return $post_id;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private function get_meta_id($id, $option, $params) {
|
||||
return empty($option['fw-storage']['post-meta'])
|
||||
? 'fw:opt:'. $id
|
||||
: $option['fw-storage']['post-meta'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php if (!defined('FW')) die('Forbidden');
|
||||
|
||||
/**
|
||||
* array(
|
||||
* 'term-id' => 3 // optional // hardcoded term id
|
||||
* 'term-meta' => 'hello_world' // optional (default: 'fw:opt:{option_id}')
|
||||
* 'key' => 'option_id/sub_key' // optional
|
||||
* )
|
||||
*/
|
||||
class FW_Option_Storage_Type_Term_Meta extends FW_Option_Storage_Type {
|
||||
public function get_type() {
|
||||
return 'term-meta';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _save( $id, array $option, $value, array $params ) {
|
||||
if ($term_id = $this->get_term_id($option, $params)) {
|
||||
$meta_id = $this->get_meta_id($id, $option, $params);
|
||||
|
||||
if (isset($option['fw-storage']['key'])) {
|
||||
$meta_value = get_term_meta($term_id, $meta_id, true);
|
||||
|
||||
fw_aks($option['fw-storage']['key'], $value, $meta_value);
|
||||
|
||||
update_term_meta($term_id, $meta_id, $meta_value);
|
||||
|
||||
unset($meta_value);
|
||||
} else {
|
||||
update_term_meta($term_id, $meta_id, $value);
|
||||
}
|
||||
|
||||
return fw()->backend->option_type($option['type'])->get_value_from_input(
|
||||
array('type' => $option['type']), null
|
||||
);
|
||||
} else {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _load( $id, array $option, $value, array $params ) {
|
||||
if ($term_id = $this->get_term_id($option, $params)) {
|
||||
$meta_id = $this->get_meta_id($id, $option, $params);
|
||||
$meta_value = get_term_meta($term_id, $meta_id, true);
|
||||
|
||||
if ($meta_value === '' && is_array($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (isset($option['fw-storage']['key'])) {
|
||||
return fw_akg($option['fw-storage']['key'], $meta_value, $value);
|
||||
} else {
|
||||
return $meta_value;
|
||||
}
|
||||
} else {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
private function get_term_id($option, $params) {
|
||||
$term_id = null;
|
||||
|
||||
if (!empty($option['fw-storage']['term-id'])) {
|
||||
$term_id = $option['fw-storage']['term-id'];
|
||||
} elseif (!empty($params['term-id'])) {
|
||||
$term_id = $params['term-id'];
|
||||
}
|
||||
|
||||
$term_id = intval($term_id);
|
||||
|
||||
if ($term_id > 0) {
|
||||
return $term_id;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private function get_meta_id($id, $option, $params) {
|
||||
return empty($option['fw-storage']['term-meta'])
|
||||
? 'fw:opt:'. $id
|
||||
: $option['fw-storage']['term-meta'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php if (!defined('FW')) die('Forbidden');
|
||||
|
||||
/**
|
||||
* array(
|
||||
* 'wp-option' => 'custom_wp_option_name'
|
||||
* 'key' => 'option_id/sub_key' // optional @since 2.5.1
|
||||
* )
|
||||
*/
|
||||
class FW_Option_Storage_Type_WP_Option extends FW_Option_Storage_Type {
|
||||
public function get_type() {
|
||||
return 'wp-option';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _save( $id, array $option, $value, array $params ) {
|
||||
if ($wp_option = $this->get_wp_option($option, $params)) {
|
||||
if (isset($option['fw-storage']['key'])) {
|
||||
$wp_option_value = get_option($wp_option, array());
|
||||
|
||||
fw_aks($option['fw-storage']['key'], $value, $wp_option_value);
|
||||
|
||||
update_option($wp_option, $wp_option_value, false);
|
||||
|
||||
unset($wp_option_value);
|
||||
} else {
|
||||
if (empty($value)) {
|
||||
delete_option($wp_option);
|
||||
return $value; // Preserve value (don't return default below) because it can be false|0|array()
|
||||
} else {
|
||||
update_option($wp_option, $value, false);
|
||||
}
|
||||
}
|
||||
|
||||
return fw()->backend->option_type($option['type'])->get_value_from_input(
|
||||
array('type' => $option['type']), null
|
||||
);
|
||||
} else {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _load( $id, array $option, $value, array $params ) {
|
||||
if ($wp_option = $this->get_wp_option($option, $params)) {
|
||||
if (isset($option['fw-storage']['key'])) {
|
||||
$wp_option_value = get_option($wp_option, array());
|
||||
|
||||
return fw_akg($option['fw-storage']['key'], $wp_option_value, $value);
|
||||
} else {
|
||||
return get_option($wp_option, $value);
|
||||
}
|
||||
} else {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
private function get_wp_option($option, $params) {
|
||||
$wp_option = null;
|
||||
|
||||
if (isset($params['post-id']) && wp_is_post_revision($params['post-id'])) {
|
||||
/**
|
||||
* Post revision is updated after real post update and it contains old option value
|
||||
* thus overwriting the new option value
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!empty($option['fw-storage']['wp-option'])) {
|
||||
$wp_option = $option['fw-storage']['wp-option'];
|
||||
} elseif (!empty($params['wp-option'])) {
|
||||
$wp_option = $params['wp-option'];
|
||||
}
|
||||
|
||||
if ($wp_option) {
|
||||
return $wp_option;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
<?php if (!defined('FW')) die('Forbidden');
|
||||
|
||||
/**
|
||||
* Rows with options
|
||||
*/
|
||||
class FW_Option_Type_Addable_Box extends FW_Option_Type
|
||||
{
|
||||
public function get_type()
|
||||
{
|
||||
return 'addable-box';
|
||||
}
|
||||
|
||||
protected function _get_data_for_js($id, $option, $data = array()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _enqueue_static($id, $option, $data)
|
||||
{
|
||||
static $enqueue = true;
|
||||
|
||||
if ($enqueue) {
|
||||
wp_enqueue_style(
|
||||
'fw-option-'. $this->get_type(),
|
||||
fw_get_framework_directory_uri('/includes/option-types/'. $this->get_type() .'/static/css/styles.css'),
|
||||
array(),
|
||||
fw()->manifest->get_version()
|
||||
);
|
||||
|
||||
wp_enqueue_script(
|
||||
'fw-option-'. $this->get_type(),
|
||||
fw_get_framework_directory_uri('/includes/option-types/'. $this->get_type() .'/static/js/scripts.js'),
|
||||
array('fw-events', 'jquery-ui-sortable'),
|
||||
fw()->manifest->get_version(),
|
||||
true
|
||||
);
|
||||
|
||||
$enqueue = false;
|
||||
}
|
||||
|
||||
fw()->backend->enqueue_options_static($option['box-options']);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Puts each option into a separate array
|
||||
* to keep their order inside the modal dialog
|
||||
*/
|
||||
private function transform_options($options)
|
||||
{
|
||||
$new_options = array();
|
||||
foreach ($options as $id => $option) {
|
||||
if (is_int($id)) {
|
||||
/**
|
||||
* this happens when in options array are loaded external options using fw()->theme->get_options()
|
||||
* and the array looks like this
|
||||
* array(
|
||||
* 'hello' => array('type' => 'text'), // this has string key
|
||||
* array('hi' => array('type' => 'text')) // this has int key
|
||||
* )
|
||||
*/
|
||||
$new_options[] = $option;
|
||||
} else {
|
||||
$new_options[] = array($id => $option);
|
||||
}
|
||||
}
|
||||
return $new_options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _render($id, $option, $data)
|
||||
{
|
||||
if (empty($data['value']) || !is_array($data['value'])) {
|
||||
$data['value'] = array();
|
||||
}
|
||||
|
||||
/** Prepare controls */
|
||||
{
|
||||
$controls = array_merge(
|
||||
array(
|
||||
'delete' => '<small class="dashicons dashicons-no-alt" title="'. esc_attr__('Remove', 'fw') .'"></small>'
|
||||
),
|
||||
$option['box-controls']
|
||||
);
|
||||
|
||||
// move 'delete' control to end
|
||||
{
|
||||
if (isset($controls['delete'])) {
|
||||
$_delete = $controls['delete'];
|
||||
unset($controls['delete']);
|
||||
$controls['delete'] = $_delete;
|
||||
unset($_delete);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
$box_options = array();
|
||||
|
||||
fw_collect_options( $box_options, $option['box-options'], array(
|
||||
'limit_option_types' => false,
|
||||
'limit_container_types' => apply_filters(
|
||||
'fw:option-type:addable-box:limit-container-types',
|
||||
// Use only groups and options by default
|
||||
array('group')
|
||||
),
|
||||
|
||||
'limit_level' => 1,
|
||||
) );
|
||||
}
|
||||
|
||||
$option['attr']['data-for-js'] = json_encode(array(
|
||||
'options' => $this->transform_options($box_options),
|
||||
'template' => $option['template'],
|
||||
));
|
||||
|
||||
return fw_render_view(fw_get_framework_directory('/includes/option-types/'. $this->get_type() .'/view.php'), array(
|
||||
'id' => $id,
|
||||
'option' => $option,
|
||||
'data' => $data,
|
||||
'controls' => $controls,
|
||||
'box_options' => $box_options,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _get_value_from_input($option, $input_value)
|
||||
{
|
||||
if (is_null($input_value)) {
|
||||
$value = $option['value'];
|
||||
} elseif (is_array($input_value)) {
|
||||
$option['limit'] = intval($option['limit']);
|
||||
|
||||
$value = array();
|
||||
|
||||
$box_options = fw_extract_only_options($option['box-options']);
|
||||
|
||||
foreach ($input_value as &$list_item_value) {
|
||||
$current_value = array();
|
||||
|
||||
foreach ($box_options as $id => $input_option) {
|
||||
$current_value[$id] = fw()->backend->option_type($input_option['type'])->get_value_from_input(
|
||||
$input_option,
|
||||
isset($list_item_value[$id]) ? $list_item_value[$id] : null
|
||||
);
|
||||
}
|
||||
|
||||
$value[] = $current_value;
|
||||
|
||||
if ($option['limit'] && count($value) === $option['limit']) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$value = array();
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function _get_defaults()
|
||||
{
|
||||
return array(
|
||||
'value' => array(),
|
||||
/**
|
||||
* Buttons on box head ( near delete button X )
|
||||
*
|
||||
* On control click will be triggered a custom event 'fw:option-type:addable-box:control:click'
|
||||
* on wrapper div (the one that has `.fw-option-type-addable-box` class)
|
||||
* data about control will be in event data
|
||||
*/
|
||||
'box-controls' => array(
|
||||
// 'control_id' => '<small class="dashicons dashicons-..." title="Some action"></small>'
|
||||
),
|
||||
'box-options' => array(),
|
||||
/**
|
||||
* Limit boxes that can be added
|
||||
*/
|
||||
'limit' => 0,
|
||||
/**
|
||||
* Box title backbonejs template
|
||||
* All box options are available as variables {{- box_option_id }}
|
||||
*
|
||||
* Note: Ids with - (instead of underscore _ ) will throw errors
|
||||
* because 'box-option-id' can't be converted to variable name
|
||||
*
|
||||
* Example: 'Hello {{- box_option_id }}'
|
||||
*/
|
||||
'template' => '',
|
||||
'add-button-text' => __('Add', 'fw'),
|
||||
/**
|
||||
* Makes the boxes sortable
|
||||
*
|
||||
* You can disable this in case the boxes order doesn't matter,
|
||||
* to not confuse the user that if changing the order will affect something.
|
||||
*/
|
||||
'sortable' => true,
|
||||
/**
|
||||
* Width type. Supported types:
|
||||
* - fixed
|
||||
* - full
|
||||
*/
|
||||
'width' => 'fixed',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function _get_backend_width_type()
|
||||
{
|
||||
return 'auto';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
.fw-option-type-addable-box {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-box.has-boxes.width-type-full {
|
||||
width: 9999px;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-box.has-boxes.width-type-fixed {
|
||||
width: 428px;
|
||||
/* same as .fw-backend-option-fixed-width */
|
||||
}
|
||||
|
||||
.fw-option-type-addable-box>.fw-option-boxes.ui-sortable>.fw-option-box>.fw-postbox {
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-box>.fw-option-boxes.ui-sortable>.fw-option-box>.fw-postbox>.hndle {
|
||||
cursor: move !important;
|
||||
/* to rewrite .fw-postbox h3.hndle */
|
||||
word-break: break-all;
|
||||
/* if box text is too long, do not move controls outside box */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-box>.fw-option-boxes.ui-sortable>.fw-option-box>.fw-postbox>.hndle>span {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#wpbody-content .fw-option-type-addable-box .metabox-holder {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-box>.fw-option-boxes>.fw-option-box {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-box>.fw-option-boxes.ui-sortable>.fw-option-box>.fw-postbox>.hndle span:after {
|
||||
content: '\00a0';
|
||||
/* - when title is empty, box has too small (broken) height */
|
||||
}
|
||||
|
||||
.fw-option-type-addable-box>.fw-option-boxes.ui-sortable>.fw-option-box>.fw-postbox>.hndle img {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-box .fw-backend-option-design-customizer {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
|
||||
/* Controls */
|
||||
.fw-option-type-addable-box>.fw-option-boxes>.fw-option-box .hndle .fw-html-before-title:empty {
|
||||
display: none;
|
||||
}
|
||||
.fw-option-type-addable-box>.fw-option-boxes>.fw-option-box .postbox-header h2.hndle {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
.rtl .fw-option-type-addable-box>.fw-option-boxes>.fw-option-box .hndle .fw-html-after-title {
|
||||
height: auto;
|
||||
left: 27px;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
.rtl .fw-option-type-addable-box .postbox .handlediv {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.rtl .fw-option-type-addable-box .postbox-header .hndle {
|
||||
justify-content: right;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-box>.fw-option-boxes>.fw-option-box .hndle .fw-html-after-title .fw-option-box-controls .fw-option-box-control {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-box>.fw-option-boxes>.fw-option-box .hndle .fw-html-after-title .fw-option-box-controls .fw-option-box-control-wrapper {
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
/* end: Controls */
|
||||
@@ -0,0 +1,390 @@
|
||||
jQuery(document).ready(function ($) {
|
||||
var optionTypeClass = '.fw-option-type-addable-box';
|
||||
|
||||
var methods = {
|
||||
/** Make full/prefixed event name from short name */
|
||||
makeEventName: function(shortName) {
|
||||
return 'fw:option-type:addable-box:'+ shortName;
|
||||
},
|
||||
/** Create object with useful data about box for event data */
|
||||
getBoxDataForEvent: function($box) {
|
||||
var data = {};
|
||||
|
||||
data.$box = $box;
|
||||
data.$controls = $box.find('.fw-option-box-controls:first');
|
||||
data.$options = $box.find('.fw-option-box-options:first');
|
||||
|
||||
data.$box = $box.find('.fw-postbox:first');
|
||||
data.$title = data.$box.find('> .hndle:first');
|
||||
data.$titleText = data.$title.find('> span:first');
|
||||
|
||||
return data;
|
||||
},
|
||||
/** Make boxes to be sortable */
|
||||
reInitSortable: function ($boxes) {
|
||||
try {
|
||||
$boxes.sortable('destroy');
|
||||
} catch (e) {
|
||||
// happens when sortable was not initialized before
|
||||
}
|
||||
|
||||
if (!$boxes.first().closest(optionTypeClass).hasClass('is-sortable')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var isMobile = $(document.body).hasClass('mobile');
|
||||
|
||||
$boxes.sortable({
|
||||
items: '> .fw-option-box',
|
||||
handle: '.hndle:first',
|
||||
cursor: 'move',
|
||||
placeholder: 'sortable-placeholder',
|
||||
delay: ( isMobile ? 200 : 0 ),
|
||||
distance: 2,
|
||||
tolerance: 'pointer',
|
||||
forcePlaceholderSize: true,
|
||||
axis: 'y',
|
||||
start: function(e, ui){
|
||||
// Update the height of the placeholder to match the moving item.
|
||||
{
|
||||
var height = ui.item.outerHeight();
|
||||
|
||||
height -= 2; // Subtract 2 for borders
|
||||
|
||||
ui.placeholder.height(height);
|
||||
}
|
||||
},
|
||||
update: function(){
|
||||
var optionType = $(this).closest(optionTypeClass);
|
||||
|
||||
optionType.trigger('change'); // for customizer
|
||||
|
||||
fw.options.trigger.changeForEl(optionType);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/** Init boxes controls */
|
||||
initControls: function ($boxes) {
|
||||
|
||||
$boxes.find('.fw-option-box-control').on('mouseover', function () {
|
||||
$(this).off('click');
|
||||
})
|
||||
|
||||
$boxes
|
||||
.find('.fw-option-box-controls:not(.initialized)')
|
||||
.on('click', '.fw-option-box-control', function(e){
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation(); // prevent open/close of the box (when the link is in box title bar)
|
||||
|
||||
var $control = $(this);
|
||||
var controlId = $control.attr('data-control-id');
|
||||
|
||||
switch (controlId) {
|
||||
case 'delete':
|
||||
var $option = $control.closest(optionTypeClass);
|
||||
|
||||
$control.closest('.fw-option-box').remove();
|
||||
|
||||
methods.checkLimit($option);
|
||||
methods.updateHasBoxesClass($option);
|
||||
|
||||
fw.options.trigger.changeForEl($option);
|
||||
|
||||
break;
|
||||
default:
|
||||
// custom control. trigger event for others to handle this
|
||||
$control.closest(optionTypeClass).trigger(
|
||||
methods.makeEventName('control:click'), {
|
||||
controlId: controlId,
|
||||
$control: $control,
|
||||
box: methods.getBoxDataForEvent($control.closest('.fw-option-box'))
|
||||
}
|
||||
);
|
||||
}
|
||||
})
|
||||
.addClass('initialized')
|
||||
.find('.fw-option-box-control').off('click'); // remove e.stopPropagation() added by /wp-admin/js/postbox.min.js
|
||||
},
|
||||
checkLimit: function($option) {
|
||||
var $button = $option.find('> .fw-option-boxes-controls .fw-option-boxes-add-button');
|
||||
var limit = fw.intval($button.attr('data-limit'));
|
||||
|
||||
if (limit > 0 && $option.find('> .fw-option-boxes > .fw-option-box').length >= limit) {
|
||||
$button.addClass('fw-hidden');
|
||||
} else {
|
||||
$button.removeClass('fw-hidden');
|
||||
}
|
||||
},
|
||||
updateHasBoxesClass: function($option) {
|
||||
$option[
|
||||
$option.find('> .fw-option-boxes > .fw-option-box:first').length
|
||||
? 'addClass' : 'removeClass'
|
||||
]('has-boxes');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Update box title using the 'template' option parameter and box option values
|
||||
*/
|
||||
var titleUpdater = {
|
||||
pendingClass: 'fw-option-type-addable-box-pending-title-update',
|
||||
isBusy: false,
|
||||
template: function(template, vars) {
|
||||
try {
|
||||
return _.template(
|
||||
$.trim(template),
|
||||
undefined,
|
||||
{
|
||||
evaluate: /\{\{([\s\S]+?)\}\}/g,
|
||||
interpolate: /\{\{=([\s\S]+?)\}\}/g,
|
||||
escape: /\{\{-([\s\S]+?)\}\}/g
|
||||
}
|
||||
)(vars);
|
||||
} catch (e) {
|
||||
return '[Template Error] '+ e.message;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Update the given box title, or find a pending box
|
||||
* @public
|
||||
*/
|
||||
update: function($box) {
|
||||
if (this.isBusy) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof $box == 'undefined') {
|
||||
$box = $(optionTypeClass +' .'+ this.pendingClass +':first');
|
||||
}
|
||||
|
||||
if (!$box.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var data = JSON.parse(
|
||||
$box.closest(optionTypeClass).attr('data-for-js')
|
||||
);
|
||||
|
||||
data.template = $.trim(data.template);
|
||||
|
||||
if (!data.template.length) {
|
||||
delete data;
|
||||
return;
|
||||
}
|
||||
|
||||
var $dataWrapper = $box.closest('.fw-option-box');
|
||||
|
||||
var values = $dataWrapper.attr('data-values');
|
||||
|
||||
if (values) {
|
||||
// box after refresh
|
||||
$dataWrapper.removeAttr('data-values');
|
||||
|
||||
$box.removeClass(titleUpdater.pendingClass);
|
||||
|
||||
var jsonParsedValues = JSON.parse(values) || {};
|
||||
|
||||
$box.find( '.postbox-header > .hndle span:not([class])' ).first().html(
|
||||
this.template(data.template, $.extend({}, {o: jsonParsedValues}, jsonParsedValues))
|
||||
);
|
||||
|
||||
delete data;
|
||||
delete jsonParsedValues;
|
||||
this.update();
|
||||
return;
|
||||
}
|
||||
|
||||
this.isBusy = true;
|
||||
|
||||
$.ajax({
|
||||
url: ajaxurl,
|
||||
type: 'POST',
|
||||
data: [
|
||||
'action=fw_backend_options_get_values',
|
||||
'options='+ encodeURIComponent(JSON.stringify(data.options)),
|
||||
'name_prefix='+ encodeURIComponent($dataWrapper.attr('data-name-prefix')),
|
||||
$box.find('> .inside > .fw-option-box-options').find('input, select, textarea').serialize()
|
||||
].join('&'),
|
||||
dataType: 'json'
|
||||
}).done(_.bind(function (response, status, xhr) {
|
||||
this.isBusy = false;
|
||||
$box.removeClass(titleUpdater.pendingClass);
|
||||
|
||||
var template = '';
|
||||
|
||||
if (response.success) {
|
||||
template = this.template(data.template, $.extend({}, {o: response.data.values}, response.data.values));
|
||||
} else {
|
||||
template = '[Ajax Error] '+ response.data.message
|
||||
}
|
||||
|
||||
$box.find( '.postbox-header > .hndle span:not([class])' ).first().html( template );
|
||||
|
||||
delete data;
|
||||
|
||||
this.update();
|
||||
}, this)).fail(_.bind(function (xhr, status, error) {
|
||||
this.isBusy = false;
|
||||
$box.removeClass(titleUpdater.pendingClass);
|
||||
|
||||
$box.find( '.postbox-header > .hndle span:not([class])' ).first().text( '[Server Error] ' + status + ': ' + error.message );
|
||||
|
||||
delete data;
|
||||
|
||||
this.update();
|
||||
}, this));
|
||||
}
|
||||
};
|
||||
|
||||
fwEvents.on('fw:options:init', function (data) {
|
||||
var $elements = data.$elements.find(optionTypeClass +':not(.fw-option-initialized)');
|
||||
|
||||
$elements.toArray().map(function (el) {
|
||||
fw.options.on.change(function (data) {
|
||||
if (! $(data.context).is(
|
||||
'[data-fw-option-type="addable-box"] .fw-option-boxes > .fw-option-box'
|
||||
)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Listen to just its own virtual contexts
|
||||
if (! el.contains(data.context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
fw.options.trigger.changeForEl(el);
|
||||
});
|
||||
});
|
||||
|
||||
/** Init Add button */
|
||||
$elements.on('click', '> .fw-option-boxes-controls > .fw-option-boxes-add-button', function(){
|
||||
var $button = $(this);
|
||||
var $option = $button.closest(optionTypeClass);
|
||||
var $boxes = $option.find('.fw-option-boxes:first');
|
||||
var increment = parseInt($button.attr('data-increment'));
|
||||
|
||||
var $newBox = $(
|
||||
$option.find('> .default-box-template').attr('data-template')
|
||||
.split( $button.attr('data-increment-placeholder') ).join( String(increment) )
|
||||
);
|
||||
|
||||
$button.attr('data-increment', increment + 1);
|
||||
|
||||
// animation
|
||||
{
|
||||
$newBox.addClass('fw-animation-zoom-in');
|
||||
|
||||
setTimeout(function(){
|
||||
$newBox.removeClass('fw-animation-zoom-in');
|
||||
}, 300);
|
||||
}
|
||||
|
||||
$boxes.append($newBox);
|
||||
|
||||
// Re-render wp-editor
|
||||
if (
|
||||
window.fwWpEditorRefreshIds
|
||||
&&
|
||||
$newBox.find('.fw-option-type-wp-editor:first').length
|
||||
) {
|
||||
$newBox.find(
|
||||
'.fw-option-type-wp-editor textarea'
|
||||
).toArray().map(function (textarea) {
|
||||
fwWpEditorRefreshIds(
|
||||
$(textarea).attr('id'),
|
||||
$newBox
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
methods.initControls($newBox);
|
||||
|
||||
if ($option.hasClass('is-sortable')) {
|
||||
methods.reInitSortable($boxes);
|
||||
}
|
||||
|
||||
// remove focus form "Add" button to prevent pressing space/enter to add easy many boxes
|
||||
$newBox.find('input,select,textarea').first().focus();
|
||||
|
||||
fwEvents.trigger('fw:options:init', {$elements: $newBox});
|
||||
|
||||
var box = methods.getBoxDataForEvent($newBox);
|
||||
|
||||
$option.trigger(methods.makeEventName('box:init'), {box: box});
|
||||
|
||||
methods.checkLimit($option);
|
||||
methods.updateHasBoxesClass($option);
|
||||
|
||||
fw.options.trigger.changeForEl($boxes);
|
||||
});
|
||||
|
||||
// close postboxes and attach event listener
|
||||
$elements.find('> .fw-option-boxes > .fw-option-box > .fw-postbox').addClass('closed');
|
||||
|
||||
$elements.on('fw:box:close', '> .fw-option-boxes > .fw-option-box > .fw-postbox', function(){
|
||||
// later a script will pick it by this class and will update the title via ajax
|
||||
$(this).addClass(titleUpdater.pendingClass);
|
||||
|
||||
/*
|
||||
$(this).find('> .hndle span:not([class])').first().html(
|
||||
$('<img>').attr('src', fw.img.loadingSpinner)
|
||||
);
|
||||
*/
|
||||
|
||||
titleUpdater.update($(this));
|
||||
});
|
||||
|
||||
methods.initControls($elements);
|
||||
|
||||
$elements.each(function(){
|
||||
methods.checkLimit($(this));
|
||||
});
|
||||
|
||||
$elements.addClass('fw-option-initialized');
|
||||
|
||||
setTimeout(function(){
|
||||
// executed later, after .sortable('destroy') from backend-options.js
|
||||
methods.reInitSortable($elements.find('.fw-option-boxes'));
|
||||
|
||||
// execute box:init event for existing boxes
|
||||
$elements.each(function(){
|
||||
var $option = $(this);
|
||||
|
||||
$option.find('> .fw-option-boxes > .fw-option-box').each(function(){
|
||||
$option.trigger(methods.makeEventName('box:init'), {
|
||||
box: methods.getBoxDataForEvent($(this))
|
||||
});
|
||||
})
|
||||
});
|
||||
}, 100);
|
||||
|
||||
titleUpdater.update();
|
||||
});
|
||||
|
||||
fw.options.register('addable-box', {
|
||||
startListeningForChanges: $.noop,
|
||||
getValue: function (optionDescriptor) {
|
||||
var promise = $.Deferred();
|
||||
|
||||
fw.whenAll(
|
||||
$(optionDescriptor.el).find(
|
||||
'.fw-option-boxes'
|
||||
).first().find(
|
||||
'> .fw-option-box.fw-backend-options-virtual-context'
|
||||
).toArray().map(fw.options.getContextValue)
|
||||
).then(function (valuesAsArray) {
|
||||
promise.resolve({
|
||||
value: valuesAsArray.map(function (singleContextValue) {
|
||||
return singleContextValue.value;
|
||||
}),
|
||||
|
||||
optionDescriptor: optionDescriptor
|
||||
})
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,112 @@
|
||||
<?php if (!defined('FW')) die('Forbidden');
|
||||
/**
|
||||
* @var string $id
|
||||
* @var array $option
|
||||
* @var array $data
|
||||
* @var array $controls
|
||||
* @var array $box_options
|
||||
*/
|
||||
|
||||
$attr = $option['attr'];
|
||||
unset($attr['name']);
|
||||
unset($attr['value']);
|
||||
|
||||
// generate controls html
|
||||
{
|
||||
ob_start(); ?>
|
||||
<small class="fw-option-box-controls">
|
||||
<?php foreach ($controls as $c_id => $control): ?>
|
||||
<small class="fw-option-box-control-wrapper"><a href="#" class="fw-option-box-control" data-control-id="<?php echo esc_attr($c_id) ?>" onclick="return false"><?php echo $control ?></a></small>
|
||||
<?php endforeach; ?>
|
||||
</small>
|
||||
<?php $controls_html = ob_get_clean();
|
||||
}
|
||||
|
||||
if ($option['sortable']) {
|
||||
$attr['class'] .= ' is-sortable';
|
||||
}
|
||||
|
||||
$attr['class'] .= ' width-type-'. $option['width'];
|
||||
|
||||
if (!empty($data['value'])) {
|
||||
$attr['class'] .= ' has-boxes';
|
||||
}
|
||||
?>
|
||||
<div <?php echo fw_attr_to_html($attr); ?>>
|
||||
<!-- Fixes https://github.com/ThemeFuse/Unyson/issues/1278#issuecomment-208032542 -->
|
||||
<?php echo fw()->backend->option_type('hidden')->render($id, array('value' => '~'), array(
|
||||
'id_prefix' => $data['id_prefix'],
|
||||
'name_prefix' => $data['name_prefix'],
|
||||
)); ?>
|
||||
<?php $i = 0; ?>
|
||||
<div class="fw-option-boxes metabox-holder">
|
||||
<?php foreach ($data['value'] as $value_index => &$values): ?>
|
||||
<?php $i++; ?>
|
||||
<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)) ?>">
|
||||
<?php ob_start() ?>
|
||||
<div class="fw-option-box-options fw-force-xs">
|
||||
<?php
|
||||
echo fw()->backend->render_options($box_options, $values, array(
|
||||
'id_prefix' => $data['id_prefix'] . $id .'-'. $i .'-',
|
||||
'name_prefix' => $data['name_prefix'] .'['. $id .']['. $i .']',
|
||||
));
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
echo fw()->backend->render_box(
|
||||
$data['id_prefix'] . $id .'-'. $i .'-box',
|
||||
' ',
|
||||
ob_get_clean(),
|
||||
array(
|
||||
'html_after_title' => $controls_html,
|
||||
'attr' => array(
|
||||
'class' => 'fw-option-type-addable-box-pending-title-update',
|
||||
),
|
||||
)
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
<?php endforeach; unset($values); ?>
|
||||
</div>
|
||||
<br class="default-box-template fw-hidden" data-template="<?php
|
||||
/**
|
||||
* Place template in attribute to prevent it to be treated as html
|
||||
* when this option will be used inside another option template
|
||||
*/
|
||||
|
||||
$values = array();
|
||||
|
||||
// must contain characters that will remain the same after htmlspecialchars()
|
||||
$increment_placeholder = '###-addable-box-increment-'. fw_rand_md5() .'-###';
|
||||
|
||||
echo fw_htmlspecialchars(
|
||||
'<div class="fw-option-box fw-backend-options-virtual-context" data-name-prefix="'. fw_htmlspecialchars($data['name_prefix'] .'['. $id .']['. $increment_placeholder .']') .'">'.
|
||||
fw()->backend->render_box(
|
||||
$data['id_prefix'] . $id .'-'. $increment_placeholder .'-box',
|
||||
' ',
|
||||
'<div class="fw-option-box-options fw-force-xs">'.
|
||||
fw()->backend->render_options($box_options, $values, array(
|
||||
'id_prefix' => $data['id_prefix'] . $id .'-'. $increment_placeholder .'-',
|
||||
'name_prefix' => $data['name_prefix'] .'['. $id .']['. $increment_placeholder .']',
|
||||
)).
|
||||
'</div>',
|
||||
array(
|
||||
'html_after_title' => $controls_html,
|
||||
)
|
||||
).
|
||||
'</div>'
|
||||
);
|
||||
?>">
|
||||
<div class="fw-option-boxes-controls">
|
||||
<?php
|
||||
echo fw_html_tag('button', array(
|
||||
'type' => 'button',
|
||||
'onclick' => 'return false;',
|
||||
'class' => 'button fw-option-boxes-add-button',
|
||||
'data-increment' => ++$i,
|
||||
'data-increment-placeholder' => $increment_placeholder,
|
||||
'data-limit' => intval($option['limit']),
|
||||
), fw_htmlspecialchars($option['add-button-text']));
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,102 @@
|
||||
<?php if (!defined('FW')) die('Forbidden');
|
||||
|
||||
class FW_Option_Type_Addable_Option extends FW_Option_Type
|
||||
{
|
||||
public function get_type()
|
||||
{
|
||||
return 'addable-option';
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function _get_defaults()
|
||||
{
|
||||
return array(
|
||||
'value' => array(),
|
||||
'option' => array(
|
||||
'type' => 'text',
|
||||
),
|
||||
'add-button-text' => __('Add', 'fw'),
|
||||
/**
|
||||
* Makes the options sortable
|
||||
*
|
||||
* You can disable this in case the options order doesn't matter,
|
||||
* to not confuse the user that if changing the order will affect something.
|
||||
*/
|
||||
'sortable' => true,
|
||||
);
|
||||
}
|
||||
|
||||
protected function _get_data_for_js($id, $option, $data = array()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _enqueue_static($id, $option, $data)
|
||||
{
|
||||
static $enqueue = true;
|
||||
|
||||
if ($enqueue) {
|
||||
wp_enqueue_style(
|
||||
'fw-option-'. $this->get_type(),
|
||||
fw_get_framework_directory_uri('/includes/option-types/'. $this->get_type() .'/static/css/styles.css'),
|
||||
array(),
|
||||
fw()->manifest->get_version()
|
||||
);
|
||||
|
||||
wp_enqueue_script(
|
||||
'fw-option-'. $this->get_type(),
|
||||
fw_get_framework_directory_uri('/includes/option-types/'. $this->get_type() .'/static/js/scripts.js'),
|
||||
array('fw-events', 'jquery-ui-sortable'),
|
||||
fw()->manifest->get_version(),
|
||||
true
|
||||
);
|
||||
|
||||
$enqueue = false;
|
||||
}
|
||||
|
||||
fw()->backend->option_type($option['option']['type'])->enqueue_static();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function _render($id, $option, $data)
|
||||
{
|
||||
return fw_render_view(fw_get_framework_directory('/includes/option-types/'. $this->get_type() .'/view.php'), array(
|
||||
'id' => $id,
|
||||
'option' => $option,
|
||||
'data' => $data,
|
||||
'move_img_src' => fw_get_framework_directory_uri('/static/img/sort-vertically.png'),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function _get_value_from_input($option, $input_value)
|
||||
{
|
||||
if (!is_array($input_value)) {
|
||||
return $option['value'];
|
||||
}
|
||||
|
||||
$option_type = fw()->backend->option_type($option['option']['type']);
|
||||
|
||||
$value = array();
|
||||
|
||||
foreach ($input_value as $option_input_value) {
|
||||
$value[] = $option_type->get_value_from_input(
|
||||
$option['option'],
|
||||
$option_input_value
|
||||
);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
.fw-option-type-addable-option .fw-option-type-addable-option-option:not(.ui-sortable-helper) td {
|
||||
max-width: 383px; /* .fw-backend-option-fixed-width - 45px */
|
||||
}
|
||||
|
||||
.fw-option-type-addable-option .fw-option-type-addable-option-option td,
|
||||
#edittag .form-table .fw-option-type-addable-option .fw-option-type-addable-option-option td,
|
||||
#edittag .form-table .fw-option-type-addable-option tr.sortable-placeholder td {
|
||||
padding: 0 0 15px 0;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-option .fw-option-type-addable-option-option td.td-option,
|
||||
#edittag .form-table .fw-option-type-addable-option .fw-option-type-addable-option-option td.td-option {
|
||||
padding-right: 10px;
|
||||
}
|
||||
body.rtl .fw-option-type-addable-option .fw-option-type-addable-option-option td.td-option,
|
||||
body.rtl #edittag .form-table .fw-option-type-addable-option .fw-option-type-addable-option-option td.td-option {
|
||||
padding-right: 0;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-option .fw-option-type-addable-option-option td.td-remove,
|
||||
#edittag .form-table .fw-option-type-addable-option .fw-option-type-addable-option-option td.td-remove {
|
||||
width: 10px;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-option .fw-option-type-addable-option-option td.td-remove .dashicons {
|
||||
font-size: 16px;
|
||||
line-height: 1.3;
|
||||
color: #AAAAAA;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-option .fw-option-type-addable-option-option td.td-remove .dashicons:hover {
|
||||
color: #CC0000;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-option .fw-option-type-addable-option-option td.td-move,
|
||||
#edittag .form-table .fw-option-type-addable-option .fw-option-type-addable-option-option td.td-move {
|
||||
cursor: move;
|
||||
width: 15px;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-option:not(.is-sortable) .fw-option-type-addable-option-option td.td-move {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-option tr.fw-option-type-addable-option-option.ui-sortable-helper {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-option tr.fw-option-type-addable-option-option.ui-sortable-helper:before,
|
||||
.fw-option-type-addable-option tr.fw-option-type-addable-option-option.ui-sortable-helper:after {
|
||||
display: table;
|
||||
content: " ";
|
||||
}
|
||||
|
||||
.fw-option-type-addable-option tr.fw-option-type-addable-option-option.ui-sortable-helper > td {
|
||||
display: block;
|
||||
float: left;
|
||||
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body.rtl .fw-option-type-addable-option tr.fw-option-type-addable-option-option.ui-sortable-helper > td {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-option tr.fw-option-type-addable-option-option.ui-sortable-helper td.td-option {
|
||||
width: calc(100% - 35px);
|
||||
}
|
||||
|
||||
|
||||
.fw-backend-option-input-type-addable-option .fw-option-help-in-input {
|
||||
top: 4px !important;
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
jQuery(document).ready(function ($) {
|
||||
var optionClass = '.fw-option-type-addable-option';
|
||||
|
||||
function initSortable ($options) {
|
||||
try {
|
||||
$options.sortable('destroy');
|
||||
} catch (e) {
|
||||
// happens when sortable was not initialized before
|
||||
}
|
||||
|
||||
if (! $options.first().closest(optionClass).hasClass('is-sortable')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var isMobile = $(document.body).hasClass('mobile');
|
||||
|
||||
$options.sortable({
|
||||
items: '> tbody > tr',
|
||||
handle: 'td:first',
|
||||
cursor: 'move',
|
||||
placeholder: 'sortable-placeholder',
|
||||
delay: ( isMobile ? 200 : 0 ),
|
||||
distance: 2,
|
||||
tolerance: 'pointer',
|
||||
forcePlaceholderSize: true,
|
||||
axis: 'y',
|
||||
start: function(e, ui){
|
||||
// Update the height of the placeholder to match the moving item.
|
||||
{
|
||||
var height = ui.item.outerHeight();
|
||||
|
||||
ui.placeholder.height(height);
|
||||
}
|
||||
},
|
||||
update: function(){
|
||||
$(this).closest(optionClass).trigger('change'); // for customizer
|
||||
fw.options.trigger.changeForEl($(this).closest(optionClass));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var methods = {
|
||||
/** Make full/prefixed event name from short name */
|
||||
makeEventName: function (shortName) {
|
||||
return 'fw:option-type:addable-option:' + shortName;
|
||||
}
|
||||
};
|
||||
|
||||
fwEvents.on('fw:options:init', function (data) {
|
||||
var $elements = data.$elements.find(optionClass +':not(.fw-option-initialized)');
|
||||
|
||||
$elements.toArray().map(function (el) {
|
||||
// Trigger change when one of the underlying contexts change
|
||||
fw.options.on.change(function (data) {
|
||||
if (! $(data.context).is(
|
||||
'[data-fw-option-type="addable-option"] tr.fw-option-type-addable-option-option'
|
||||
)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Listen to just its own virtual contexts
|
||||
if (! el.contains(data.context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
fw.options.trigger.changeForEl(el);
|
||||
});
|
||||
});
|
||||
|
||||
/** Init Add button */
|
||||
$elements.on('click', optionClass +'-add', function(){
|
||||
var $button = $(this);
|
||||
var $option = $button.closest(optionClass);
|
||||
var $options = $option.find(optionClass +'-options:first');
|
||||
var increment = parseInt($button.attr('data-increment'));
|
||||
|
||||
var $newOption = $(
|
||||
$option.find('.default-addable-option-template:first').attr('data-template')
|
||||
.split( $button.attr('data-increment-placeholder') ).join( String(increment) )
|
||||
);
|
||||
|
||||
// animation
|
||||
{
|
||||
$newOption.addClass('fw-animation-zoom-in');
|
||||
|
||||
setTimeout(function(){
|
||||
$newOption.removeClass('fw-animation-zoom-in');
|
||||
}, 300);
|
||||
}
|
||||
|
||||
$button.attr('data-increment', increment + 1);
|
||||
|
||||
$options.append($newOption);
|
||||
|
||||
// Re-render wp-editor
|
||||
if (
|
||||
window.fwWpEditorRefreshIds
|
||||
&&
|
||||
$newOption.find('.fw-option-type-wp-editor:first').length
|
||||
) {
|
||||
fwWpEditorRefreshIds(
|
||||
$newOption.find('.fw-option-type-wp-editor textarea:first').attr('id'),
|
||||
$newOption
|
||||
);
|
||||
}
|
||||
|
||||
// remove focus form "Add" button to prevent pressing space/enter to add easy many options
|
||||
$newOption.find('input,select,textarea').first().focus();
|
||||
|
||||
fwEvents.trigger('fw:options:init', {$elements: $newOption});
|
||||
|
||||
$option.trigger(methods.makeEventName('option:init'), {$option: $newOption});
|
||||
fw.options.trigger.changeForEl($option);
|
||||
});
|
||||
|
||||
/** Init Remove button */
|
||||
$elements.on('click', optionClass +'-remove', function(){
|
||||
fw.options.trigger.changeForEl($(this).closest(
|
||||
'[data-fw-option-type="addable-option"]'
|
||||
));
|
||||
|
||||
$(this).closest(optionClass +'-option').remove();
|
||||
});
|
||||
|
||||
$elements.each(function(){
|
||||
initSortable($elements.find(optionClass +'-options:first'));
|
||||
});
|
||||
|
||||
$elements.addClass('fw-option-initialized');
|
||||
});
|
||||
|
||||
fw.options.register('addable-option', {
|
||||
startListeningForChanges: $.noop,
|
||||
getValue: function (optionDescriptor) {
|
||||
var promise = $.Deferred();
|
||||
|
||||
fw.whenAll(
|
||||
$(optionDescriptor.el).find(
|
||||
'table.fw-option-type-addable-option-options'
|
||||
).first().find(
|
||||
'> tbody > .fw-backend-options-virtual-context'
|
||||
).toArray().map(fw.options.getContextValue)
|
||||
).then(function (valuesAsArray) {
|
||||
promise.resolve({
|
||||
value: valuesAsArray.map(function (singleContextValue) {
|
||||
return _.values(singleContextValue.value)[0];
|
||||
}),
|
||||
|
||||
optionDescriptor: optionDescriptor
|
||||
})
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php if (!defined('FW')) die('Forbidden');
|
||||
/**
|
||||
* @var string $id
|
||||
* @var array $option
|
||||
* @var array $data
|
||||
* @var array $controls
|
||||
* @var string $move_img_src
|
||||
*/
|
||||
|
||||
$attr = $option['attr'];
|
||||
unset($attr['name']);
|
||||
unset($attr['value']);
|
||||
|
||||
if ($option['sortable']) {
|
||||
$attr['class'] .= ' is-sortable';
|
||||
}
|
||||
|
||||
?>
|
||||
<div <?php echo fw_attr_to_html($attr) ?>>
|
||||
<table class="fw-option-type-addable-option-options" width="100%" cellpadding="0" cellspacing="0" border="0">
|
||||
<?php $i = 1; ?>
|
||||
<?php foreach($data['value'] as $option_value): ?>
|
||||
<tr class="fw-option-type-addable-option-option fw-backend-options-virtual-context">
|
||||
<td class="td-move">
|
||||
<img src="<?php echo esc_attr($move_img_src); ?>" width="7" />
|
||||
</td>
|
||||
<td class="td-option fw-force-xs">
|
||||
<?php
|
||||
echo fw()->backend->option_type($option['option']['type'])->render(
|
||||
$i,
|
||||
$option['option'],
|
||||
array(
|
||||
'value' => $option_value,
|
||||
'id_prefix' => $data['id_prefix'] . $id .'--option-',
|
||||
'name_prefix' => $data['name_prefix'] .'['. $id .']',
|
||||
)
|
||||
);
|
||||
|
||||
$i++;
|
||||
?>
|
||||
</td>
|
||||
<td class="td-remove">
|
||||
<a href="#" onclick="return false;" class="dashicons fw-x fw-option-type-addable-option-remove"></a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
<br class="default-addable-option-template fw-hidden" data-template="<?php
|
||||
/**
|
||||
* Place template in attribute to prevent it to be treated as html
|
||||
* when this option will be used inside another option template
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is a reference.
|
||||
* Unset before replacing with new value
|
||||
* to prevent changing value to what it refers
|
||||
*/
|
||||
unset($values);
|
||||
|
||||
$values = array();
|
||||
|
||||
// must contain characters that will remain the same after htmlspecialchars()
|
||||
$increment_placeholder = '###-addable-option-increment-'. fw_rand_md5() .'-###';
|
||||
|
||||
echo fw_htmlspecialchars(
|
||||
'<tr class="fw-option-type-addable-option-option fw-backend-options-virtual-context">
|
||||
<td class="td-move">
|
||||
<img src="'. $move_img_src .'" width="7" />
|
||||
</td>
|
||||
<td class="td-option fw-force-xs">'.
|
||||
fw()->backend->option_type($option['option']['type'])->render(
|
||||
$increment_placeholder,
|
||||
$option['option'],
|
||||
array(
|
||||
'id_prefix' => $data['id_prefix'] . $id .'--option-',
|
||||
'name_prefix' => $data['name_prefix'] .'['. $id .']',
|
||||
)
|
||||
).
|
||||
'</td>
|
||||
<td class="td-remove">
|
||||
<a href="#" onclick="return false;" class="dashicons fw-x fw-option-type-addable-option-remove"></a>
|
||||
</td>
|
||||
</tr>'
|
||||
);
|
||||
?>">
|
||||
<div><?php
|
||||
echo fw_html_tag('button', array(
|
||||
'type' => 'button',
|
||||
'class' => 'button fw-option-type-addable-option-add',
|
||||
'onclick' => 'return false;',
|
||||
'data-increment' => $i,
|
||||
'data-increment-placeholder' => $increment_placeholder,
|
||||
), fw_htmlspecialchars($option['add-button-text']));
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,219 @@
|
||||
<?php if (!defined('FW')) die('Forbidden');
|
||||
|
||||
class FW_Option_Type_Addable_Popup extends FW_Option_Type
|
||||
{
|
||||
public function get_type()
|
||||
{
|
||||
return 'addable-popup';
|
||||
}
|
||||
|
||||
public function _get_backend_width_type()
|
||||
{
|
||||
return 'fixed';
|
||||
}
|
||||
|
||||
protected function _get_data_for_js($id, $option, $data = array()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _enqueue_static($id, $option, $data)
|
||||
{
|
||||
static $enqueue = true;
|
||||
|
||||
/**
|
||||
* Use hardcoded type because this class is extended and type is changed, but the paths must be the same
|
||||
* Fixes https://github.com/ThemeFuse/Unyson/issues/1769#issuecomment-247054955
|
||||
*/
|
||||
$option_type = 'addable-popup';
|
||||
|
||||
if ($enqueue) {
|
||||
wp_enqueue_style(
|
||||
'fw-option-' . $option_type,
|
||||
fw_get_framework_directory_uri('/includes/option-types/' . $option_type . '/static/css/styles.css'),
|
||||
array('fw'),
|
||||
fw()->manifest->get_version()
|
||||
);
|
||||
|
||||
wp_enqueue_script(
|
||||
'fw-option-' . $option_type,
|
||||
fw_get_framework_directory_uri('/includes/option-types/' . $option_type . '/static/js/scripts.js'),
|
||||
array('underscore', 'fw-events', 'jquery-ui-sortable', 'fw'),
|
||||
fw()->manifest->get_version(),
|
||||
true
|
||||
);
|
||||
|
||||
$enqueue = false;
|
||||
}
|
||||
|
||||
fw()->backend->enqueue_options_static($option['popup-options']);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate option's html from option array
|
||||
* @param string $id
|
||||
* @param array $option
|
||||
* @param array $data
|
||||
* @return string HTML
|
||||
* @internal
|
||||
*/
|
||||
protected function _render($id, $option, $data)
|
||||
{
|
||||
unset($option['attr']['name'], $option['attr']['value']);
|
||||
|
||||
$option['attr']['data-for-js'] =
|
||||
/**
|
||||
* Prevent js error when the generated html is used in another option type js template with {{...}}
|
||||
* Do this trick because {{ is not escaped/encoded by fw_htmlspecialchars()
|
||||
* Fixes https://github.com/ThemeFuse/Unyson/issues/1877
|
||||
*/
|
||||
json_encode(explode('{{',
|
||||
json_encode(array(
|
||||
'title' => empty($option['popup-title']) ? $option['label'] : $option['popup-title'],
|
||||
'options' => $this->transform_options($option['popup-options']),
|
||||
'template' => $option['template'],
|
||||
'size' => $option['size'],
|
||||
'limit' => $option['limit']
|
||||
))
|
||||
));
|
||||
|
||||
$sortable_image = fw_get_framework_directory_uri('/static/img/sort-vertically.png');
|
||||
|
||||
return fw_render_view(
|
||||
fw_get_framework_directory('/includes/option-types/addable-popup/view.php'),
|
||||
compact('id', 'option', 'data', 'sortable_image')
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Puts each option into a separate array
|
||||
* to keep their order inside the modal dialog
|
||||
*/
|
||||
private function transform_options($options)
|
||||
{
|
||||
$new_options = array();
|
||||
|
||||
foreach ($options as $id => $option) {
|
||||
if (is_int($id)) {
|
||||
/**
|
||||
* this happens when in options array are loaded external options using fw()->theme->get_options()
|
||||
* and the array looks like this
|
||||
* array(
|
||||
* 'hello' => array('type' => 'text'), // this has string key
|
||||
* array('hi' => array('type' => 'text')) // this has int key
|
||||
* )
|
||||
*/
|
||||
$new_options[] = $option;
|
||||
} else {
|
||||
$new_options[] = array($id => $option);
|
||||
}
|
||||
}
|
||||
|
||||
return $new_options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract correct value for $option['value'] from input array
|
||||
* If input value is empty, will be returned $option['value']
|
||||
* @param array $option
|
||||
* @param array|string|null $input_value
|
||||
* @return string|array|int|bool Correct value
|
||||
* @internal
|
||||
*/
|
||||
protected function _get_value_from_input($option, $input_value)
|
||||
{
|
||||
if (is_null($input_value)) {
|
||||
$values = $option['value'];
|
||||
} elseif (is_array($input_value)) {
|
||||
$values = array();
|
||||
|
||||
foreach ($input_value as $elem){
|
||||
/**
|
||||
* Do JSON deconding only if $elem is not already parsed.
|
||||
* json_decode will throw an error when passing him anything
|
||||
* but a string.
|
||||
*/
|
||||
if (is_array($elem)) {
|
||||
$values[] = $elem;
|
||||
} else {
|
||||
$values[] = json_decode($elem, true);
|
||||
}
|
||||
}
|
||||
|
||||
if ( $option['limit'] = intval( $option['limit'] ) ) {
|
||||
$values = array_slice( $values, 0, $option['limit'] );
|
||||
}
|
||||
} else {
|
||||
$values = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* For e.g. option type 'unique' needs to execute _get_value_from_input() for each option
|
||||
* to prevent duplicate values
|
||||
*/
|
||||
return apply_filters('fw:option-type:addable-popup:value-from-input', $values, $option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default option array
|
||||
*
|
||||
* This makes possible an option array to have required only one parameter: array('type' => '...')
|
||||
* Other parameters are merged with array returned from this method
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* array(
|
||||
* 'value' => '',
|
||||
* ...
|
||||
* )
|
||||
* @internal
|
||||
*/
|
||||
protected function _get_defaults()
|
||||
{
|
||||
return array(
|
||||
'value' => array(),
|
||||
'popup-options' => array(
|
||||
'default' => array('type' => 'text'),
|
||||
),
|
||||
'template' => '',
|
||||
'popup-title' => null,
|
||||
'limit' => 0,
|
||||
'size' => 'small', // small, medium, large
|
||||
'add-button-text' => __('Add', 'fw'),
|
||||
/**
|
||||
* Makes the items sortable
|
||||
*
|
||||
* You can disable this in case the items order doesn't matter,
|
||||
* to not confuse the user that if changing the order will affect something.
|
||||
*/
|
||||
'sortable' => true,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class FW_Option_Type_Addable_Popup_Full extends FW_Option_Type_Addable_Popup
|
||||
{
|
||||
public function get_type()
|
||||
{
|
||||
return 'addable-popup-full';
|
||||
}
|
||||
|
||||
public function _get_backend_width_type()
|
||||
{
|
||||
return 'full';
|
||||
}
|
||||
|
||||
protected function _render($id, $option, $data)
|
||||
{
|
||||
// Use styles and scripts from parent option
|
||||
$option['attr']['class'] .= ' fw-option-type-addable-popup';
|
||||
|
||||
return parent::_render($id, $option, $data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
.fw-option-type-addable-popup .item {
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
min-height: 40px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-popup .item .content {
|
||||
padding: 12px 30px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-popup .item + .item {
|
||||
border-top: 1px dashed #E1E1E1;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-popup .items-wrapper {
|
||||
border: 1px solid #e1e1e1;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-popup .delete-item {
|
||||
position: absolute;
|
||||
right: 7px;
|
||||
top:50%;
|
||||
margin-top: -10px;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-popup .clone-item {
|
||||
position: absolute;
|
||||
right: 25px;
|
||||
top:50%;
|
||||
margin-top: -8px;
|
||||
font-size:16px;
|
||||
opacity:0.4;
|
||||
}
|
||||
.fw-option-type-addable-popup .clone-item:hover{
|
||||
opacity:0.7;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-popup .sort-item {
|
||||
position: absolute;
|
||||
left: 11px;
|
||||
top:50%;
|
||||
margin-top: -4px;
|
||||
width: 7px;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-popup .default-item,
|
||||
.fw-option-type-addable-popup:not(.is-sortable) .sort-item,
|
||||
.fw-option-type-addable-popup .items-wrapper.hide-clone .clone-item {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.fw-option-type-addable-popup:not(.is-sortable) .item .content {
|
||||
padding-left: 15px;
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
(function ($, _, fwEvents, window) {
|
||||
var addablePopup = function () {
|
||||
var $this = $(this),
|
||||
$defaultItem = $this.find('.default-item:first'),
|
||||
nodes = {
|
||||
$optionWrapper: $this,
|
||||
$addButton: $this.find('.add-new-item'),
|
||||
$itemsWrapper: $this.find('.items-wrapper'),
|
||||
getDefaultItem: function () {
|
||||
return $defaultItem.clone().removeClass('default-item').addClass('item');
|
||||
}
|
||||
},
|
||||
|
||||
data = JSON.parse(
|
||||
JSON.parse(nodes.$optionWrapper.attr('data-for-js')).join('{{') // check option php class
|
||||
),
|
||||
|
||||
utils = {
|
||||
modal: new fw.OptionsModal({
|
||||
title: data.title,
|
||||
options: data.options,
|
||||
size : data.size
|
||||
}),
|
||||
|
||||
countItems: function () {
|
||||
return nodes.$itemsWrapper.find('> .item').length;
|
||||
},
|
||||
|
||||
removeDefaultItem: function () {
|
||||
nodes.$optionWrapper.find('.default-item:first').remove();
|
||||
},
|
||||
|
||||
toogleNodes : function(){
|
||||
utils.toogleItemsWrapper();
|
||||
utils.toogleAddButton();
|
||||
utils.toogleClone();
|
||||
},
|
||||
|
||||
toogleItemsWrapper: function () {
|
||||
|
||||
if (utils.countItems() === 0) {
|
||||
nodes.$itemsWrapper.hide();
|
||||
} else {
|
||||
nodes.$itemsWrapper.show();
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
toogleAddButton: function(){
|
||||
if(data.limit !== 0 ){
|
||||
(utils.countItems() >= data.limit ) ?
|
||||
nodes.$addButton.hide() :
|
||||
nodes.$addButton.show();
|
||||
}
|
||||
},
|
||||
|
||||
toogleClone: function(){
|
||||
if(data.limit !== 0 ){
|
||||
(utils.countItems() >= data.limit ) ?
|
||||
nodes.$itemsWrapper.addClass('hide-clone') :
|
||||
nodes.$itemsWrapper.removeClass('hide-clone');
|
||||
}
|
||||
},
|
||||
|
||||
init: function () {
|
||||
utils.initItemsTemplates();
|
||||
utils.toogleNodes();
|
||||
utils.removeDefaultItem();
|
||||
utils.initSortable();
|
||||
},
|
||||
|
||||
initSortable: function () {
|
||||
if (! nodes.$optionWrapper.hasClass('is-sortable')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nodes.$itemsWrapper.sortable({
|
||||
items: '> .item',
|
||||
cursor: 'move',
|
||||
distance: 2,
|
||||
tolerance: 'pointer',
|
||||
axis: 'y',
|
||||
update: function(){
|
||||
nodes.$optionWrapper.trigger('change'); // for customizer
|
||||
fw.options.trigger.changeForEl(nodes.$optionWrapper);
|
||||
},
|
||||
start: function(e, ui){
|
||||
// Update the height of the placeholder to match the moving item.
|
||||
{
|
||||
var height = ui.item.outerHeight() - 1;
|
||||
|
||||
ui.placeholder.height(height);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
initItemsTemplates: function () {
|
||||
var $items = nodes.$itemsWrapper.find('> .item');
|
||||
|
||||
if ($items.length > 0) {
|
||||
$items.each(function () {
|
||||
utils.editItem($(this), JSON.parse($(this).find('input').val()));
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
createItem: function (values) {
|
||||
var $clonedItem = nodes.getDefaultItem(),
|
||||
$clonedInput = $clonedItem.find('.input-wrapper');
|
||||
|
||||
var $inputTemplate = $(
|
||||
$.trim($clonedInput.html())
|
||||
.split(
|
||||
nodes.$addButton.attr('data-increment-placeholder')
|
||||
)
|
||||
.join(utils.countItems())
|
||||
);
|
||||
|
||||
$inputTemplate.find('input').attr('value', JSON.stringify(values));
|
||||
|
||||
$clonedInput.children().first().replaceWith($inputTemplate);
|
||||
|
||||
var template = '';
|
||||
|
||||
try {
|
||||
/**
|
||||
* may throw error in in template is used an option id
|
||||
* added after some items was already saved
|
||||
*/
|
||||
values._context = $clonedItem.find('.content');
|
||||
|
||||
template = _.template(
|
||||
$.trim(data.template),
|
||||
undefined,
|
||||
{
|
||||
evaluate: /\{\{([\s\S]+?)\}\}/g,
|
||||
interpolate: /\{\{=([\s\S]+?)\}\}/g,
|
||||
escape: /\{\{-([\s\S]+?)\}\}/g
|
||||
}
|
||||
)(values);
|
||||
} catch (e) {
|
||||
template = '[Template Error] '+ e.message;
|
||||
}
|
||||
|
||||
$clonedItem.find('.content').html(template);
|
||||
|
||||
return $clonedItem;
|
||||
},
|
||||
|
||||
addNewItem: function (values) {
|
||||
nodes.$itemsWrapper.append(utils.createItem(values));
|
||||
},
|
||||
|
||||
editItem: function (item, values) {
|
||||
item.replaceWith(utils.createItem(values));
|
||||
}
|
||||
};
|
||||
|
||||
nodes.$itemsWrapper.on('click', '.delete-item', function (e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
$(this).closest('.item').remove();
|
||||
utils.toogleNodes();
|
||||
nodes.$optionWrapper.trigger('change'); // for customizer
|
||||
fw.options.trigger.changeForEl(nodes.$optionWrapper);
|
||||
});
|
||||
|
||||
nodes.$itemsWrapper.on('click', '.clone-item', function (e) {
|
||||
e.stopPropagation();
|
||||
var $item = $(this).closest('.item');
|
||||
var $vals = JSON.parse($($item).find('input').val());
|
||||
utils.addNewItem($vals);
|
||||
utils.toogleNodes();
|
||||
nodes.$optionWrapper.trigger('change'); // for customizer
|
||||
fw.options.trigger.changeForEl(nodes.$optionWrapper);
|
||||
});
|
||||
|
||||
nodes.$itemsWrapper.on('click', '> .item', function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
var values = {};
|
||||
var $input = $(this).find('input');
|
||||
|
||||
if ($input.length) {
|
||||
values = JSON.parse($input.val());
|
||||
}
|
||||
|
||||
utils.modal.set('edit', true);
|
||||
utils.modal.set('values', values, {silent: true});
|
||||
utils.modal.set('itemRef', $(this));
|
||||
utils.modal.open();
|
||||
});
|
||||
|
||||
nodes.$addButton.on('click', function () {
|
||||
utils.modal.set('edit', false);
|
||||
utils.modal.set('values', {}, {silent: true});
|
||||
utils.modal.open();
|
||||
});
|
||||
|
||||
utils.modal.on('change:values', function (modal, values) {
|
||||
if (!modal.get('edit')) {
|
||||
utils.addNewItem(values);
|
||||
utils.toogleNodes();
|
||||
} else {
|
||||
utils.editItem(utils.modal.get('itemRef'), values);
|
||||
}
|
||||
|
||||
nodes.$optionWrapper.trigger('change'); // for customizer
|
||||
fw.options.trigger.changeForEl(nodes.$optionWrapper);
|
||||
});
|
||||
|
||||
_.map(
|
||||
[
|
||||
'open',
|
||||
'render',
|
||||
'close'
|
||||
],
|
||||
|
||||
function (ev) {
|
||||
utils.modal.on(ev, _.partial(triggerEvent, ev));
|
||||
|
||||
function triggerEvent (eventName, modal) {
|
||||
eventName = 'fw:option-type:addable-popup:options-modal:' + eventName;
|
||||
fwEvents.trigger(eventName, { modal: this });
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$this.on('remove', function(){ // fixes https://github.com/ThemeFuse/Unyson/issues/2167
|
||||
utils.modal.frame.$el.closest('.fw-modal').remove(); // remove modal from DOM
|
||||
nodes = data = utils = undefined; // clear memory
|
||||
});
|
||||
|
||||
utils.init();
|
||||
};
|
||||
|
||||
fwEvents.on('fw:options:init', function (data) {
|
||||
data.$elements
|
||||
.find('.fw-option-type-addable-popup:not(.fw-option-initialized)').each(addablePopup)
|
||||
.addClass('fw-option-initialized');
|
||||
});
|
||||
|
||||
fw.options.register('addable-popup', {
|
||||
getValue: function (optionDescriptor) {
|
||||
var promise = $.Deferred();
|
||||
|
||||
fw.whenAll(
|
||||
$(optionDescriptor.el).find(
|
||||
'> .fw-option-type-addable-popup > .items-wrapper'
|
||||
).first().find(
|
||||
'> .item.fw-backend-options-virtual-context'
|
||||
).toArray().map(fw.options.getContextValue)
|
||||
).then(function (valuesAsArray) {
|
||||
promise.resolve({
|
||||
value: _.map(
|
||||
valuesAsArray,
|
||||
_.compose(JSON.parse, _.first, _.values, _.property('value'))
|
||||
),
|
||||
|
||||
optionDescriptor: optionDescriptor
|
||||
})
|
||||
});
|
||||
|
||||
return promise;
|
||||
},
|
||||
|
||||
startListeningForChanges: $.noop
|
||||
});
|
||||
|
||||
})(jQuery, _, fwEvents, window);
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php if (!defined('FW')) die('Forbidden');
|
||||
/**
|
||||
* @var string $id
|
||||
* @var array $option
|
||||
* @var array $data
|
||||
* @var string $sortable_image url
|
||||
*/
|
||||
$attr = $option['attr'];
|
||||
unset($attr['name']);
|
||||
unset($attr['value']);
|
||||
|
||||
if ($option['sortable']) {
|
||||
$attr['class'] .= ' is-sortable';
|
||||
}
|
||||
|
||||
// must contain characters that will remain the same after htmlspecialchars()
|
||||
$increment_placeholder = '###-addable-popup-increment-'. fw_rand_md5() .'-###';
|
||||
?>
|
||||
<div <?php echo fw_attr_to_html($attr); ?>>
|
||||
<!-- Fixes https://github.com/ThemeFuse/Unyson/issues/1278 -->
|
||||
<?php echo fw()->backend->option_type('hidden')->render($id, array('value' => '~'), array(
|
||||
'id_prefix' => $data['id_prefix'],
|
||||
'name_prefix' => $data['name_prefix'],
|
||||
)); ?>
|
||||
<div class="items-wrapper">
|
||||
<?php foreach ($data['value'] as $key => $value): ?>
|
||||
<div class="item fw-backend-options-virtual-context">
|
||||
<div class="input-wrapper">
|
||||
<?php echo fw()->backend->option_type('hidden')->render('', array('value' => json_encode($value)), array(
|
||||
'id_prefix' => $data['id_prefix'] . $id . '-' . $key . '-',
|
||||
'name_prefix' => $data['name_prefix'] . '[' . $id . ']',
|
||||
));?>
|
||||
</div>
|
||||
<img src="<?php echo esc_attr($sortable_image); ?>" class="sort-item"/>
|
||||
|
||||
<div class="content"><!-- will be populated from js --></div>
|
||||
<a href="#" class="dashicons fw-x delete-item"></a>
|
||||
<small class="dashicons dashicons-admin-page clone-item" title="<?php echo __('Clone','fw') ?>"></small>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<div class="default-item fw-backend-options-virtual-context">
|
||||
<div class="input-wrapper">
|
||||
<?php echo fw()->backend->option_type('hidden')->render('', array('value' => '[]'), array(
|
||||
'id_prefix' => $data['id_prefix'] . $id . '-' . $increment_placeholder,
|
||||
'name_prefix' => $data['name_prefix'] . '[' . $id . ']',
|
||||
)); ?>
|
||||
</div>
|
||||
<img src="<?php echo esc_attr($sortable_image); ?>" class="sort-item"/>
|
||||
|
||||
<div class="content"></div>
|
||||
<a href="#" class="dashicons fw-x delete-item"></a>
|
||||
<small class="dashicons dashicons-admin-page clone-item" title="<?php echo __('Clone','fw') ?>"></small>
|
||||
</div>
|
||||
<?php
|
||||
echo fw_html_tag('button', array(
|
||||
'type' => 'button',
|
||||
'class' => 'button add-new-item',
|
||||
'onclick' => 'return false;',
|
||||
'data-increment-placeholder' => $increment_placeholder,
|
||||
), fw_htmlspecialchars($option['add-button-text']));
|
||||
?>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
<?php if ( ! defined( 'FW' ) ) {
|
||||
die( 'Forbidden' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Background Image
|
||||
*/
|
||||
class FW_Option_Type_Background_Image extends FW_Option_Type {
|
||||
|
||||
public function get_type() {
|
||||
return 'background-image';
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function _get_defaults() {
|
||||
return array(
|
||||
'value' => '',
|
||||
'choices' => array()
|
||||
);
|
||||
}
|
||||
|
||||
protected function _get_data_for_js($id, $option, $data = array()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _enqueue_static($id, $option, $data)
|
||||
{
|
||||
wp_enqueue_style(
|
||||
'fw-option-' . $this->get_type(),
|
||||
fw_get_framework_directory_uri('/includes/option-types/' . $this->get_type() . '/static/css/styles.css'),
|
||||
array(),
|
||||
fw()->manifest->get_version()
|
||||
);
|
||||
wp_enqueue_script(
|
||||
'fw-option-' . $this->get_type(),
|
||||
fw_get_framework_directory_uri('/includes/option-types/' . $this->get_type() . '/static/js/scripts.js'),
|
||||
array( 'jquery', 'fw-events' ),
|
||||
fw()->manifest->get_version(),
|
||||
true
|
||||
);
|
||||
|
||||
/*
|
||||
* ensures that the static of option type upload
|
||||
* and image-picker is enqueued
|
||||
*/
|
||||
fw()->backend->enqueue_options_static(array(
|
||||
'background-image-dummy-upload' => array(
|
||||
'type' => 'upload'
|
||||
),
|
||||
'background-image-dummy-image-picker' => array(
|
||||
'type' => 'image-picker'
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function _render( $id, $option, $data ) {
|
||||
$option = $this->check_parameters( $option );
|
||||
$data = $this->check_data( $option, $data );
|
||||
|
||||
return fw_render_view( fw_get_framework_directory('/includes/option-types/' . $this->get_type() . '/view.php'), array(
|
||||
'id' => $id,
|
||||
'option' => $option,
|
||||
'data' => $data
|
||||
) );
|
||||
}
|
||||
|
||||
private function check_parameters( $option ) {
|
||||
|
||||
if ( empty( $option['choices'] ) || ! is_array( $option['choices'] ) ) {
|
||||
$option['choices'] = array();
|
||||
}
|
||||
if ( empty( $option['value'] ) || ! in_array( $option['value'], array_keys( $option['choices'] ) ) ) {
|
||||
$option['value'] = '';
|
||||
}
|
||||
|
||||
return $option;
|
||||
}
|
||||
|
||||
private function check_data( $option, $data ) {
|
||||
|
||||
$value = ( ! empty( $option['value'] ) ) ? $option['value'] : '';
|
||||
unset( $option['value'] );
|
||||
|
||||
$data['value'] = array_merge(
|
||||
array(
|
||||
'type' => ( ! empty( $value ) ) ? 'predefined' : 'custom',
|
||||
'predefined' => $value,
|
||||
'custom' => '',
|
||||
'data' => ( ! empty( $option['choices'][ $value ]['css'] ) ) ? $option['choices'][ $value ]['css'] : array()
|
||||
),
|
||||
(array) $data['value']
|
||||
);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function _get_value_from_input( $option, $input_value )
|
||||
{
|
||||
if (is_array($input_value)) {
|
||||
if ( empty( $input_value['type'] ) ) {
|
||||
$input_value['type'] = ( ! empty( $option['choices'] ) ) ? 'predefined' : 'custom';
|
||||
}
|
||||
|
||||
if ( $input_value['type'] === 'custom') {
|
||||
if( $attachment_id = intval($input_value['custom']) ) {
|
||||
$input_value['predefined'] = $option['value'];
|
||||
$attachment_url = wp_get_attachment_url($attachment_id);
|
||||
$input_value['data'] = array(
|
||||
'icon' => $attachment_url,
|
||||
'css' => array(
|
||||
'background-image' => 'url("' . $attachment_url . '")'
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$input_value['predefined'] = $option['value'];
|
||||
$input_value['data'] = array(
|
||||
'icon' => '',
|
||||
'css' => array()
|
||||
);
|
||||
}
|
||||
|
||||
} else {
|
||||
$input_value['predefined'] = ( isset( $input_value['predefined'] ) ) ? $input_value['predefined'] : $option['value'];
|
||||
$input_value['custom'] = '';
|
||||
$input_value['data'] = ( ! empty( $option['choices'][ $input_value['predefined'] ] ) ) ? $option['choices'][ $input_value['predefined'] ] : array();
|
||||
}
|
||||
} else {
|
||||
$input_value = $option['value'];
|
||||
}
|
||||
|
||||
return $input_value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
.fw-option-type-background-image > .type .fw-option-type-radio div {
|
||||
display: inline-block;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.fw-option-type-background-image > .predefined,
|
||||
.fw-option-type-background-image > .custom {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.fw-option-type-background-image div.fw-option-type-radio {
|
||||
margin: 0 0 9px -15px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.fw-option-type-background-image.no-choices > .type {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.fw-option-type-background-image.no-choices > .predefined,
|
||||
.fw-option-type-background-image.no-choices > .custom {
|
||||
margin-top: 0;
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
jQuery(document).ready(function ($) {
|
||||
var optionTypeClass = 'fw-option-type-background-image';
|
||||
var eventNamePrefix = 'fw:option-type:background-image:';
|
||||
|
||||
fw.options.register('background-image', {
|
||||
startListeningForChanges: jQuery.noop,
|
||||
getValue: function (optionDescriptor) {
|
||||
return {
|
||||
value: getValueForEl(optionDescriptor.el),
|
||||
optionDescriptor: optionDescriptor
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
fwEvents.on('fw:options:init', function (data) {
|
||||
var $options = data.$elements.find('.'+ optionTypeClass +':not(.initialized)');
|
||||
|
||||
$options.toArray().map(function (el) {
|
||||
/**
|
||||
* Here we start listening to events triggered by inner option
|
||||
* types. We may receive events from 3 nested option types here:
|
||||
*
|
||||
* 1. radio
|
||||
* 2. image-picker
|
||||
* 3. upload
|
||||
*/
|
||||
fw.options.on.changeByContext(el, function (optionDescriptor) {
|
||||
if (optionDescriptor.type === 'radio') {
|
||||
var $predefined = $(
|
||||
optionDescriptor.el
|
||||
).closest('.fw-inner').find('.predefined');
|
||||
|
||||
var $custom = $(
|
||||
optionDescriptor.el
|
||||
).closest('.fw-inner').find('.custom');
|
||||
|
||||
getValueForEl(el).then(function (value) {
|
||||
var type = value.type
|
||||
|
||||
if (type === 'custom') {
|
||||
$predefined.hide();
|
||||
$custom.show();
|
||||
} else {
|
||||
$predefined.show();
|
||||
$custom.hide();
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
triggerChangeAndInferValueFor(
|
||||
// Here we refer to the optionDescriptor.context
|
||||
// as to the `background-image` option type container
|
||||
optionDescriptor.context
|
||||
)
|
||||
});
|
||||
});
|
||||
|
||||
// route inner image-picker events as this option events
|
||||
{
|
||||
$options.on(
|
||||
'fw:option-type:image-picker:clicked',
|
||||
'.fw-option-type-image-picker',
|
||||
function(e, data) {
|
||||
jQuery(this).trigger(eventNamePrefix + 'clicked', data);
|
||||
}
|
||||
);
|
||||
|
||||
$options.on(
|
||||
'fw:option-type:image-picker:changed',
|
||||
'.fw-option-type-image-picker',
|
||||
function(e, data) {
|
||||
jQuery(this).trigger(eventNamePrefix + 'changed', data);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
$options.addClass('initialized');
|
||||
|
||||
function triggerChangeAndInferValueFor (el) {
|
||||
getValueForEl(el).then(function (value) {
|
||||
fw.options.trigger.changeForEl(el, {
|
||||
value: value
|
||||
});
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
function getValueForEl (el) {
|
||||
var promise = $.Deferred();
|
||||
|
||||
var optionDescriptor = fw.options.getOptionDescriptor(el);
|
||||
|
||||
fw.options.getContextValue(
|
||||
optionDescriptor.el
|
||||
).then(function (value) {
|
||||
promise.resolve(value.value);
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
});
|
||||
@@ -0,0 +1,100 @@
|
||||
<?php if ( ! defined( 'FW' ) ) {
|
||||
die( 'Forbidden' );
|
||||
}
|
||||
/**
|
||||
* @var string $id
|
||||
* @var array $option
|
||||
* @var array $data
|
||||
*/
|
||||
|
||||
{
|
||||
$wrapper_attr = $option['attr'];
|
||||
|
||||
unset(
|
||||
$wrapper_attr['value'],
|
||||
$wrapper_attr['name']
|
||||
);
|
||||
}
|
||||
|
||||
if ( empty( $option['choices'] ) ) {
|
||||
$option['choices'] = array();
|
||||
}
|
||||
|
||||
if (empty( $option['choices'] )) {
|
||||
$wrapper_attr['class'] .= ' no-choices';
|
||||
}
|
||||
|
||||
?>
|
||||
<div <?php echo fw_attr_to_html($wrapper_attr) ?>>
|
||||
<div class="type">
|
||||
<?php
|
||||
echo fw()->backend->option_type( 'radio' )->render(
|
||||
'type',
|
||||
array(
|
||||
'type' => 'radio',
|
||||
'value' => 'predefined',
|
||||
'choices' => array(
|
||||
'predefined' => __( 'Predefined images', 'fw' ),
|
||||
'custom' => __( 'Custom image', 'fw' )
|
||||
),
|
||||
),
|
||||
array(
|
||||
'value' => $data['value']['type'],
|
||||
'id_prefix' => $data['id_prefix'] . $id . '-',
|
||||
'name_prefix' => $data['name_prefix'] . '[' . $id . ']',
|
||||
)
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
// Predefined
|
||||
$choices = array();
|
||||
foreach ( $option['choices'] as $choice_key => $choice_value ) {
|
||||
$choices[ $choice_key ] = array(
|
||||
'small' => array(
|
||||
'src' => $choice_value['icon'],
|
||||
'height' => 50
|
||||
),
|
||||
'data' => array(
|
||||
'css' => $choice_value['css']
|
||||
)
|
||||
);
|
||||
}
|
||||
?>
|
||||
<div class="predefined" <?php if ($data['value']['type'] === 'custom'): ?>style="display: none;"<?php endif; ?>>
|
||||
<?php
|
||||
echo fw()->backend->option_type( 'image-picker' )->render(
|
||||
'predefined',
|
||||
array(
|
||||
'type' => 'image-picker',
|
||||
'value' => $option['value'],
|
||||
'choices' => $choices
|
||||
),
|
||||
array(
|
||||
'value' => ( $data['value']['type'] === 'predefined' ) ? $data['value']['predefined'] : $option['value'],
|
||||
'id_prefix' => $data['id_prefix'] . $id . '-',
|
||||
'name_prefix' => $data['name_prefix'] . '[' . $id . ']',
|
||||
)
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="custom" <?php if ($data['value']['type'] !== 'custom'): ?>style="display: none;"<?php endif; ?>>
|
||||
<?php
|
||||
echo fw()->backend->option_type( 'upload' )->render(
|
||||
'custom',
|
||||
array(
|
||||
'type' => 'upload'
|
||||
),
|
||||
array(
|
||||
'value' => ( $data['value']['type'] === 'custom' )
|
||||
? array('attachment_id' => $data['value']['custom'])
|
||||
: '',
|
||||
'id_prefix' => $data['id_prefix'] . $id . '-',
|
||||
'name_prefix' => $data['name_prefix'] . '[' . $id . ']',
|
||||
)
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php if (!defined('FW')) die('Forbidden');
|
||||
|
||||
/**
|
||||
* This will be returned when tried to get a not existing option type
|
||||
* to prevent fatal errors for cases when just one option type was typed wrong
|
||||
* or any other minor bug that has no sense to crash the whole site
|
||||
*/
|
||||
final class FW_Option_Type_Undefined extends FW_Option_Type {
|
||||
public function get_type() {
|
||||
return 'fw-undefined';
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _enqueue_static( $id, $option, $data ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _render( $id, $name, $data ) {
|
||||
return '/* ' . __( 'UNDEFINED OPTION TYPE', 'fw' ) . ' */';
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _get_value_from_input( $option, $input_value ) {
|
||||
return $option['value'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function _get_defaults() {
|
||||
return array(
|
||||
'value' => array()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php if (!defined('FW')) die('Forbidden');
|
||||
|
||||
/**
|
||||
* Color Picker
|
||||
*/
|
||||
class FW_Option_Type_Color_Picker extends FW_Option_Type
|
||||
{
|
||||
public function get_type()
|
||||
{
|
||||
return 'color-picker';
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _enqueue_static($id, $option, $data)
|
||||
{
|
||||
wp_enqueue_style(
|
||||
'fw-option-'. $this->get_type(),
|
||||
fw_get_framework_directory_uri('/includes/option-types/'. $this->get_type() .'/static/css/styles.css'),
|
||||
array(),
|
||||
fw()->manifest->get_version()
|
||||
);
|
||||
|
||||
wp_enqueue_script(
|
||||
'fw-option-'. $this->get_type(),
|
||||
fw_get_framework_directory_uri('/includes/option-types/'. $this->get_type() .'/static/js/scripts.js'),
|
||||
array('jquery', 'fw-events', 'wp-color-picker'),
|
||||
fw()->manifest->get_version(),
|
||||
true
|
||||
);
|
||||
|
||||
wp_localize_script(
|
||||
'fw-option-'. $this->get_type(),
|
||||
'_fw_option_type_'. str_replace('-', '_', $this->get_type()) .'_localized',
|
||||
array(
|
||||
'l10n' => array(
|
||||
'reset_to_default' => __('Reset', 'fw'),
|
||||
'reset_to_initial' => __('Reset', 'fw'),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function _render($id, $option, $data)
|
||||
{
|
||||
$option['attr']['value'] = strtolower($data['value']);
|
||||
$option['attr']['class'] .= ' code';
|
||||
$option['attr']['size'] = '7';
|
||||
$option['attr']['maxlength'] = '7';
|
||||
$option['attr']['onclick'] = 'this.select()';
|
||||
$option['attr']['data-default'] = $option['value'];
|
||||
|
||||
|
||||
$palettes = (bool) $option['palettes'];
|
||||
if ( ! empty( $option['palettes'] ) && is_array( $option['palettes'] ) ) {
|
||||
$palettes = $option['palettes'];
|
||||
}
|
||||
|
||||
$option['attr']['data-palettes'] = json_encode( $palettes );
|
||||
|
||||
return '<input type="text" '. fw_attr_to_html($option['attr']) .'>';
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function _get_value_from_input($option, $input_value)
|
||||
{
|
||||
if (
|
||||
is_null($input_value)
|
||||
||
|
||||
(
|
||||
// do not use `!is_null()` allow empty values https://github.com/ThemeFuse/Unyson/issues/2025
|
||||
!empty($input_value)
|
||||
&&
|
||||
!preg_match('/^#([a-f0-9]{3}){1,2}$/i', $input_value)
|
||||
)
|
||||
) {
|
||||
return (string)$option['value'];
|
||||
} else {
|
||||
return (string)$input_value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function _get_backend_width_type()
|
||||
{
|
||||
return 'auto';
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function _get_defaults()
|
||||
{
|
||||
return array(
|
||||
'value' => '',
|
||||
'palettes'=> true,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
input.fw-option-type-color-picker {
|
||||
width: 70px !important;
|
||||
}
|
||||
|
||||
@media (max-width: 782px) {
|
||||
input.fw-option-type-color-picker {
|
||||
width: 100px !important;
|
||||
}
|
||||
}
|
||||
|
||||
input.fw-option-type-color-picker.iris-error {
|
||||
background-color: #ffebe8;
|
||||
border-color: #c00;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.fw-option-type-color-picker-with-reset-default > .iris-palette-container {
|
||||
bottom: 27px !important;
|
||||
}
|
||||
|
||||
.fw-option-type-color-picker-iris,
|
||||
.fw-option-type-color-picker-iris.iris-picker {
|
||||
z-index: 999;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.fw-option-type-color-picker-iris .fw-option-type-color-picker-reset-default {
|
||||
width: 139px;
|
||||
margin-top: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.fw-option-type-color-picker-iris .fw-option-type-color-picker-reset-default span {
|
||||
line-height: 16px;
|
||||
padding-left: 2px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.fw-backend-option-input-type-color-picker .fw-option-help-in-input {
|
||||
top: 4px !important;
|
||||
}
|
||||
|
||||
/* Fixes https://github.com/ThemeFuse/Unyson/issues/2275 */
|
||||
#customize-controls .customize-pane-child > .customize-control:last-child > .fw-backend-customizer-option > div > .fw-backend-option-type-color-picker {
|
||||
padding-bottom: 170px;
|
||||
}
|
||||
|
||||
/* Fixes https://github.com/ThemeFuse/Unyson/issues/2905 */
|
||||
#customize-theme-controls > ul.customize-pane-child {
|
||||
height: 100% !important;
|
||||
}
|
||||
#customize-controls .customize-pane-child .customize-control:last-child .fw-backend-customizer-option .fw-backend-option-type-gradient {
|
||||
padding-bottom: 170px;
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
jQuery(document).ready(function($){
|
||||
var helpers = {
|
||||
optionClass: 'fw-option-type-color-picker',
|
||||
eventNamespace: '.fwOptionTypeColorPicker',
|
||||
colorRegex: /^#([a-f0-9]{3}){1,2}$/i,
|
||||
localized: window._fw_option_type_color_picker_localized,
|
||||
/**
|
||||
* Return true if color is dark
|
||||
* @param {string} color Accept only correct color format, e.g. #123456
|
||||
*/
|
||||
isColorValid: function (color) {
|
||||
return this.colorRegex.test(color);
|
||||
},
|
||||
isColorDark: function (color) {
|
||||
color = color.substring(1); // remove #
|
||||
|
||||
/** @link http://24ways.org/2010/calculating-color-contrast/ */
|
||||
{
|
||||
var r = parseInt(color.substr(0,2),16),
|
||||
g = parseInt(color.substr(2,2),16),
|
||||
b = parseInt(color.substr(4,2),16),
|
||||
yiq = ((r*299)+(g*587)+(b*114))/1000;
|
||||
}
|
||||
|
||||
return yiq < 128;
|
||||
},
|
||||
getInstance: function ($iris) {
|
||||
return $iris.data('a8cIris');
|
||||
},
|
||||
updatePreview: function ( $input, color ) {
|
||||
if ( this.isColorValid( color ) ) {
|
||||
$input.attr( 'style', 'background-color:' + color + ' !important; color:' + ( this.isColorDark( color ) ? '#FFFFFF' : '#000000' ) + ' !important;' );
|
||||
} else {
|
||||
$input.css( {'background-color': '', 'color': ''} );
|
||||
}
|
||||
},
|
||||
increment: 0
|
||||
};
|
||||
|
||||
fwEvents.on('fw:options:init', function (data) {
|
||||
data.$elements.find('input.'+ helpers.optionClass +':not(.initialized)').each(function(){
|
||||
var $input = $(this),
|
||||
changeTimeoutId = 0,
|
||||
eventNamespace = helpers.eventNamespace +'_'+ (++helpers.increment);
|
||||
|
||||
/**
|
||||
* Improvement: Initialized picker only on first focus
|
||||
* Do not initialize all pickers on the page, for performance reasons, maybe none of them will be opened
|
||||
*/
|
||||
$input.one('focus', function(){
|
||||
var initialValue = $input.val();
|
||||
|
||||
$input.iris({
|
||||
hide: true,
|
||||
defaultColor: false,
|
||||
clear: function(){},
|
||||
change: function(event, ui){
|
||||
/**
|
||||
* If we trigger the 'change' right here, that will block the picker (I don't know why)
|
||||
*/
|
||||
clearTimeout(changeTimeoutId);
|
||||
changeTimeoutId = setTimeout(function(){
|
||||
// prevent useless 'change' event when nothing has changed (happens right after init)
|
||||
if (initialValue !== null && $input.val() === initialValue) {
|
||||
initialValue = null;
|
||||
return;
|
||||
} else {
|
||||
initialValue = null; // make sure the above `if` is executed only once
|
||||
}
|
||||
|
||||
$input.trigger('fw:color:picker:changed', { // should be 'fw:option-type:color-picker:change'
|
||||
$element: $input,
|
||||
event : event,
|
||||
ui : ui
|
||||
});
|
||||
$input.trigger('change');
|
||||
}, 12);
|
||||
},
|
||||
palettes: JSON.parse($input.attr('data-palettes'))
|
||||
});
|
||||
|
||||
$input.addClass('iris-initialized');
|
||||
|
||||
var $picker = helpers.getInstance($input).picker;
|
||||
|
||||
$picker.addClass(helpers.optionClass +'-iris');
|
||||
|
||||
{
|
||||
var color = $input.val();
|
||||
|
||||
if (helpers.isColorValid(color)) {
|
||||
$input.iris('color', color);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide if clicked outside option
|
||||
*/
|
||||
{
|
||||
$input.parent().attr('id', 'fw-color-picker-r-'+ (++helpers.increment));
|
||||
|
||||
var originalShowCallback = helpers.getInstance($input).show;
|
||||
|
||||
helpers.getInstance($input).show = function () {
|
||||
$(document.body)
|
||||
.off('click'+ eventNamespace)
|
||||
.on('click'+ eventNamespace, function(e){
|
||||
if (!$(e.target).closest('#'+ $input.parent().attr('id')).length) {
|
||||
$(document.body).off('click'+ eventNamespace);
|
||||
$input.iris('hide');
|
||||
}
|
||||
});
|
||||
|
||||
originalShowCallback.apply(this);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* After the second hide the picker is not showing on the next focus (I don't know why)
|
||||
* Show it manually
|
||||
*/
|
||||
$input.on('focus', function(){
|
||||
if (!$picker.is(':visible')) {
|
||||
$input.iris('show');
|
||||
}
|
||||
});
|
||||
|
||||
$input.on('change keyup blur', function(){
|
||||
/**
|
||||
* iris::change is not triggered when the input is empty or color is wrong
|
||||
* we need to remove the preview from previous correct color
|
||||
*/
|
||||
helpers.updatePreview($input, $input.val());
|
||||
});
|
||||
|
||||
var $firstPalette = $picker.find('.iris-palette-container > .iris-palette:first-child');
|
||||
|
||||
/**
|
||||
* Fix style
|
||||
*/
|
||||
$firstPalette.css('margin-left', '');
|
||||
|
||||
/**
|
||||
* "Reset" color button
|
||||
*/
|
||||
$.each([{
|
||||
color: $input.attr('data-default'),
|
||||
text: helpers.localized.l10n.reset_to_default
|
||||
},{
|
||||
color: $input.val(),
|
||||
text: helpers.localized.l10n.reset_to_initial
|
||||
}], function(i, data){
|
||||
if (data.color && helpers.isColorValid(data.color)) {
|
||||
$picker.find('> .iris-picker-inner').append(''
|
||||
+ '<div class="' + helpers.optionClass + '-reset-default fw-pull-left">'
|
||||
+ /**/'<a class="iris-palette" style="'
|
||||
+ /**//**/'background-color:'+ data.color +';'
|
||||
+ /**//**/'height:' + $firstPalette.css('height') + ';'
|
||||
+ /**//**/'width:' + $firstPalette.css('width') + ';'
|
||||
+ /**//**/'"></a>'
|
||||
+ /**/'<span>' + data.text + '</span>'
|
||||
+ '</div>'
|
||||
);
|
||||
|
||||
$picker
|
||||
.on(
|
||||
'click',
|
||||
'.' + helpers.optionClass + '-reset-default',
|
||||
function(){
|
||||
$input.iris('color', $(this).find('.iris-palette').css('background-color'));
|
||||
}
|
||||
)
|
||||
.on('remove', function(){
|
||||
$(document.body).off(eventNamespace);
|
||||
})
|
||||
.addClass(helpers.optionClass + '-with-reset-default')
|
||||
.css('height', parseFloat($picker.css('height')) + 17);
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
$input.iris('show');
|
||||
});
|
||||
|
||||
helpers.updatePreview($input, $input.val());
|
||||
|
||||
$input.addClass('initialized');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,123 @@
|
||||
<?php if ( ! defined( 'FW' ) ) {
|
||||
die( 'Forbidden' );
|
||||
}
|
||||
|
||||
class FW_Option_Type_Date_Picker extends FW_Option_Type {
|
||||
private $internal_options = array();
|
||||
|
||||
public function get_type() {
|
||||
return 'date-picker';
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function _init() {
|
||||
$this->internal_options = array(
|
||||
'label' => false,
|
||||
'type' => 'text',
|
||||
'value' => ''
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function _get_backend_width_type() {
|
||||
return 'fixed';
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function _get_defaults() {
|
||||
return array(
|
||||
'value' => '',
|
||||
'monday-first' => true, // The week will begin with Monday; for Sunday, set to false
|
||||
'min-date' => date('d-m-Y'), // Minimum date will be current day, set a date in format d-m-Y as a start date, or set null for no minimum date
|
||||
'max-date' => null, // There will not be set the maximum date by default, set a date in format d-m-Y as a start date
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _enqueue_static($id, $option, $data)
|
||||
{
|
||||
$uri = fw_get_framework_directory_uri('/includes/option-types/' . $this->get_type() . '/static');
|
||||
$css_uri = $uri .'/css/datepicker.css';
|
||||
$js_uri = $uri .'/js/scripts.js';
|
||||
$date_picker_js_uri = $uri .'/js/bootstrap-datepicker.js';
|
||||
$locale_uri = ($language = substr(get_locale(), 0, 2)) != 'en'
|
||||
? $uri . '/js/locales/bootstrap-datepicker.' . $language . '.min.js'
|
||||
: null;
|
||||
|
||||
wp_enqueue_style(
|
||||
'fw-option-' . $this->get_type(),
|
||||
$css_uri,
|
||||
array(),
|
||||
fw()->manifest->get_version()
|
||||
);
|
||||
wp_enqueue_script(
|
||||
'fw-option-' . $this->get_type(),
|
||||
$js_uri,
|
||||
array('jquery', 'fw-events'),
|
||||
fw()->manifest->get_version(),
|
||||
true
|
||||
);
|
||||
wp_enqueue_script(
|
||||
'fw-option-' . $this->get_type() . '-date-picker',
|
||||
$date_picker_js_uri,
|
||||
array('jquery', 'fw-events'),
|
||||
fw()->manifest->get_version(),
|
||||
true
|
||||
);
|
||||
|
||||
if ($locale_uri) {
|
||||
wp_enqueue_script(
|
||||
'fw-option-' . $this->get_type() . '-date-picker-locale',
|
||||
$locale_uri,
|
||||
array('fw-option-' . $this->get_type() . '-date-picker'),
|
||||
fw()->manifest->get_version(),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
fw()->backend->option_type( 'text' )->enqueue_static();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id
|
||||
* @param array $option
|
||||
* @param array $data
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _render( $id, $option, $data ) {
|
||||
$language = substr(get_locale(), 0, 2);
|
||||
|
||||
$properties = array(
|
||||
'language' => $language,
|
||||
'weekStart' => ( $option['monday-first'] == true ) ? 1 : 0,
|
||||
'minDate' => ( $option['min-date'] !== null ) ? $option['min-date'] : null,
|
||||
'maxDate' => ( $option['max-date'] !== null ) ? $option['max-date'] : null,
|
||||
);
|
||||
|
||||
$option['attr']['readonly'] = 'readonly';
|
||||
$option['attr']['data-fw-option-date-picker-opts'] = json_encode( $properties );
|
||||
|
||||
return fw()->backend->option_type( 'text' )->render( $id, $option, $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function _get_value_from_input( $option, $input_value ) {
|
||||
if (is_null($input_value)) {
|
||||
$input_value = $option['value'];
|
||||
}
|
||||
|
||||
return (string)$input_value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,514 @@
|
||||
/*!
|
||||
* Datepicker for Bootstrap
|
||||
*
|
||||
* Copyright 2012 Stefan Petre
|
||||
* Improvements by Andrew Rowls
|
||||
* Licensed under the Apache License v2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*/
|
||||
.datepicker {
|
||||
padding: 4px;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
direction: ltr;
|
||||
/*.dow {
|
||||
border-top: 1px solid #ddd !important;
|
||||
}*/
|
||||
}
|
||||
.datepicker-inline {
|
||||
width: 220px;
|
||||
}
|
||||
.datepicker.datepicker-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
.datepicker.datepicker-rtl table tr td span {
|
||||
float: right;
|
||||
}
|
||||
.datepicker-dropdown {
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.datepicker-dropdown:before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
border-left: 7px solid transparent;
|
||||
border-right: 7px solid transparent;
|
||||
border-bottom: 7px solid #ccc;
|
||||
border-top: 0;
|
||||
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||
position: absolute;
|
||||
}
|
||||
.datepicker-dropdown:after {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
border-left: 6px solid transparent;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid #ffffff;
|
||||
border-top: 0;
|
||||
position: absolute;
|
||||
}
|
||||
.datepicker-dropdown.datepicker-orient-left:before {
|
||||
left: 6px;
|
||||
}
|
||||
.datepicker-dropdown.datepicker-orient-left:after {
|
||||
left: 7px;
|
||||
}
|
||||
.datepicker-dropdown.datepicker-orient-right:before {
|
||||
right: 6px;
|
||||
}
|
||||
.datepicker-dropdown.datepicker-orient-right:after {
|
||||
right: 7px;
|
||||
}
|
||||
.datepicker-dropdown.datepicker-orient-top:before {
|
||||
top: -7px;
|
||||
}
|
||||
.datepicker-dropdown.datepicker-orient-top:after {
|
||||
top: -6px;
|
||||
}
|
||||
.datepicker-dropdown.datepicker-orient-bottom:before {
|
||||
bottom: -7px;
|
||||
border-bottom: 0;
|
||||
border-top: 7px solid #999;
|
||||
}
|
||||
.datepicker-dropdown.datepicker-orient-bottom:after {
|
||||
bottom: -6px;
|
||||
border-bottom: 0;
|
||||
border-top: 6px solid #ffffff;
|
||||
}
|
||||
.datepicker > div {
|
||||
display: none;
|
||||
}
|
||||
.datepicker.days div.datepicker-days {
|
||||
display: block;
|
||||
}
|
||||
.datepicker.months div.datepicker-months {
|
||||
display: block;
|
||||
}
|
||||
.datepicker.years div.datepicker-years {
|
||||
display: block;
|
||||
}
|
||||
.datepicker table {
|
||||
margin: 0;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.datepicker td,
|
||||
.datepicker th {
|
||||
text-align: center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
}
|
||||
.table-striped .datepicker table tr td,
|
||||
.table-striped .datepicker table tr th {
|
||||
background-color: transparent;
|
||||
}
|
||||
.datepicker table tr td.day:hover,
|
||||
.datepicker table tr td.day.focused {
|
||||
background: #eeeeee;
|
||||
cursor: pointer;
|
||||
}
|
||||
.datepicker table tr td.old,
|
||||
.datepicker table tr td.new {
|
||||
color: #999999;
|
||||
}
|
||||
.datepicker table tr td.disabled,
|
||||
.datepicker table tr td.disabled:hover {
|
||||
background: none;
|
||||
color: #999999;
|
||||
cursor: default;
|
||||
}
|
||||
.datepicker table tr td.today,
|
||||
.datepicker table tr td.today:hover,
|
||||
.datepicker table tr td.today.disabled,
|
||||
.datepicker table tr td.today.disabled:hover {
|
||||
background-color: #fde19a;
|
||||
background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a);
|
||||
background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a);
|
||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));
|
||||
background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a);
|
||||
background-image: -o-linear-gradient(top, #fdd49a, #fdf59a);
|
||||
background-image: linear-gradient(top, #fdd49a, #fdf59a);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);
|
||||
border-color: #fdf59a #fdf59a #fbed50;
|
||||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||
color: #000;
|
||||
}
|
||||
.datepicker table tr td.today:hover,
|
||||
.datepicker table tr td.today:hover:hover,
|
||||
.datepicker table tr td.today.disabled:hover,
|
||||
.datepicker table tr td.today.disabled:hover:hover,
|
||||
.datepicker table tr td.today:active,
|
||||
.datepicker table tr td.today:hover:active,
|
||||
.datepicker table tr td.today.disabled:active,
|
||||
.datepicker table tr td.today.disabled:hover:active,
|
||||
.datepicker table tr td.today.active,
|
||||
.datepicker table tr td.today:hover.active,
|
||||
.datepicker table tr td.today.disabled.active,
|
||||
.datepicker table tr td.today.disabled:hover.active,
|
||||
.datepicker table tr td.today.disabled,
|
||||
.datepicker table tr td.today:hover.disabled,
|
||||
.datepicker table tr td.today.disabled.disabled,
|
||||
.datepicker table tr td.today.disabled:hover.disabled,
|
||||
.datepicker table tr td.today[disabled],
|
||||
.datepicker table tr td.today:hover[disabled],
|
||||
.datepicker table tr td.today.disabled[disabled],
|
||||
.datepicker table tr td.today.disabled:hover[disabled] {
|
||||
background-color: #fdf59a;
|
||||
}
|
||||
.datepicker table tr td.today:active,
|
||||
.datepicker table tr td.today:hover:active,
|
||||
.datepicker table tr td.today.disabled:active,
|
||||
.datepicker table tr td.today.disabled:hover:active,
|
||||
.datepicker table tr td.today.active,
|
||||
.datepicker table tr td.today:hover.active,
|
||||
.datepicker table tr td.today.disabled.active,
|
||||
.datepicker table tr td.today.disabled:hover.active {
|
||||
background-color: #fbf069 \9;
|
||||
}
|
||||
.datepicker table tr td.today:hover:hover {
|
||||
color: #000;
|
||||
}
|
||||
.datepicker table tr td.today.active:hover {
|
||||
color: #fff;
|
||||
}
|
||||
.datepicker table tr td.range,
|
||||
.datepicker table tr td.range:hover,
|
||||
.datepicker table tr td.range.disabled,
|
||||
.datepicker table tr td.range.disabled:hover {
|
||||
background: #eeeeee;
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
.datepicker table tr td.range.today,
|
||||
.datepicker table tr td.range.today:hover,
|
||||
.datepicker table tr td.range.today.disabled,
|
||||
.datepicker table tr td.range.today.disabled:hover {
|
||||
background-color: #f3d17a;
|
||||
background-image: -moz-linear-gradient(top, #f3c17a, #f3e97a);
|
||||
background-image: -ms-linear-gradient(top, #f3c17a, #f3e97a);
|
||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a));
|
||||
background-image: -webkit-linear-gradient(top, #f3c17a, #f3e97a);
|
||||
background-image: -o-linear-gradient(top, #f3c17a, #f3e97a);
|
||||
background-image: linear-gradient(top, #f3c17a, #f3e97a);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);
|
||||
border-color: #f3e97a #f3e97a #edde34;
|
||||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
.datepicker table tr td.range.today:hover,
|
||||
.datepicker table tr td.range.today:hover:hover,
|
||||
.datepicker table tr td.range.today.disabled:hover,
|
||||
.datepicker table tr td.range.today.disabled:hover:hover,
|
||||
.datepicker table tr td.range.today:active,
|
||||
.datepicker table tr td.range.today:hover:active,
|
||||
.datepicker table tr td.range.today.disabled:active,
|
||||
.datepicker table tr td.range.today.disabled:hover:active,
|
||||
.datepicker table tr td.range.today.active,
|
||||
.datepicker table tr td.range.today:hover.active,
|
||||
.datepicker table tr td.range.today.disabled.active,
|
||||
.datepicker table tr td.range.today.disabled:hover.active,
|
||||
.datepicker table tr td.range.today.disabled,
|
||||
.datepicker table tr td.range.today:hover.disabled,
|
||||
.datepicker table tr td.range.today.disabled.disabled,
|
||||
.datepicker table tr td.range.today.disabled:hover.disabled,
|
||||
.datepicker table tr td.range.today[disabled],
|
||||
.datepicker table tr td.range.today:hover[disabled],
|
||||
.datepicker table tr td.range.today.disabled[disabled],
|
||||
.datepicker table tr td.range.today.disabled:hover[disabled] {
|
||||
background-color: #f3e97a;
|
||||
}
|
||||
.datepicker table tr td.range.today:active,
|
||||
.datepicker table tr td.range.today:hover:active,
|
||||
.datepicker table tr td.range.today.disabled:active,
|
||||
.datepicker table tr td.range.today.disabled:hover:active,
|
||||
.datepicker table tr td.range.today.active,
|
||||
.datepicker table tr td.range.today:hover.active,
|
||||
.datepicker table tr td.range.today.disabled.active,
|
||||
.datepicker table tr td.range.today.disabled:hover.active {
|
||||
background-color: #efe24b \9;
|
||||
}
|
||||
.datepicker table tr td.selected,
|
||||
.datepicker table tr td.selected:hover,
|
||||
.datepicker table tr td.selected.disabled,
|
||||
.datepicker table tr td.selected.disabled:hover {
|
||||
background-color: #9e9e9e;
|
||||
background-image: -moz-linear-gradient(top, #b3b3b3, #808080);
|
||||
background-image: -ms-linear-gradient(top, #b3b3b3, #808080);
|
||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(#808080));
|
||||
background-image: -webkit-linear-gradient(top, #b3b3b3, #808080);
|
||||
background-image: -o-linear-gradient(top, #b3b3b3, #808080);
|
||||
background-image: linear-gradient(top, #b3b3b3, #808080);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);
|
||||
border-color: #808080 #808080 #595959;
|
||||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||
color: #fff;
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.datepicker table tr td.selected:hover,
|
||||
.datepicker table tr td.selected:hover:hover,
|
||||
.datepicker table tr td.selected.disabled:hover,
|
||||
.datepicker table tr td.selected.disabled:hover:hover,
|
||||
.datepicker table tr td.selected:active,
|
||||
.datepicker table tr td.selected:hover:active,
|
||||
.datepicker table tr td.selected.disabled:active,
|
||||
.datepicker table tr td.selected.disabled:hover:active,
|
||||
.datepicker table tr td.selected.active,
|
||||
.datepicker table tr td.selected:hover.active,
|
||||
.datepicker table tr td.selected.disabled.active,
|
||||
.datepicker table tr td.selected.disabled:hover.active,
|
||||
.datepicker table tr td.selected.disabled,
|
||||
.datepicker table tr td.selected:hover.disabled,
|
||||
.datepicker table tr td.selected.disabled.disabled,
|
||||
.datepicker table tr td.selected.disabled:hover.disabled,
|
||||
.datepicker table tr td.selected[disabled],
|
||||
.datepicker table tr td.selected:hover[disabled],
|
||||
.datepicker table tr td.selected.disabled[disabled],
|
||||
.datepicker table tr td.selected.disabled:hover[disabled] {
|
||||
background-color: #808080;
|
||||
}
|
||||
.datepicker table tr td.selected:active,
|
||||
.datepicker table tr td.selected:hover:active,
|
||||
.datepicker table tr td.selected.disabled:active,
|
||||
.datepicker table tr td.selected.disabled:hover:active,
|
||||
.datepicker table tr td.selected.active,
|
||||
.datepicker table tr td.selected:hover.active,
|
||||
.datepicker table tr td.selected.disabled.active,
|
||||
.datepicker table tr td.selected.disabled:hover.active {
|
||||
background-color: #666666 \9;
|
||||
}
|
||||
.datepicker table tr td.active,
|
||||
.datepicker table tr td.active:hover,
|
||||
.datepicker table tr td.active.disabled,
|
||||
.datepicker table tr td.active.disabled:hover {
|
||||
background-color: #006dcc;
|
||||
background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
|
||||
background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
|
||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
|
||||
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
|
||||
background-image: -o-linear-gradient(top, #0088cc, #0044cc);
|
||||
background-image: linear-gradient(top, #0088cc, #0044cc);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
|
||||
border-color: #0044cc #0044cc #002a80;
|
||||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||
color: #fff;
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.datepicker table tr td.active:hover,
|
||||
.datepicker table tr td.active:hover:hover,
|
||||
.datepicker table tr td.active.disabled:hover,
|
||||
.datepicker table tr td.active.disabled:hover:hover,
|
||||
.datepicker table tr td.active:active,
|
||||
.datepicker table tr td.active:hover:active,
|
||||
.datepicker table tr td.active.disabled:active,
|
||||
.datepicker table tr td.active.disabled:hover:active,
|
||||
.datepicker table tr td.active.active,
|
||||
.datepicker table tr td.active:hover.active,
|
||||
.datepicker table tr td.active.disabled.active,
|
||||
.datepicker table tr td.active.disabled:hover.active,
|
||||
.datepicker table tr td.active.disabled,
|
||||
.datepicker table tr td.active:hover.disabled,
|
||||
.datepicker table tr td.active.disabled.disabled,
|
||||
.datepicker table tr td.active.disabled:hover.disabled,
|
||||
.datepicker table tr td.active[disabled],
|
||||
.datepicker table tr td.active:hover[disabled],
|
||||
.datepicker table tr td.active.disabled[disabled],
|
||||
.datepicker table tr td.active.disabled:hover[disabled] {
|
||||
background-color: #0044cc;
|
||||
}
|
||||
.datepicker table tr td.active:active,
|
||||
.datepicker table tr td.active:hover:active,
|
||||
.datepicker table tr td.active.disabled:active,
|
||||
.datepicker table tr td.active.disabled:hover:active,
|
||||
.datepicker table tr td.active.active,
|
||||
.datepicker table tr td.active:hover.active,
|
||||
.datepicker table tr td.active.disabled.active,
|
||||
.datepicker table tr td.active.disabled:hover.active {
|
||||
background-color: #003399 \9;
|
||||
}
|
||||
.datepicker table tr td span {
|
||||
display: block;
|
||||
width: 23%;
|
||||
height: 54px;
|
||||
line-height: 54px;
|
||||
float: left;
|
||||
margin: 1%;
|
||||
cursor: pointer;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.datepicker table tr td span:hover {
|
||||
background: #eeeeee;
|
||||
}
|
||||
.datepicker table tr td span.disabled,
|
||||
.datepicker table tr td span.disabled:hover {
|
||||
background: none;
|
||||
color: #999999;
|
||||
cursor: default;
|
||||
}
|
||||
.datepicker table tr td span.active,
|
||||
.datepicker table tr td span.active:hover,
|
||||
.datepicker table tr td span.active.disabled,
|
||||
.datepicker table tr td span.active.disabled:hover {
|
||||
background-color: #006dcc;
|
||||
background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
|
||||
background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
|
||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
|
||||
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
|
||||
background-image: -o-linear-gradient(top, #0088cc, #0044cc);
|
||||
background-image: linear-gradient(top, #0088cc, #0044cc);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
|
||||
border-color: #0044cc #0044cc #002a80;
|
||||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||
color: #fff;
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.datepicker table tr td span.active:hover,
|
||||
.datepicker table tr td span.active:hover:hover,
|
||||
.datepicker table tr td span.active.disabled:hover,
|
||||
.datepicker table tr td span.active.disabled:hover:hover,
|
||||
.datepicker table tr td span.active:active,
|
||||
.datepicker table tr td span.active:hover:active,
|
||||
.datepicker table tr td span.active.disabled:active,
|
||||
.datepicker table tr td span.active.disabled:hover:active,
|
||||
.datepicker table tr td span.active.active,
|
||||
.datepicker table tr td span.active:hover.active,
|
||||
.datepicker table tr td span.active.disabled.active,
|
||||
.datepicker table tr td span.active.disabled:hover.active,
|
||||
.datepicker table tr td span.active.disabled,
|
||||
.datepicker table tr td span.active:hover.disabled,
|
||||
.datepicker table tr td span.active.disabled.disabled,
|
||||
.datepicker table tr td span.active.disabled:hover.disabled,
|
||||
.datepicker table tr td span.active[disabled],
|
||||
.datepicker table tr td span.active:hover[disabled],
|
||||
.datepicker table tr td span.active.disabled[disabled],
|
||||
.datepicker table tr td span.active.disabled:hover[disabled] {
|
||||
background-color: #0044cc;
|
||||
}
|
||||
.datepicker table tr td span.active:active,
|
||||
.datepicker table tr td span.active:hover:active,
|
||||
.datepicker table tr td span.active.disabled:active,
|
||||
.datepicker table tr td span.active.disabled:hover:active,
|
||||
.datepicker table tr td span.active.active,
|
||||
.datepicker table tr td span.active:hover.active,
|
||||
.datepicker table tr td span.active.disabled.active,
|
||||
.datepicker table tr td span.active.disabled:hover.active {
|
||||
background-color: #003399 \9;
|
||||
}
|
||||
.datepicker table tr td span.old,
|
||||
.datepicker table tr td span.new {
|
||||
color: #999999;
|
||||
}
|
||||
.datepicker th.datepicker-switch {
|
||||
width: 145px;
|
||||
}
|
||||
.datepicker thead tr:first-child th,
|
||||
.datepicker tfoot tr th {
|
||||
cursor: pointer;
|
||||
}
|
||||
.datepicker thead tr:first-child th:hover,
|
||||
.datepicker tfoot tr th:hover {
|
||||
background: #eeeeee;
|
||||
}
|
||||
.datepicker .cw {
|
||||
font-size: 10px;
|
||||
width: 12px;
|
||||
padding: 0 2px 0 5px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.datepicker thead tr:first-child th.cw {
|
||||
cursor: default;
|
||||
background-color: transparent;
|
||||
}
|
||||
.input-append.date .add-on i,
|
||||
.input-prepend.date .add-on i {
|
||||
cursor: pointer;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
.input-daterange input {
|
||||
text-align: center;
|
||||
}
|
||||
.input-daterange input:first-child {
|
||||
-webkit-border-radius: 3px 0 0 3px;
|
||||
-moz-border-radius: 3px 0 0 3px;
|
||||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
.input-daterange input:last-child {
|
||||
-webkit-border-radius: 0 3px 3px 0;
|
||||
-moz-border-radius: 0 3px 3px 0;
|
||||
border-radius: 0 3px 3px 0;
|
||||
}
|
||||
.input-daterange .add-on {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
min-width: 16px;
|
||||
height: 20px;
|
||||
padding: 4px 5px;
|
||||
font-weight: normal;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
text-shadow: 0 1px 0 #ffffff;
|
||||
vertical-align: middle;
|
||||
background-color: #eeeeee;
|
||||
border: 1px solid #ccc;
|
||||
margin-left: -5px;
|
||||
margin-right: -5px;
|
||||
}
|
||||
.datepicker.dropdown-menu {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
z-index: 1000;
|
||||
float: left;
|
||||
display: none;
|
||||
min-width: 160px;
|
||||
list-style: none;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #ccc;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
|
||||
-moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
|
||||
-webkit-background-clip: padding-box;
|
||||
-moz-background-clip: padding;
|
||||
background-clip: padding-box;
|
||||
*border-right-width: 2px;
|
||||
*border-bottom-width: 2px;
|
||||
color: #333333;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
}
|
||||
.datepicker.dropdown-menu th,
|
||||
.datepicker.datepicker-inline th,
|
||||
.datepicker.dropdown-menu td,
|
||||
.datepicker.datepicker-inline td {
|
||||
padding: 4px 5px;
|
||||
}
|
||||
1671
wp-content/plugins/unyson/framework/includes/option-types/date-picker/static/js/bootstrap-datepicker.js
vendored
Normal file
1671
wp-content/plugins/unyson/framework/includes/option-types/date-picker/static/js/bootstrap-datepicker.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.ar={days:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأحد"],daysShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت","أحد"],daysMin:["ح","ن","ث","ع","خ","ج","س","ح"],months:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthsShort:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],today:"هذا اليوم",rtl:!0}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.az={days:["Bazar","Bazar ertəsi","Çərşənbə axşamı","Çərşənbə","Cümə axşamı","Cümə","Şənbə"],daysShort:["B.","B.e","Ç.a","Ç.","C.a","C.","Ş."],daysMin:["B.","B.e","Ç.a","Ç.","C.a","C.","Ş."],months:["Yanvar","Fevral","Mart","Aprel","May","İyun","İyul","Avqust","Sentyabr","Oktyabr","Noyabr","Dekabr"],monthsShort:["Yan","Fev","Mar","Apr","May","İyun","İyul","Avq","Sen","Okt","Noy","Dek"],today:"Bu gün",weekStart:1}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.bg={days:["Неделя","Понеделник","Вторник","Сряда","Четвъртък","Петък","Събота"],daysShort:["Нед","Пон","Вто","Сря","Чет","Пет","Съб"],daysMin:["Н","П","В","С","Ч","П","С"],months:["Януари","Февруари","Март","Април","Май","Юни","Юли","Август","Септември","Октомври","Ноември","Декември"],monthsShort:["Ян","Фев","Мар","Апр","Май","Юни","Юли","Авг","Сеп","Окт","Ное","Дек"],today:"днес"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.bs={days:["Nedjelja","Ponedjeljak","Utorak","Srijeda","Četvrtak","Petak","Subota"],daysShort:["Ned","Pon","Uto","Sri","Čet","Pet","Sub"],daysMin:["N","Po","U","Sr","Č","Pe","Su"],months:["Januar","Februar","Mart","April","Maj","Juni","Juli","August","Septembar","Oktobar","Novembar","Decembar"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],today:"Danas",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.ca={days:["Diumenge","Dilluns","Dimarts","Dimecres","Dijous","Divendres","Dissabte"],daysShort:["Diu","Dil","Dmt","Dmc","Dij","Div","Dis"],daysMin:["dg","dl","dt","dc","dj","dv","ds"],months:["Gener","Febrer","Març","Abril","Maig","Juny","Juliol","Agost","Setembre","Octubre","Novembre","Desembre"],monthsShort:["Gen","Feb","Mar","Abr","Mai","Jun","Jul","Ago","Set","Oct","Nov","Des"],today:"Avui",monthsTitle:"Mesos",clear:"Esborrar",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.cs={days:["Neděle","Pondělí","Úterý","Středa","Čtvrtek","Pátek","Sobota"],daysShort:["Ned","Pon","Úte","Stř","Čtv","Pát","Sob"],daysMin:["Ne","Po","Út","St","Čt","Pá","So"],months:["Leden","Únor","Březen","Duben","Květen","Červen","Červenec","Srpen","Září","Říjen","Listopad","Prosinec"],monthsShort:["Led","Úno","Bře","Dub","Kvě","Čer","Čnc","Srp","Zář","Říj","Lis","Pro"],today:"Dnes",clear:"Vymazat",weekStart:1,format:"dd.m.yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.cy={days:["Sul","Llun","Mawrth","Mercher","Iau","Gwener","Sadwrn"],daysShort:["Sul","Llu","Maw","Mer","Iau","Gwe","Sad"],daysMin:["Su","Ll","Ma","Me","Ia","Gwe","Sa"],months:["Ionawr","Chewfror","Mawrth","Ebrill","Mai","Mehefin","Gorfennaf","Awst","Medi","Hydref","Tachwedd","Rhagfyr"],monthsShort:["Ion","Chw","Maw","Ebr","Mai","Meh","Gor","Aws","Med","Hyd","Tach","Rha"],today:"Heddiw"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.da={days:["søndag","mandag","tirsdag","onsdag","torsdag","fredag","lørdag"],daysShort:["søn","man","tir","ons","tor","fre","lør"],daysMin:["sø","ma","ti","on","to","fr","lø"],months:["januar","februar","marts","april","maj","juni","juli","august","september","oktober","november","december"],monthsShort:["jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec"],today:"I Dag",clear:"Nulstil"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.de={days:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],daysShort:["Son","Mon","Die","Mit","Don","Fre","Sam"],daysMin:["So","Mo","Di","Mi","Do","Fr","Sa"],months:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],monthsShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",monthsTitle:"Monate",clear:"Löschen",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.el={days:["Κυριακή","Δευτέρα","Τρίτη","Τετάρτη","Πέμπτη","Παρασκευή","Σάββατο"],daysShort:["Κυρ","Δευ","Τρι","Τετ","Πεμ","Παρ","Σαβ"],daysMin:["Κυ","Δε","Τρ","Τε","Πε","Πα","Σα"],months:["Ιανουάριος","Φεβρουάριος","Μάρτιος","Απρίλιος","Μάιος","Ιούνιος","Ιούλιος","Αύγουστος","Σεπτέμβριος","Οκτώβριος","Νοέμβριος","Δεκέμβριος"],monthsShort:["Ιαν","Φεβ","Μαρ","Απρ","Μάι","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Νοε","Δεκ"],today:"Σήμερα",clear:"Καθαρισμός",weekStart:1,format:"d/m/yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["en-AU"]={days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",monthsTitle:"Months",clear:"Clear",weekStart:1,format:"d/mm/yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["en-GB"]={days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",monthsTitle:"Months",clear:"Clear",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.eo={days:["dimanĉo","lundo","mardo","merkredo","ĵaŭdo","vendredo","sabato"],daysShort:["dim.","lun.","mar.","mer.","ĵaŭ.","ven.","sam."],daysMin:["d","l","ma","me","ĵ","v","s"],months:["januaro","februaro","marto","aprilo","majo","junio","julio","aŭgusto","septembro","oktobro","novembro","decembro"],monthsShort:["jan.","feb.","mar.","apr.","majo","jun.","jul.","aŭg.","sep.","okt.","nov.","dec."],today:"Hodiaŭ",clear:"Nuligi",weekStart:1,format:"yyyy-mm-dd"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.es={days:["Domingo","Lunes","Martes","Miércoles","Jueves","Viernes","Sábado"],daysShort:["Dom","Lun","Mar","Mié","Jue","Vie","Sáb"],daysMin:["Do","Lu","Ma","Mi","Ju","Vi","Sa"],months:["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"],monthsShort:["Ene","Feb","Mar","Abr","May","Jun","Jul","Ago","Sep","Oct","Nov","Dic"],today:"Hoy",monthsTitle:"Meses",clear:"Borrar",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.et={days:["Pühapäev","Esmaspäev","Teisipäev","Kolmapäev","Neljapäev","Reede","Laupäev"],daysShort:["Pühap","Esmasp","Teisip","Kolmap","Neljap","Reede","Laup"],daysMin:["P","E","T","K","N","R","L"],months:["Jaanuar","Veebruar","Märts","Aprill","Mai","Juuni","Juuli","August","September","Oktoober","November","Detsember"],monthsShort:["Jaan","Veebr","Märts","Apr","Mai","Juuni","Juuli","Aug","Sept","Okt","Nov","Dets"],today:"Täna",clear:"Tühjenda",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.eu={days:["Igandea","Astelehena","Asteartea","Asteazkena","Osteguna","Ostirala","Larunbata"],daysShort:["Ig","Al","Ar","Az","Og","Ol","Lr"],daysMin:["Ig","Al","Ar","Az","Og","Ol","Lr"],months:["Urtarrila","Otsaila","Martxoa","Apirila","Maiatza","Ekaina","Uztaila","Abuztua","Iraila","Urria","Azaroa","Abendua"],monthsShort:["Urt","Ots","Mar","Api","Mai","Eka","Uzt","Abu","Ira","Urr","Aza","Abe"],today:"Gaur"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.fa={days:["یکشنبه","دوشنبه","سهشنبه","چهارشنبه","پنجشنبه","جمعه","شنبه","یکشنبه"],daysShort:["یک","دو","سه","چهار","پنج","جمعه","شنبه","یک"],daysMin:["ی","د","س","چ","پ","ج","ش","ی"],months:["ژانویه","فوریه","مارس","آوریل","مه","ژوئن","ژوئیه","اوت","سپتامبر","اکتبر","نوامبر","دسامبر"],monthsShort:["ژان","فور","مار","آور","مه","ژون","ژوی","اوت","سپت","اکت","نوا","دسا"],today:"امروز",clear:"پاک کن",weekStart:1,format:"yyyy/mm/dd"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.fi={days:["sunnuntai","maanantai","tiistai","keskiviikko","torstai","perjantai","lauantai"],daysShort:["sun","maa","tii","kes","tor","per","lau"],daysMin:["su","ma","ti","ke","to","pe","la"],months:["tammikuu","helmikuu","maaliskuu","huhtikuu","toukokuu","kesäkuu","heinäkuu","elokuu","syyskuu","lokakuu","marraskuu","joulukuu"],monthsShort:["tam","hel","maa","huh","tou","kes","hei","elo","syy","lok","mar","jou"],today:"tänään",clear:"Tyhjennä",weekStart:1,format:"d.m.yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.fo={days:["Sunnudagur","Mánadagur","Týsdagur","Mikudagur","Hósdagur","Fríggjadagur","Leygardagur"],daysShort:["Sun","Mán","Týs","Mik","Hós","Frí","Ley"],daysMin:["Su","Má","Tý","Mi","Hó","Fr","Le"],months:["Januar","Februar","Marts","Apríl","Mei","Juni","Juli","August","Septembur","Oktobur","Novembur","Desembur"],monthsShort:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Aug","Sep","Okt","Nov","Des"],today:"Í Dag",clear:"Reinsa"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.fr={days:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],daysShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],daysMin:["D","L","Ma","Me","J","V","S"],months:["Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Septembre","Octobre","Novembre","Décembre"],monthsShort:["Jan","Fév","Mar","Avr","Mai","Jui","Jul","Aou","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",monthsTitle:"Mois",clear:"Effacer",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.fr={days:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],daysShort:["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],daysMin:["d","l","ma","me","j","v","s"],months:["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],monthsShort:["janv.","févr.","mars","avril","mai","juin","juil.","août","sept.","oct.","nov.","déc."],today:"Aujourd'hui",monthsTitle:"Mois",clear:"Effacer",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.gl={days:["Domingo","Luns","Martes","Mércores","Xoves","Venres","Sábado"],daysShort:["Dom","Lun","Mar","Mér","Xov","Ven","Sáb"],daysMin:["Do","Lu","Ma","Me","Xo","Ve","Sa"],months:["Xaneiro","Febreiro","Marzo","Abril","Maio","Xuño","Xullo","Agosto","Setembro","Outubro","Novembro","Decembro"],monthsShort:["Xan","Feb","Mar","Abr","Mai","Xun","Xul","Ago","Sep","Out","Nov","Dec"],today:"Hoxe",clear:"Limpar",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.he={days:["ראשון","שני","שלישי","רביעי","חמישי","שישי","שבת","ראשון"],daysShort:["א","ב","ג","ד","ה","ו","ש","א"],daysMin:["א","ב","ג","ד","ה","ו","ש","א"],months:["ינואר","פברואר","מרץ","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"],monthsShort:["ינו","פבר","מרץ","אפר","מאי","יונ","יול","אוג","ספט","אוק","נוב","דצמ"],today:"היום",rtl:!0}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.hr={days:["Nedjelja","Ponedjeljak","Utorak","Srijeda","Četvrtak","Petak","Subota"],daysShort:["Ned","Pon","Uto","Sri","Čet","Pet","Sub"],daysMin:["Ne","Po","Ut","Sr","Če","Pe","Su"],months:["Siječanj","Veljača","Ožujak","Travanj","Svibanj","Lipanj","Srpanj","Kolovoz","Rujan","Listopad","Studeni","Prosinac"],monthsShort:["Sij","Velj","Ožu","Tra","Svi","Lip","Srp","Kol","Ruj","Lis","Stu","Pro"],today:"Danas"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.hu={days:["vasárnap","hétfő","kedd","szerda","csütörtök","péntek","szombat"],daysShort:["vas","hét","ked","sze","csü","pén","szo"],daysMin:["V","H","K","Sze","Cs","P","Szo"],months:["január","február","március","április","május","június","július","augusztus","szeptember","október","november","december"],monthsShort:["jan","feb","már","ápr","máj","jún","júl","aug","sze","okt","nov","dec"],today:"ma",weekStart:1,clear:"töröl",titleFormat:"yyyy. MM",format:"yyyy.mm.dd"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.hy={days:["Կիրակի","Երկուշաբթի","Երեքշաբթի","Չորեքշաբթի","Հինգշաբթի","Ուրբաթ","Շաբաթ"],daysShort:["Կրկ","Երկ","Երք","Չրք","Հնգ","Ուր","Շբթ"],daysMin:["Կրկ","Երկ","Երք","Չրք","Հնգ","Ուր","Շբթ"],months:["Հունվար","Փետրվար","Մարտ","Ապրիլ","Մայիս","Հունիս","Հուլիս","Օգոստոս","Սեպտեմբեր","Հոկտեմբեր","Նոյեմբեր","Դեկտեմբեր"],monthsShort:["Հուն","Փետ","Մար","Ապր","Մայ","Հնս","Հլս","Օգս","Սեպ","Հոկ","Նմբ","Դեկ"],today:"Այսօր",clear:"Ջնջել",format:"dd.mm.yyyy",weekStart:1}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.id={days:["Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu"],daysShort:["Mgu","Sen","Sel","Rab","Kam","Jum","Sab"],daysMin:["Mg","Sn","Sl","Ra","Ka","Ju","Sa"],months:["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember"],monthsShort:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Ags","Sep","Okt","Nov","Des"],today:"Hari Ini",clear:"Kosongkan"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.is={days:["Sunnudagur","Mánudagur","Þriðjudagur","Miðvikudagur","Fimmtudagur","Föstudagur","Laugardagur"],daysShort:["Sun","Mán","Þri","Mið","Fim","Fös","Lau"],daysMin:["Su","Má","Þr","Mi","Fi","Fö","La"],months:["Janúar","Febrúar","Mars","Apríl","Maí","Júní","Júlí","Ágúst","September","Október","Nóvember","Desember"],monthsShort:["Jan","Feb","Mar","Apr","Maí","Jún","Júl","Ágú","Sep","Okt","Nóv","Des"],today:"Í Dag"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.it={days:["Domenica","Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato"],daysShort:["Dom","Lun","Mar","Mer","Gio","Ven","Sab"],daysMin:["Do","Lu","Ma","Me","Gi","Ve","Sa"],months:["Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","Agosto","Settembre","Ottobre","Novembre","Dicembre"],monthsShort:["Gen","Feb","Mar","Apr","Mag","Giu","Lug","Ago","Set","Ott","Nov","Dic"],today:"Oggi",clear:"Cancella",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.it={days:["Domenica","Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato"],daysShort:["Dom","Lun","Mar","Mer","Gio","Ven","Sab"],daysMin:["Do","Lu","Ma","Me","Gi","Ve","Sa"],months:["Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","Agosto","Settembre","Ottobre","Novembre","Dicembre"],monthsShort:["Gen","Feb","Mar","Apr","Mag","Giu","Lug","Ago","Set","Ott","Nov","Dic"],today:"Oggi",monthsTitle:"Mesi",clear:"Cancella",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.ja={days:["日曜","月曜","火曜","水曜","木曜","金曜","土曜"],daysShort:["日","月","火","水","木","金","土"],daysMin:["日","月","火","水","木","金","土"],months:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],monthsShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],today:"今日",format:"yyyy/mm/dd",titleFormat:"yyyy年mm月",clear:"クリア"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.ka={days:["კვირა","ორშაბათი","სამშაბათი","ოთხშაბათი","ხუთშაბათი","პარასკევი","შაბათი"],daysShort:["კვი","ორშ","სამ","ოთხ","ხუთ","პარ","შაბ"],daysMin:["კვ","ორ","სა","ოთ","ხუ","პა","შა"],months:["იანვარი","თებერვალი","მარტი","აპრილი","მაისი","ივნისი","ივლისი","აგვისტო","სექტემბერი","ოქტომები","ნოემბერი","დეკემბერი"],monthsShort:["იან","თებ","მარ","აპრ","მაი","ივნ","ივლ","აგვ","სექ","ოქტ","ნოე","დეკ"],today:"დღეს",clear:"გასუფთავება",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.kh={days:["អាទិត្យ","ចន្ទ","អង្គារ","ពុធ","ព្រហស្បតិ៍","សុក្រ","សៅរ៍","អាទិត្យ"],daysShort:["អា.ទិ","ចន្ទ","អង្គារ","ពុធ","ព្រ.ហ","សុក្រ","សៅរ៍","អា.ទិ"],daysMin:["អា.ទិ","ចន្ទ","អង្គារ","ពុធ","ព្រ.ហ","សុក្រ","សៅរ៍","អា.ទិ"],months:["មករា","កុម្ភះ","មិនា","មេសា","ឧសភា","មិថុនា","កក្កដា","សីហា","កញ្ញា","តុលា","វិច្ឆិកា","ធ្នូ"],monthsShort:["មករា","កុម្ភះ","មិនា","មេសា","ឧសភា","មិថុនា","កក្កដា","សីហា","កញ្ញា","តុលា","វិច្ឆិកា","ធ្នូ"],today:"ថ្ងៃនេះ",clear:"សំអាត"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.kk={days:["Жексенбі","Дүйсенбі","Сейсенбі","Сәрсенбі","Бейсенбі","Жұма","Сенбі"],daysShort:["Жек","Дүй","Сей","Сәр","Бей","Жұм","Сен"],daysMin:["Жк","Дс","Сс","Ср","Бс","Жм","Сн"],months:["Қаңтар","Ақпан","Наурыз","Сәуір","Мамыр","Маусым","Шілде","Тамыз","Қыркүйек","Қазан","Қараша","Желтоқсан"],monthsShort:["Қаң","Ақп","Нау","Сәу","Мамыр","Мау","Шлд","Тмз","Қыр","Қзн","Қар","Жел"],today:"Бүгін",weekStart:1}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.ko={days:["일요일","월요일","화요일","수요일","목요일","금요일","토요일"],daysShort:["일","월","화","수","목","금","토"],daysMin:["일","월","화","수","목","금","토"],months:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],monthsShort:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],today:"오늘",clear:"삭제",format:"yyyy-mm-dd",titleFormat:"yyyy년mm월",weekStart:0}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.kr={days:["일요일","월요일","화요일","수요일","목요일","금요일","토요일"],daysShort:["일","월","화","수","목","금","토"],daysMin:["일","월","화","수","목","금","토"],months:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],monthsShort:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"]}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.lt={days:["Sekmadienis","Pirmadienis","Antradienis","Trečiadienis","Ketvirtadienis","Penktadienis","Šeštadienis"],daysShort:["S","Pr","A","T","K","Pn","Š"],daysMin:["Sk","Pr","An","Tr","Ke","Pn","Št"],months:["Sausis","Vasaris","Kovas","Balandis","Gegužė","Birželis","Liepa","Rugpjūtis","Rugsėjis","Spalis","Lapkritis","Gruodis"],monthsShort:["Sau","Vas","Kov","Bal","Geg","Bir","Lie","Rugp","Rugs","Spa","Lap","Gru"],today:"Šiandien",monthsTitle:"Mėnesiai",clear:"Išvalyti",weekStart:1,format:"yyyy-mm-dd"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.lv={days:["Svētdiena","Pirmdiena","Otrdiena","Trešdiena","Ceturtdiena","Piektdiena","Sestdiena"],daysShort:["Sv","P","O","T","C","Pk","S"],daysMin:["Sv","Pr","Ot","Tr","Ce","Pk","Se"],months:["Janvāris","Februāris","Marts","Aprīlis","Maijs","Jūnijs","Jūlijs","Augusts","Septembris","Oktobris","Novembris","Decembris"],monthsShort:["Jan","Feb","Mar","Apr","Mai","Jūn","Jūl","Aug","Sep","Okt","Nov","Dec"],today:"Šodien",weekStart:1}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.me={days:["Nedjelja","Ponedjeljak","Utorak","Srijeda","Četvrtak","Petak","Subota"],daysShort:["Ned","Pon","Uto","Sri","Čet","Pet","Sub"],daysMin:["Ne","Po","Ut","Sr","Če","Pe","Su"],months:["Januar","Februar","Mart","April","Maj","Jun","Jul","Avgust","Septembar","Oktobar","Novembar","Decembar"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],today:"Danas",weekStart:1,clear:"Izbriši",format:"dd.mm.yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.mk={days:["Недела","Понеделник","Вторник","Среда","Четврток","Петок","Сабота"],daysShort:["Нед","Пон","Вто","Сре","Чет","Пет","Саб"],daysMin:["Не","По","Вт","Ср","Че","Пе","Са"],months:["Јануари","Февруари","Март","Април","Мај","Јуни","Јули","Август","Септември","Октомври","Ноември","Декември"],monthsShort:["Јан","Фев","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Ное","Дек"],today:"Денес",format:"dd.mm.yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.mn={days:["Ням","Даваа","Мягмар","Лхагва","Пүрэв","Баасан","Бямба"],daysShort:["Ням","Дав","Мяг","Лха","Пүр","Баа","Бям"],daysMin:["Ня","Да","Мя","Лх","Пү","Ба","Бя"],months:["Хулгана","Үхэр","Бар","Туулай","Луу","Могой","Морь","Хонь","Бич","Тахиа","Нохой","Гахай"],monthsShort:["Хул","Үхэ","Бар","Туу","Луу","Мог","Мор","Хон","Бич","Тах","Нох","Гах"],today:"Өнөөдөр",clear:"Тодорхой",format:"yyyy.mm.dd",weekStart:1}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.ms={days:["Ahad","Isnin","Selasa","Rabu","Khamis","Jumaat","Sabtu"],daysShort:["Aha","Isn","Sel","Rab","Kha","Jum","Sab"],daysMin:["Ah","Is","Se","Ra","Kh","Ju","Sa"],months:["Januari","Februari","Mac","April","Mei","Jun","Julai","Ogos","September","Oktober","November","Disember"],monthsShort:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Ogo","Sep","Okt","Nov","Dis"],today:"Hari Ini",clear:"Bersihkan"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.nb={days:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag"],daysShort:["Søn","Man","Tir","Ons","Tor","Fre","Lør"],daysMin:["Sø","Ma","Ti","On","To","Fr","Lø"],months:["Januar","Februar","Mars","April","Mai","Juni","Juli","August","September","Oktober","November","Desember"],monthsShort:["Jan","Feb","Mar","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Des"],today:"I Dag",format:"dd.mm.yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["nl-BE"]={days:["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],daysShort:["zo","ma","di","wo","do","vr","za"],daysMin:["zo","ma","di","wo","do","vr","za"],months:["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],monthsShort:["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"],today:"Vandaag",monthsTitle:"Maanden",clear:"Leegmaken",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.nl={days:["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],daysShort:["zo","ma","di","wo","do","vr","za"],daysMin:["zo","ma","di","wo","do","vr","za"],months:["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],monthsShort:["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"],today:"Vandaag",monthsTitle:"Maanden",clear:"Wissen",weekStart:1,format:"dd-mm-yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.no={days:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag"],daysShort:["Søn","Man","Tir","Ons","Tor","Fre","Lør"],daysMin:["Sø","Ma","Ti","On","To","Fr","Lø"],months:["Januar","Februar","Mars","April","Mai","Juni","Juli","August","September","Oktober","November","Desember"],monthsShort:["Jan","Feb","Mar","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Des"],today:"I dag",clear:"Nullstill",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.pl={days:["niedziela","poniedziałek","wtorek","środa","czwartek","piątek","sobota"],daysShort:["niedz.","pon.","wt.","śr.","czw.","piąt.","sob."],daysMin:["ndz.","pn.","wt.","śr.","czw.","pt.","sob."],months:["styczeń","luty","marzec","kwiecień","maj","czerwiec","lipiec","sierpień","wrzesień","październik","listopad","grudzień"],monthsShort:["sty.","lut.","mar.","kwi.","maj","cze.","lip.","sie.","wrz.","paź.","lis.","gru."],today:"dzisiaj",weekStart:1,clear:"wyczyść",format:"dd.mm.yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["pt-BR"]={days:["Domingo","Segunda","Terça","Quarta","Quinta","Sexta","Sábado"],daysShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],daysMin:["Do","Se","Te","Qu","Qu","Se","Sa"],months:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthsShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],today:"Hoje",monthsTitle:"Meses",clear:"Limpar",format:"dd/mm/yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.pt={days:["Domingo","Segunda","Terça","Quarta","Quinta","Sexta","Sábado"],daysShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],daysMin:["Do","Se","Te","Qu","Qu","Se","Sa"],months:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthsShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],today:"Hoje",monthsTitle:"Meses",clear:"Limpar",format:"dd/mm/yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.ro={days:["Duminică","Luni","Marţi","Miercuri","Joi","Vineri","Sâmbătă"],daysShort:["Dum","Lun","Mar","Mie","Joi","Vin","Sâm"],daysMin:["Du","Lu","Ma","Mi","Jo","Vi","Sâ"],months:["Ianuarie","Februarie","Martie","Aprilie","Mai","Iunie","Iulie","August","Septembrie","Octombrie","Noiembrie","Decembrie"],monthsShort:["Ian","Feb","Mar","Apr","Mai","Iun","Iul","Aug","Sep","Oct","Nov","Dec"],today:"Astăzi",clear:"Șterge",weekStart:1}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["rs-latin"]={days:["Nedelja","Ponedeljak","Utorak","Sreda","Četvrtak","Petak","Subota"],daysShort:["Ned","Pon","Uto","Sre","Čet","Pet","Sub"],daysMin:["N","Po","U","Sr","Č","Pe","Su"],months:["Januar","Februar","Mart","April","Maj","Jun","Jul","Avgust","Septembar","Oktobar","Novembar","Decembar"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],today:"Danas",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.rs={days:["Недеља","Понедељак","Уторак","Среда","Четвртак","Петак","Субота"],daysShort:["Нед","Пон","Уто","Сре","Чет","Пет","Суб"],daysMin:["Н","По","У","Ср","Ч","Пе","Су"],months:["Јануар","Фебруар","Март","Април","Мај","Јун","Јул","Август","Септембар","Октобар","Новембар","Децембар"],monthsShort:["Јан","Феб","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Нов","Дец"],today:"Данас",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.ru={days:["Воскресенье","Понедельник","Вторник","Среда","Четверг","Пятница","Суббота"],daysShort:["Вск","Пнд","Втр","Срд","Чтв","Птн","Суб"],daysMin:["Вс","Пн","Вт","Ср","Чт","Пт","Сб"],months:["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],monthsShort:["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"],today:"Сегодня",clear:"Очистить",format:"dd.mm.yyyy",weekStart:1}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.sk={days:["Nedeľa","Pondelok","Utorok","Streda","Štvrtok","Piatok","Sobota"],daysShort:["Ned","Pon","Uto","Str","Štv","Pia","Sob"],daysMin:["Ne","Po","Ut","St","Št","Pia","So"],months:["Január","Február","Marec","Apríl","Máj","Jún","Júl","August","September","Október","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Máj","Jún","Júl","Aug","Sep","Okt","Nov","Dec"],today:"Dnes",clear:"Vymazať",weekStart:1,format:"d.m.yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.sl={days:["Nedelja","Ponedeljek","Torek","Sreda","Četrtek","Petek","Sobota"],daysShort:["Ned","Pon","Tor","Sre","Čet","Pet","Sob"],daysMin:["Ne","Po","To","Sr","Če","Pe","So"],months:["Januar","Februar","Marec","April","Maj","Junij","Julij","Avgust","September","Oktober","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],today:"Danes"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.sq={days:["E Diel","E Hënë","E Martē","E Mërkurë","E Enjte","E Premte","E Shtunë"],daysShort:["Die","Hën","Mar","Mër","Enj","Pre","Shtu"],daysMin:["Di","Hë","Ma","Më","En","Pr","Sht"],months:["Janar","Shkurt","Mars","Prill","Maj","Qershor","Korrik","Gusht","Shtator","Tetor","Nëntor","Dhjetor"],monthsShort:["Jan","Shk","Mar","Pri","Maj","Qer","Korr","Gu","Sht","Tet","Nën","Dhjet"],today:"Sot"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["sr-latin"]={days:["Nedelja","Ponedeljak","Utorak","Sreda","Četvrtak","Petak","Subota"],daysShort:["Ned","Pon","Uto","Sre","Čet","Pet","Sub"],daysMin:["N","Po","U","Sr","Č","Pe","Su"],months:["Januar","Februar","Mart","April","Maj","Jun","Jul","Avgust","Septembar","Oktobar","Novembar","Decembar"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],today:"Danas",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.sr={days:["Недеља","Понедељак","Уторак","Среда","Четвртак","Петак","Субота"],daysShort:["Нед","Пон","Уто","Сре","Чет","Пет","Суб"],daysMin:["Н","По","У","Ср","Ч","Пе","Су"],months:["Јануар","Фебруар","Март","Април","Мај","Јун","Јул","Август","Септембар","Октобар","Новембар","Децембар"],monthsShort:["Јан","Феб","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Нов","Дец"],today:"Данас",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.sv={days:["Söndag","Måndag","Tisdag","Onsdag","Torsdag","Fredag","Lördag"],daysShort:["Sön","Mån","Tis","Ons","Tor","Fre","Lör"],daysMin:["Sö","Må","Ti","On","To","Fr","Lö"],months:["Januari","Februari","Mars","April","Maj","Juni","Juli","Augusti","September","Oktober","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],today:"Idag",format:"yyyy-mm-dd",weekStart:1,clear:"Rensa"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.sw={days:["Jumapili","Jumatatu","Jumanne","Jumatano","Alhamisi","Ijumaa","Jumamosi"],daysShort:["J2","J3","J4","J5","Alh","Ij","J1"],daysMin:["2","3","4","5","A","I","1"],months:["Januari","Februari","Machi","Aprili","Mei","Juni","Julai","Agosti","Septemba","Oktoba","Novemba","Desemba"],monthsShort:["Jan","Feb","Mac","Apr","Mei","Jun","Jul","Ago","Sep","Okt","Nov","Des"],today:"Leo"}}(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.th={days:["อาทิตย์","จันทร์","อังคาร","พุธ","พฤหัส","ศุกร์","เสาร์","อาทิตย์"],daysShort:["อา","จ","อ","พ","พฤ","ศ","ส","อา"],daysMin:["อา","จ","อ","พ","พฤ","ศ","ส","อา"],months:["มกราคม","กุมภาพันธ์","มีนาคม","เมษายน","พฤษภาคม","มิถุนายน","กรกฎาคม","สิงหาคม","กันยายน","ตุลาคม","พฤศจิกายน","ธันวาคม"],monthsShort:["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค."],today:"วันนี้"}}(jQuery);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user