Hotel Raxa - Advanced Booking System Implementation

🏨 Hotel Booking Enhancements:
- Implemented Eagle Booking Advanced Pricing add-on
- Added Booking.com-style rate management system
- Created professional calendar interface for pricing
- Integrated deals and discounts functionality

💰 Advanced Pricing Features:
- Dynamic pricing models (per room, per person, per adult)
- Base rates, adult rates, and child rates management
- Length of stay discounts and early bird deals
- Mobile rates and secret deals implementation
- Seasonal promotions and flash sales

📅 Availability Management:
- Real-time availability tracking
- Stop sell and restriction controls
- Closed to arrival/departure functionality
- Minimum/maximum stay requirements
- Automatic sold-out management

💳 Payment Integration:
- Maintained Redsys payment gateway integration
- Seamless integration with existing Eagle Booking
- No modifications to core Eagle Booking plugin

🛠️ Technical Implementation:
- Custom database tables for advanced pricing
- WordPress hooks and filters integration
- AJAX-powered admin interface
- Data migration from existing Eagle Booking
- Professional calendar view for revenue management

📊 Admin Interface:
- Booking.com-style management dashboard
- Visual rate and availability calendar
- Bulk operations for date ranges
- Statistics and analytics dashboard
- Modal dialogs for quick editing

🔧 Code Quality:
- WordPress coding standards compliance
- Secure database operations with prepared statements
- Proper input validation and sanitization
- Error handling and logging
- Responsive admin interface

