first commit

This commit is contained in:
Roman Pyrih
2023-07-24 08:30:51 +02:00
commit c2e100a763
7128 changed files with 1622619 additions and 0 deletions

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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');
});
});

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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,
)
);
}
}

View File

@@ -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>

View File

@@ -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();
}
}

View File

@@ -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)
)
);
}
}

View 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
);
}
}
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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'];
}
}

View File

@@ -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'];
}
}

View File

@@ -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;
}
}
}

View File

@@ -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';
}
}

View File

@@ -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';
/* &nbsp; - 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 */

View File

@@ -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;
}
})
});

View File

@@ -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',
'&nbsp;',
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',
'&nbsp;',
'<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>

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}
})
});

View File

@@ -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>

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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>

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}
});

View File

@@ -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>

View File

@@ -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()
);
}
}

View File

@@ -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,
);
}
}

View File

@@ -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;
}

View File

@@ -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');
});
});
});

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -0,0 +1 @@
!function(a){a.fn.datepicker.dates.ar={days:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأحد"],daysShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت","أحد"],daysMin:["ح","ن","ث","ع","خ","ج","س","ح"],months:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthsShort:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],today:"هذا اليوم",rtl:!0}}(jQuery);

View File

@@ -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);

View File

@@ -0,0 +1 @@
!function(a){a.fn.datepicker.dates.bg={days:["Неделя","Понеделник","Вторник","Сряда","Четвъртък","Петък","Събота"],daysShort:["Нед","Пон","Вто","Сря","Чет","Пет","Съб"],daysMin:["Н","П","В","С","Ч","П","С"],months:["Януари","Февруари","Март","Април","Май","Юни","Юли","Август","Септември","Октомври","Ноември","Декември"],monthsShort:["Ян","Фев","Мар","Апр","Май","Юни","Юли","Авг","Сеп","Окт","Ное","Дек"],today:"днес"}}(jQuery);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -0,0 +1 @@
!function(a){a.fn.datepicker.dates.el={days:["Κυριακή","Δευτέρα","Τρίτη","Τετάρτη","Πέμπτη","Παρασκευή","Σάββατο"],daysShort:["Κυρ","Δευ","Τρι","Τετ","Πεμ","Παρ","Σαβ"],daysMin:["Κυ","Δε","Τρ","Τε","Πε","Πα","Σα"],months:["Ιανουάριος","Φεβρουάριος","Μάρτιος","Απρίλιος","Μάιος","Ιούνιος","Ιούλιος","Αύγουστος","Σεπτέμβριος","Οκτώβριος","Νοέμβριος","Δεκέμβριος"],monthsShort:["Ιαν","Φεβ","Μαρ","Απρ","Μάι","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Νοε","Δεκ"],today:"Σήμερα",clear:"Καθαρισμός",weekStart:1,format:"d/m/yyyy"}}(jQuery);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -0,0 +1 @@
!function(a){a.fn.datepicker.dates.fa={days:["یک‌شنبه","دوشنبه","سه‌شنبه","چهارشنبه","پنج‌شنبه","جمعه","شنبه","یک‌شنبه"],daysShort:["یک","دو","سه","چهار","پنج","جمعه","شنبه","یک"],daysMin:["ی","د","س","چ","پ","ج","ش","ی"],months:["ژانویه","فوریه","مارس","آوریل","مه","ژوئن","ژوئیه","اوت","سپتامبر","اکتبر","نوامبر","دسامبر"],monthsShort:["ژان","فور","مار","آور","مه","ژون","ژوی","اوت","سپت","اکت","نوا","دسا"],today:"امروز",clear:"پاک کن",weekStart:1,format:"yyyy/mm/dd"}}(jQuery);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -0,0 +1 @@
!function(a){a.fn.datepicker.dates.he={days:["ראשון","שני","שלישי","רביעי","חמישי","שישי","שבת","ראשון"],daysShort:["א","ב","ג","ד","ה","ו","ש","א"],daysMin:["א","ב","ג","ד","ה","ו","ש","א"],months:["ינואר","פברואר","מרץ","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"],monthsShort:["ינו","פבר","מרץ","אפר","מאי","יונ","יול","אוג","ספט","אוק","נוב","דצמ"],today:"היום",rtl:!0}}(jQuery);

View File

@@ -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);

View File

@@ -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);

View File