🤖 Generated with Claude Code (https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Hotel Raxa Dev
2025-07-11 07:43:22 +02:00
commit 5b1e2453c7
9816 changed files with 2784509 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 B

View File

@@ -0,0 +1,57 @@
<?php
/**
* Redux Widget Areas Extension Class
*
* @package Redux
* @author Dovy Paukstys (dovy)
* @class Redux_Extension_Widget_Areas
* @version 4.3.20
*/
defined( 'ABSPATH' ) || exit;
if ( ! class_exists( 'Redux_Extension_Widget_Areas' ) ) {
/**
* Class Redux_Extension_Widget_Areas
*/
class Redux_Extension_Widget_Areas extends Redux_Extension_Abstract {
/**
* Extension version.
*
* @var string
*/
public static $version = '4.3.20';
/**
* Extension Friendly name.
*
* @var string
*/
public $extension_name = 'Widget Areas';
/**
* Redux_Extension_Widget_Areas constructor.
*
* @param object $redux ReduxFramework object pointer.
*/
public function __construct( $redux ) {
parent::__construct( $redux, __FILE__ );
$this->add_field( 'widget_areas' );
require_once __DIR__ . '/class-redux-widget-areas.php';
$widget_areas = new Redux_Widget_Areas( $this->parent );
// Allow users to extend if they want.
// Phpcs:ignore WordPress.NamingConventions.ValidHookName
do_action( 'redux/widget_areas/' . $redux->args['opt_name'] . '/construct' );
add_action( 'wp_ajax_redux_delete_widget_area', array( $widget_areas, 'redux_delete_widget_area_area' ) );
}
}
}
class_alias( 'Redux_Extension_Widget_Areas', 'ReduxFramework_extension_widget_areas' );

View File

@@ -0,0 +1,311 @@
<?php
/**
* Redux Widget Areas Class
*
* @package Redux
* @author Dovy Paukstys (dovy)
* @class Redux_Widget_Areas
*/
defined( 'ABSPATH' ) || exit;
// Don't duplicate me!
if ( ! class_exists( 'Redux_Widget_Areas' ) ) {
/**
* Main ReduxFramework customizer extension class
*
* @since 1.0.0
*/
class Redux_Widget_Areas {
/**
* Extension URI.
*
* @var string
*/
private $extension_url;
/** Extension directory.
*
* @var string
*/
private $extension_dir;
/**
* Array of enabled widget_areas
*
* @since 1.0.0
* @var array
*/
protected $widget_areas = array();
/**
* Widget array.
*
* @var array
*/
protected $orig = array();
/**
* ReduxFramework object.
*
* @var object
*/
private $parent;
/**
* Redux_Widget_Areas constructor.
*
* @param object $redux ReduxFramework pointer.
*/
public function __construct( $redux ) {
global $pagenow;
$this->parent = $redux;
if ( empty( $this->extension_dir ) ) {
$this->extension_dir = trailingslashit( str_replace( '\\', '/', __DIR__ ) );
$this->extension_url = site_url( str_replace( trailingslashit( str_replace( '\\', '/', ABSPATH ) ), '', $this->extension_dir ) );
}
add_action( 'init', array( &$this, 'register_custom_widget_areas' ), 1000 );
if ( 'widgets.php' === $pagenow ) {
add_action( 'admin_print_scripts', array( $this, 'add_new_widget_area_box' ) );
add_action( 'load-widgets.php', array( $this, 'add_widget_area_area' ), 100 );
add_action( 'load-widgets.php', array( $this, 'enqueue' ), 100 );
}
}
/**
* Function to create the HTML used to create widget_areas.
*
* @since 1.0.0
*/
public function add_new_widget_area_box() {
$nonce = wp_create_nonce( 'add-redux-widget_area-nonce' );
$del_nonce = wp_create_nonce( 'delete-redux-widget_area-nonce' );
?>
<script type="text/html" id="redux-add-widget-template">
<div id="redux-add-widget" class="widgets-holder-wrap">
<div class="">
<input type="hidden" name="redux-nonce" value="<?php echo esc_attr( $del_nonce ); ?>"/>
<div class="sidebar-name">
<h3><?php echo esc_html__( 'Create Widget Area', 'redux-framework' ); ?> <span class="spinner"></span></h3>
</div>
<div class="sidebar-description">
<form id="addWidgetAreaForm" action="" method="post">
<input type="hidden" name="redux-add-widget-nonce" value="<?php echo esc_attr( $nonce ); ?>"/>
<div class="widget-content">
<input
id="redux-add-widget-input" name="redux-add-widget-input" type="text"
class="regular-text"
title="<?php echo esc_attr__( 'Name', 'redux-framework' ); ?>"
placeholder="<?php echo esc_attr__( 'Name', 'redux-framework' ); ?>"/>
</div>
<div class="widget-control-actions">
<div class="aligncenter">
<input
class="addWidgetArea-button button-primary"
type="submit"
value="<?php echo esc_attr__( 'Create Widget Area', 'redux-framework' ); ?>"/>
</div>
<br class="clear">
</div>
</form>
</div>
</div>
</div>
</script>
<?php
}
/**
* Add widget area.
*/
public function add_widget_area_area() {
if ( isset( $_POST ) && isset( $_POST['redux-add-widget-nonce'] ) && wp_verify_nonce( sanitize_key( wp_unslash( $_POST['redux-add-widget-nonce'] ) ), 'add-redux-widget_area-nonce' ) ) {
if ( ! empty( $_POST['redux-add-widget-input'] ) ) {
$this->widget_areas = $this->get_widget_areas();
$this->widget_areas[] = $this->check_widget_area_name( sanitize_text_field( wp_unslash( $_POST['redux-add-widget-input'] ) ) );
$this->save_widget_areas();
wp_safe_redirect( admin_url( 'widgets.php' ) );
die();
}
}
}
/**
* Before we create a new widget_area, verify it doesn't already exist. If it does, append a number to the name.
*
* @param string $name Name of the widget_area to be created.
*
* @return string|void $name Name of the new widget_area just created.
* @since 1.0.0
*/
private function check_widget_area_name( string $name ) {
if ( empty( $GLOBALS['wp_registered_widget_areas'] ) ) {
return $name;
}
$taken = array();
foreach ( $GLOBALS['wp_registered_widget_areas'] as $widget_area ) {
$taken[] = $widget_area['name'];
}
$taken = array_merge( $taken, $this->widget_areas );
if ( in_array( $name, $taken, true ) ) {
$counter = substr( $name, - 1 );
if ( ! is_numeric( $counter ) ) {
$new_name = $name . ' 1';
} else {
$new_name = substr( $name, 0, - 1 ) . ( (int) $counter + 1 );
}
$name = $this->check_widget_area_name( $new_name );
}
echo $name; // phpcs:disable WordPress.Security.EscapeOutput
exit();
}
/**
* Save Widget Areas.
*/
private function save_widget_areas() {
set_theme_mod( 'redux-widget-areas', array_unique( $this->widget_areas ) );
}
/**
* Register and display the custom widget_area areas we have set.
*
* @since 1.0.0
*/
public function register_custom_widget_areas() {
// If the single instance hasn't been set, set it now.
if ( empty( $this->widget_areas ) ) {
$this->widget_areas = $this->get_widget_areas();
}
// phpcs:ignore WordPress.NamingConventions.ValidHookName
$this->orig = array_unique( apply_filters( 'redux/' . $this->parent->args['opt_name'] . '/widget_areas', array() ) );
if ( ! empty( $this->orig ) && $this->orig !== $this->widget_areas ) {
$this->widget_areas = array_unique( array_merge( $this->widget_areas, $this->orig ) );
$this->save_widget_areas();
}
$options = array(
'before_title' => '<h3 class="widgettitle">',
'after_title' => '</h3>',
'before_widget' => '<div id="%1$s" class="widget clearfix %2$s">',
'after_widget' => '</div>',
);
$options = apply_filters( 'redux_custom_widget_args', $options );
if ( is_array( $this->widget_areas ) ) {
foreach ( array_unique( $this->widget_areas ) as $widget_area ) {
$options['class'] = 'redux-custom';
$options['name'] = $widget_area;
$options['id'] = sanitize_key( $widget_area );
register_sidebar( $options );
}
}
}
/**
* Return the widget_areas array.
*
* @since 1.0.0
* @return array If not empty, active redux widget_areas are returned.
*/
public function get_widget_areas(): array {
// If the single instance hasn't been set, set it now.
if ( ! empty( $this->widget_areas ) ) {
return $this->widget_areas;
}
$db = get_theme_mod( 'redux-widget-areas' );
if ( ! empty( $db ) ) {
$this->widget_areas = array_unique( array_merge( $this->widget_areas, $db ) );
}
return $this->widget_areas;
}
/**
* Delete widget area.
*/
public function redux_delete_widget_area_area() {
if ( isset( $_POST ) && isset( $_POST['_wpnonce'] ) && wp_verify_nonce( sanitize_key( wp_unslash( $_POST['_wpnonce'] ) ), 'delete-redux-widget_area-nonce' ) ) {
if ( isset( $_POST['name'] ) && ! empty( sanitize_text_field( wp_unslash( $_POST['name'] ) ) ) ) {
$name = sanitize_text_field( wp_unslash( $_POST['name'] ) );
$this->widget_areas = $this->get_widget_areas();
$key = array_search( $name, $this->widget_areas, true );
if ( $key >= 0 ) {
unset( $this->widget_areas[ $key ] );
$this->save_widget_areas();
}
echo 'widget_area-deleted';
}
}
die();
}
/**
* Enqueue support files.
*/
public function enqueue() {
$min = Redux_Functions::is_min();
wp_enqueue_style( 'dashicons' );
wp_enqueue_script(
'redux-widget-areas',
$this->extension_url . 'redux-extension-widget-areas' . $min . '.js',
array( 'jquery' ),
Redux_Extension_Widget_Areas::$version,
true
);
if ( $this->parent->args['dev_mode'] ) {
wp_enqueue_style(
'redux-widget-areas',
$this->extension_url . 'redux-extension-widget-areas.css',
array(),
Redux_Extension_Widget_Areas::$version
);
}
// Localize script.
wp_localize_script(
'redux-widget-areas',
'reduxWidgetAreasLocalize',
array(
'count' => count( $this->orig ),
'delete' => esc_html__( 'Delete', 'redux-framework' ),
'confirm' => esc_html__( 'Confirm', 'redux-framework' ),
'cancel' => esc_html__( 'Cancel', 'redux-framework' ),
)
);
}
}
}

View File

@@ -0,0 +1,8 @@
<?php
/**
* Silence is golden.
*
* @package Redux Framework
*/
echo null;

View File

@@ -0,0 +1,37 @@
#widget_area-redux-custom, #widget_area-redux-custom h3 { position: relative; }
#redux-add-widget { margin: 10px 0 0; position: relative; }
#redux-add-widget p { margin-top: 0; }
#redux-add-widget form { text-align: center; }
#redux-add-widget h3 { text-align: center !important; padding: 15px 7px; font-size: 1.3em; margin-top: 5px; }
.redux-widget_area-delete { position: absolute; top: 0; right: 35px; padding: 12px 10px; cursor: pointer; }
.redux-widget_area-delete:before { font-family: "dashicons", serif; content: "\f182"; font: 400 20px/1 dashicons; speak: none; display: inline-block; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-decoration: none !important; color: #aaa; }
.redux-widget_area-delete:hover:before { color: #888; }
.activate_spinner { display: block !important; position: absolute; top: 10px; right: 4px; background-color: #ECECEC; }
#redux-add-widget-input { max-width: 95%; padding: 8px; margin-bottom: 14px; margin-top: 3px; text-align: center; }
div#widgets-right .sidebar-redux-custom .widgets-sortables { padding-bottom: 45px; }
div#widgets-right .sidebar-redux-custom.closed .widgets-sortables { padding-bottom: 0; }
div#widgets-right .sidebar-redux-custom.closed .widgets-sortables .redux-widget-area-edit { display: none; }
.redux-widget-area-edit { display: block; position: absolute; bottom: 0; left: 0; height: 40px; line-height: 40px; width: 100%; border-top: 1px solid #eee; }
.redux-widget-area-edit .redux-widget-area-delete { display: block; float: right; margin: 11px 8px 0 0 !important; }
.redux-widget-area-edit .redux-widget-area-delete-confirm { display: none; float: right; margin: 11px 8px 0 0 !important; }
.redux-widget-area-edit .redux-widget-area-delete-cancel { display: none; float: right; margin: 11px 8px 0 0 !important; }
/*# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkdXgtZXh0ZW5zaW9uLXdpZGdldC1hcmVhcy5jc3MiLCJzb3VyY2VzIjpbInJlZHV4LWV4dGVuc2lvbi13aWRnZXQtYXJlYXMuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxBQUFBLHlCQUF5QixFQUN6Qix5QkFBeUIsQ0FBQyxFQUFFLENBQUMsRUFDekIsUUFBUSxFQUFFLFFBQVEsR0FDckI7O0FBRUQsQUFBQSxpQkFBaUIsQ0FBQyxFQUNkLE1BQU0sRUFBRSxRQUFRLEVBQ2hCLFFBQVEsRUFBRSxRQUFRLEdBZ0JyQjs7QUFsQkQsQUFJSSxpQkFKYSxDQUliLENBQUMsQ0FBQyxFQUNFLFVBQVUsRUFBRSxDQUFDLEdBQ2hCOztBQU5MLEFBUUksaUJBUmEsQ0FRYixJQUFJLENBQUMsRUFDRCxVQUFVLEVBQUUsTUFBTSxHQUNyQjs7QUFWTCxBQVlJLGlCQVphLENBWWIsRUFBRSxDQUFDLEVBQ0MsVUFBVSxFQUFFLGlCQUFpQixFQUM3QixPQUFPLEVBQUUsUUFBUSxFQUNqQixTQUFTLEVBQUUsS0FBSyxFQUNoQixVQUFVLEVBQUUsR0FBRyxHQUNsQjs7QUFHTCxBQUFBLHlCQUF5QixDQUFDLEVBQ3RCLFFBQVEsRUFBRSxRQUFRLEVBQ2xCLEdBQUcsRUFBRSxDQUFDLEVBQ04sS0FBSyxFQUFFLElBQUksRUFDWCxPQUFPLEVBQUUsU0FBUyxFQUNsQixNQUFNLEVBQUUsT0FBTyxHQWlCbEI7O0FBdEJELEFBT0kseUJBUHFCLEFBT3BCLE9BQU8sQ0FBQyxFQUNMLFdBQVcsRUFBRSxrQkFBa0IsRUFDL0IsT0FBTyxFQUFFLE9BQU8sRUFDaEIsSUFBSSxFQUFFLG9CQUFvQixFQUMxQixLQUFLLEVBQUUsSUFBSSxFQUNYLE9BQU8sRUFBRSxZQUFZLEVBQ3JCLHNCQUFzQixFQUFFLFdBQVcsRUFDbkMsdUJBQXVCLEVBQUUsU0FBUyxFQUNsQyxlQUFlLEVBQUUsZUFBZSxFQUNoQyxLQUFLLEVBQUUsSUFBSSxHQUNkOztBQWpCTCxBQW1CSSx5QkFuQnFCLEFBbUJwQixNQUFNLEFBQUEsT0FBTyxDQUFDLEVBQ1gsS0FBSyxFQUFFLElBQUksR0FDZDs7QUFHTCxBQUFBLGlCQUFpQixDQUFDLEVBQ2QsT0FBTyxFQUFFLGdCQUFnQixFQUN6QixRQUFRLEVBQUUsUUFBUSxFQUNsQixHQUFHLEVBQUUsSUFBSSxFQUNULEtBQUssRUFBRSxHQUFHLEVBQ1YsZ0JBQWdCLEVBQUUsT0FBTyxHQUM1Qjs7QUFFRCxBQUFBLHVCQUF1QixDQUFDLEVBQ3BCLFNBQVMsRUFBRSxHQUFHLEVBQ2QsT0FBTyxFQUFFLEdBQUcsRUFDWixhQUFhLEVBQUUsSUFBSSxFQUNuQixVQUFVLEVBQUUsR0FBRyxFQUNmLFVBQVUsRUFBRSxNQUFNLEdBQ3JCOztBQUVELEFBRVEsR0FGTCxBQUFBLGNBQWMsQ0FDYixxQkFBcUIsQ0FDakIsa0JBQWtCLENBQUMsRUFDZixjQUFjLEVBQUUsSUFBSSxHQUN2Qjs7QUFKVCxBQUtRLEdBTEwsQUFBQSxjQUFjLENBQ2IscUJBQXFCLEFBSWhCLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxFQUN4QixjQUFjLEVBQUUsQ0FBQyxHQUlwQjs7QUFWVCxBQU9ZLEdBUFQsQUFBQSxjQUFjLENBQ2IscUJBQXFCLEFBSWhCLE9BQU8sQ0FBQyxrQkFBa0IsQ0FFdkIsdUJBQXVCLENBQUMsRUFDcEIsT0FBTyxFQUFFLElBQUksR0FDaEI7O0FBS2IsQUFBQSx1QkFBdUIsQ0FBQyxFQUNwQixPQUFPLEVBQUUsS0FBSyxFQUNkLFFBQVEsRUFBRSxRQUFRLEVBQ2xCLE1BQU0sRUFBRSxDQUFDLEVBQ1QsSUFBSSxFQUFFLENBQUMsRUFDUCxNQUFNLEVBQUUsSUFBSSxFQUNaLFdBQVcsRUFBRSxJQUFJLEVBQ2pCLEtBQUssRUFBRSxJQUFJLEVBQ1gsVUFBVSxFQUFFLGNBQWMsR0FtQjdCOztBQTNCRCxBQVVJLHVCQVZtQixDQVVuQix5QkFBeUIsQ0FBQyxFQUN0QixPQUFPLEVBQUUsS0FBSyxFQUNkLEtBQUssRUFBRSxLQUFLLEVBQ1osTUFBTSxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQSxVQUFVLEdBQ2pDOztBQWRMLEFBZ0JJLHVCQWhCbUIsQ0FnQm5CLGlDQUFpQyxDQUFDLEVBQzlCLE9BQU8sRUFBRSxJQUFJLEVBQ2IsS0FBSyxFQUFFLEtBQUssRUFDWixNQUFNLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBLFVBQVUsR0FDakM7O0FBcEJMLEFBc0JJLHVCQXRCbUIsQ0FzQm5CLGdDQUFnQyxDQUFDLEVBQzdCLE9BQU8sRUFBRSxJQUFJLEVBQ2IsS0FBSyxFQUFFLEtBQUssRUFDWixNQUFNLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBLFVBQVUsR0FDakMifQ== */
/*# sourceMappingURL=redux-extension-widget-areas.css.map */

View File

@@ -0,0 +1,132 @@
/* global reduxWidgetAreasLocalize, ajaxurl, jQuery */
( function( $ ) {
'use strict';
var reduxWidgetAreas = function() {
this.widgetWrap = $( '.sidebars-column-1' );
this.widgetArea = $( '#widgets-right' );
this.parentArea = $( '.widget-liquid-right' );
this.widgetTemplate = $( '#redux-add-widget-template' );
this.addFormHtml();
this.addDelButton();
this.bindEvents();
};
reduxWidgetAreas.prototype = {
addFormHtml: function() {
this.widgetWrap.append( this.widgetTemplate.html() );
this.widgetName = this.widgetWrap.find( 'input[name="redux-add-widget-input"]' );
this.nonce = this.widgetWrap.find( 'input[name="redux-nonce"]' ).val();
},
addDelButton: function() {
var i = 0;
this.widgetArea.find( '.sidebar-redux-custom .widgets-sortables' ).each(
function() {
if ( i >= reduxWidgetAreasLocalize.count ) {
$( this ).append(
'<div class="redux-widget-area-edit"><a href="#" class="redux-widget-area-delete button-primary">' + reduxWidgetAreasLocalize.delete +
'</a><a href="#" style="display:none" class="redux-widget-area-delete-cancel button-secondary">' + reduxWidgetAreasLocalize.cancel +
'</a><a href="#" style="display:none" class="redux-widget-area-delete-confirm button-primary">' + reduxWidgetAreasLocalize.confirm + '</a></div>'
);
}
i++;
}
);
},
bindEvents: function() {
this.parentArea.on(
'click',
'a.redux-widget-area-delete',
function( event ) {
event.preventDefault();
$( this ).hide();
$( this ).next( 'a.redux-widget-area-delete-cancel' ).show().next( 'a.redux-widget-area-delete-confirm' ).show();
}
);
this.parentArea.on(
'click',
'a.redux-widget-area-delete-cancel',
function( event ) {
event.preventDefault();
$( this ).hide();
$( this ).prev( 'a.redux-widget-area-delete' ).show();
$( this ).next( 'a.redux-widget-area-delete-confirm' ).hide();
}
);
this.parentArea.on(
'click',
'a.redux-widget-area-delete-confirm',
$.proxy( this.deleteWidgetArea, this )
);
$( '#addWidgetAreaForm' ).on(
'submit',
function() {
var spinner = $( '#redux-add-widget' ).find( '.spinner' );
spinner.css( 'display', 'inline-block' );
spinner.css( 'visibility', 'visible' );
$.proxy( this.addWidgetArea, this );
}
);
},
addWidgetArea: function( e ) {
e.preventDefault();
return false;
},
// Delete the widgetArea area with all widgets within, then re calculate the other widgetArea ids and save the order.
deleteWidgetArea: function( e ) {
var widget = $( e.currentTarget ).parents( '.widgets-holder-wrap:eq(0)' );
var title = widget.find( '.sidebar-name h2' );
var spinner = title.find( '.spinner' );
var widgetName = title.text().trim();
var _this = this;
widget.addClass( 'closed' );
spinner.css( 'display', 'inline-block' );
spinner.css( 'visibility', 'visible' );
$.ajax(
{
type: 'POST',
url: ajaxurl,
data: {
action: 'redux_delete_widget_area',
name: widgetName,
_wpnonce: _this.nonce
},
success: function( response ) {
if ( 'widget_area-deleted' === response.trim() ) {
widget.slideUp(
200,
function() {
this.remove();
}
);
}
}
}
);
}
};
$(
function() {
new reduxWidgetAreas();
}
);
})( jQuery );

View File

@@ -0,0 +1 @@
!function(d){"use strict";function e(){this.widgetWrap=d(".sidebars-column-1"),this.widgetArea=d("#widgets-right"),this.parentArea=d(".widget-liquid-right"),this.widgetTemplate=d("#redux-add-widget-template"),this.addFormHtml(),this.addDelButton(),this.bindEvents()}e.prototype={addFormHtml:function(){this.widgetWrap.append(this.widgetTemplate.html()),this.widgetName=this.widgetWrap.find('input[name="redux-add-widget-input"]'),this.nonce=this.widgetWrap.find('input[name="redux-nonce"]').val()},addDelButton:function(){var e=0;this.widgetArea.find(".sidebar-redux-custom .widgets-sortables").each(function(){e>=reduxWidgetAreasLocalize.count&&d(this).append('<div class="redux-widget-area-edit"><a href="#" class="redux-widget-area-delete button-primary">'+reduxWidgetAreasLocalize.delete+'</a><a href="#" style="display:none" class="redux-widget-area-delete-cancel button-secondary">'+reduxWidgetAreasLocalize.cancel+'</a><a href="#" style="display:none" class="redux-widget-area-delete-confirm button-primary">'+reduxWidgetAreasLocalize.confirm+"</a></div>"),e++})},bindEvents:function(){this.parentArea.on("click","a.redux-widget-area-delete",function(e){e.preventDefault(),d(this).hide(),d(this).next("a.redux-widget-area-delete-cancel").show().next("a.redux-widget-area-delete-confirm").show()}),this.parentArea.on("click","a.redux-widget-area-delete-cancel",function(e){e.preventDefault(),d(this).hide(),d(this).prev("a.redux-widget-area-delete").show(),d(this).next("a.redux-widget-area-delete-confirm").hide()}),this.parentArea.on("click","a.redux-widget-area-delete-confirm",d.proxy(this.deleteWidgetArea,this)),d("#addWidgetAreaForm").on("submit",function(){var e=d("#redux-add-widget").find(".spinner");e.css("display","inline-block"),e.css("visibility","visible"),d.proxy(this.addWidgetArea,this)})},addWidgetArea:function(e){return e.preventDefault(),!1},deleteWidgetArea:function(e){var t=d(e.currentTarget).parents(".widgets-holder-wrap:eq(0)"),e=t.find(".sidebar-name h2"),i=e.find(".spinner"),e=e.text().trim();t.addClass("closed"),i.css("display","inline-block"),i.css("visibility","visible"),d.ajax({type:"POST",url:ajaxurl,data:{action:"redux_delete_widget_area",name:e,_wpnonce:this.nonce},success:function(e){"widget_area-deleted"===e.trim()&&t.slideUp(200,function(){this.remove()})}})}},d(function(){new e})}(jQuery);

View File

@@ -0,0 +1,107 @@
#widget_area-redux-custom,
#widget_area-redux-custom h3 {
position: relative;
}
#redux-add-widget {
margin: 10px 0 0;
position: relative;
p {
margin-top: 0;
}
form {
text-align: center;
}
h3 {
text-align: center !important;
padding: 15px 7px;
font-size: 1.3em;
margin-top: 5px;
}
}
.redux-widget_area-delete {
position: absolute;
top: 0;
right: 35px;
padding: 12px 10px;
cursor: pointer;
&:before {
font-family: "dashicons", serif;
content: "\f182";
font: 400 20px/1 dashicons;
speak: none;
display: inline-block;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-decoration: none !important;
color: #aaa;
}
&:hover:before {
color: #888;
}
}
.activate_spinner {
display: block !important;
position: absolute;
top: 10px;
right: 4px;
background-color: #ECECEC;
}
#redux-add-widget-input {
max-width: 95%;
padding: 8px;
margin-bottom: 14px;
margin-top: 3px;
text-align: center;
}
div#widgets-right {
.sidebar-redux-custom {
.widgets-sortables {
padding-bottom: 45px;
}
&.closed .widgets-sortables {
padding-bottom: 0;
.redux-widget-area-edit {
display: none;
}
}
}
}
.redux-widget-area-edit {
display: block;
position: absolute;
bottom: 0;
left: 0;
height: 40px;
line-height: 40px;
width: 100%;
border-top: 1px solid #eee;
.redux-widget-area-delete {
display: block;
float: right;
margin: 11px 8px 0 0!important;
}
.redux-widget-area-delete-confirm {
display: none;
float: right;
margin: 11px 8px 0 0!important;
}
.redux-widget-area-delete-cancel {
display: none;
float: right;
margin: 11px 8px 0 0!important;
}
}