@@ -0,0 +1 @@
!function(a){a.fn.datepicker.dates.hy={days:["Կիրակի","Երկուշաբթի","Երեքշաբթի","Չորեքշաբթի","Հինգշաբթի","Ուրբաթ","Շաբաթ"],daysShort:["Կրկ","Երկ","Երք","Չրք","Հնգ","Ուր","Շբթ"],daysMin:["Կրկ","Երկ","Երք","Չրք","Հնգ","Ուր","Շբթ"],months:["Հունվար","Փետրվար","Մարտ","Ապրիլ","Մայիս","Հունիս","Հուլիս","Օգոստոս","Սեպտեմբեր","Հոկտեմբեր","Նոյեմբեր","Դեկտեմբեր"],monthsShort:["Հուն","Փետ","Մար","Ապր","Մայ","Հնս","Հլս","Օգս","Սեպ","Հոկ","Նմբ","Դեկ"],today:"Այսօր",clear:"Ջնջել",format:"dd.mm.yyyy",weekStart:1}}(jQuery);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -0,0 +1 @@
!function(a){a.fn.datepicker.dates.ka={days:["კვირა","ორშაბათი","სამშაბათი","ოთხშაბათი","ხუთშაბათი","პარასკევი","შაბათი"],daysShort:["კვი","ორშ","სამ","ოთხ","ხუთ","პარ","შაბ"],daysMin:["კვ","ორ","სა","ოთ","ხუ","პა","შა"],months:["იანვარი","თებერვალი","მარტი","აპრილი","მაისი","ივნისი","ივლისი","აგვისტო","სექტემბერი","ოქტომები","ნოემბერი","დეკემბერი"],monthsShort:["იან","თებ","მარ","აპრ","მაი","ივნ","ივლ","აგვ","სექ","ოქტ","ნოე","დეკ"],today:"დღეს",clear:"გასუფთავება",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);

View File

@@ -0,0 +1 @@
!function(a){a.fn.datepicker.dates.kh={days:["អាទិត្យ","ចន្ទ","អង្គារ","ពុធ","ព្រហស្បតិ៍","សុក្រ","សៅរ៍","អាទិត្យ"],daysShort:["អា.ទិ","ចន្ទ","អង្គារ","ពុធ","ព្រ.ហ","សុក្រ","សៅរ៍","អា.ទិ"],daysMin:["អា.ទិ","ចន្ទ","អង្គារ","ពុធ","ព្រ.ហ","សុក្រ","សៅរ៍","អា.ទិ"],months:["មករា","កុម្ភះ","មិនា","មេសា","ឧសភា","មិថុនា","កក្កដា","សីហា","កញ្ញា","តុលា","វិច្ឆិកា","ធ្នូ"],monthsShort:["មករា","កុម្ភះ","មិនា","មេសា","ឧសភា","មិថុនា","កក្កដា","សីហា","កញ្ញា","តុលា","វិច្ឆិកា","ធ្នូ"],today:"ថ្ងៃនេះ",clear:"សំអាត"}}(jQuery);

View File

@@ -0,0 +1 @@
!function(a){a.fn.datepicker.dates.kk={days:["Жексенбі","Дүйсенбі","Сейсенбі","Сәрсенбі","Бейсенбі","Жұма","Сенбі"],daysShort:["Жек","Дүй","Сей","Сәр","Бей","Жұм","Сен"],daysMin:["Жк","Дс","Сс","Ср","Бс","Жм","Сн"],months:["Қаңтар","Ақпан","Наурыз","Сәуір","Мамыр","Маусым","Шілде","Тамыз","Қыркүйек","Қазан","Қараша","Желтоқсан"],monthsShort:["Қаң","Ақп","Нау","Сәу","Мамыр","Мау","Шлд","Тмз","Қыр","Қзн","Қар","Жел"],today:"Бүгін",weekStart:1}}(jQuery);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -0,0 +1 @@
!function(a){a.fn.datepicker.dates.mk={days:["Недела","Понеделник","Вторник","Среда","Четврток","Петок","Сабота"],daysShort:["Нед","Пон","Вто","Сре","Чет","Пет","Саб"],daysMin:["Не","По","Вт","Ср","Че","Пе","Са"],months:["Јануари","Февруари","Март","Април","Мај","Јуни","Јули","Август","Септември","Октомври","Ноември","Декември"],monthsShort:["Јан","Фев","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Ное","Дек"],today:"Денес",format:"dd.mm.yyyy"}}(jQuery);

View File

@@ -0,0 +1 @@
!function(a){a.fn.datepicker.dates.mn={days:["Ням","Даваа","Мягмар","Лхагва","Пүрэв","Баасан","Бямба"],daysShort:["Ням","Дав","Мяг","Лха","Пүр","Баа","Бям"],daysMin:["Ня","Да","Мя","Лх","Пү","Ба","Бя"],months:["Хулгана","Үхэр","Бар","Туулай","Луу","Могой","Морь","Хонь","Бич","Тахиа","Нохой","Гахай"],monthsShort:["Хул","Үхэ","Бар","Туу","Луу","Мог","Мор","Хон","Бич","Тах","Нох","Гах"],today:"Өнөөдөр",clear:"Тодорхой",format:"yyyy.mm.dd",weekStart:1}}(jQuery);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -0,0 +1 @@
!function(a){a.fn.datepicker.dates.rs={days:["Недеља","Понедељак","Уторак","Среда","Четвртак","Петак","Субота"],daysShort:["Нед","Пон","Уто","Сре","Чет","Пет","Суб"],daysMin:["Н","По","У","Ср","Ч","Пе","Су"],months:["Јануар","Фебруар","Март","Април","Мај","Јун","Јул","Август","Септембар","Октобар","Новембар","Децембар"],monthsShort:["Јан","Феб","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Нов","Дец"],today:"Данас",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);

View File

@@ -0,0 +1 @@
!function(a){a.fn.datepicker.dates.ru={days:["Воскресенье","Понедельник","Вторник","Среда","Четверг","Пятница","Суббота"],daysShort:["Вск","Пнд","Втр","Срд","Чтв","Птн","Суб"],daysMin:["Вс","Пн","Вт","Ср","Чт","Пт","Сб"],months:["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],monthsShort:["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"],today:"Сегодня",clear:"Очистить",format:"dd.mm.yyyy",weekStart:1}}(jQuery);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -0,0 +1 @@
!function(a){a.fn.datepicker.dates.sr={days:["Недеља","Понедељак","Уторак","Среда","Четвртак","Петак","Субота"],daysShort:["Нед","Пон","Уто","Сре","Чет","Пет","Суб"],daysMin:["Н","По","У","Ср","Ч","Пе","Су"],months:["Јануар","Фебруар","Март","Април","Мај","Јун","Јул","Август","Септембар","Октобар","Новембар","Децембар"],monthsShort:["Јан","Феб","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Нов","Дец"],today:"Данас",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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