Restore to commit 74e578279624c6045ca440a3459ebfa1f8d54191
This commit is contained in:
239
chat/templates/Announcements/public/class-frontend.php
Normal file
239
chat/templates/Announcements/public/class-frontend.php
Normal file
@@ -0,0 +1,239 @@
|
||||
<?php
|
||||
/**
|
||||
* Frontend class for displaying announcements on public pages
|
||||
*/
|
||||
|
||||
// Prevent direct access
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class PC_Announcements_274_Frontend {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_scripts'));
|
||||
add_action('wp_head', array($this, 'display_announcements'), 1);
|
||||
add_shortcode('pc_announcements_274', array($this, 'get_announcements_for_shortcode'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue frontend scripts and styles
|
||||
*/
|
||||
public function enqueue_frontend_scripts() {
|
||||
wp_enqueue_style('pc-announcements-274-public-style', PC_ANNOUNCEMENTS_274_PLUGIN_URL . 'public/css/public-style.css', array(), PC_ANNOUNCEMENTS_274_VERSION);
|
||||
wp_enqueue_script('pc-announcements-274-public-script', PC_ANNOUNCEMENTS_274_PLUGIN_URL . 'public/js/public-script.js', array('jquery'), PC_ANNOUNCEMENTS_274_VERSION, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get active announcements
|
||||
*/
|
||||
private function get_active_announcements() {
|
||||
global $wpdb;
|
||||
$table_name = PC_Announcements_274_Install::get_table_name();
|
||||
|
||||
if (empty($table_name)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$current_time = current_time('mysql');
|
||||
|
||||
$announcements = $wpdb->get_results($wpdb->prepare("
|
||||
SELECT * FROM $table_name
|
||||
WHERE status = %s
|
||||
AND (start_date IS NULL OR start_date <= %s)
|
||||
AND (end_date IS NULL OR end_date >= %s)
|
||||
ORDER BY created_at DESC
|
||||
", 'active', $current_time, $current_time));
|
||||
|
||||
if ($announcements === null) {
|
||||
return array();
|
||||
}
|
||||
|
||||
return $announcements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display announcements at the top of pages
|
||||
*/
|
||||
public function display_announcements() {
|
||||
// Don't show on admin pages or in WordPress admin
|
||||
if (is_admin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$announcements = $this->get_active_announcements();
|
||||
|
||||
if (empty($announcements)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Display only the most recent active announcement
|
||||
$announcement = $announcements[0];
|
||||
|
||||
$this->render_announcement($announcement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render single announcement
|
||||
*/
|
||||
private function render_announcement($announcement) {
|
||||
$title = esc_html($announcement->title);
|
||||
$message = wpautop(wp_kses_post($announcement->message));
|
||||
$image_url = esc_url($announcement->image_url);
|
||||
$banner_color = esc_attr($announcement->banner_color);
|
||||
$link_url = esc_url($announcement->link_url);
|
||||
$close_text = __('Close', 'pc-announcements-274');
|
||||
|
||||
$banner_style = '';
|
||||
if (!empty($banner_color) && $banner_color !== '#0d47a1') {
|
||||
$banner_style = 'background: ' . $banner_color . ';';
|
||||
}
|
||||
|
||||
$has_link = !empty($link_url);
|
||||
$link_attrs = $has_link ? 'href="' . $link_url . '" target="_blank" rel="noopener noreferrer"' : '';
|
||||
$close_button = $has_link ? '' : '<button class="pc-announcements-274-close" aria-label="' . esc_attr($close_text) . '">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>';
|
||||
|
||||
?>
|
||||
<div class="pc-announcements-274-announcement" data-announcement-id="<?php echo $announcement->id; ?>" style="<?php echo $banner_style; ?>">
|
||||
<div class="pc-announcements-274-container">
|
||||
<div class="pc-announcements-274-content">
|
||||
<?php if ($has_link): ?>
|
||||
<a class="pc-announcements-274-link" <?php echo $link_attrs; ?>>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($image_url)): ?>
|
||||
<div class="pc-announcements-274-image">
|
||||
<img src="<?php echo $image_url; ?>" alt="<?php echo esc_attr($title); ?>" loading="lazy">
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="pc-announcements-274-text">
|
||||
<?php if (!empty($title)): ?>
|
||||
<h3 class="pc-announcements-274-title"><?php echo $title; ?></h3>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty(trim($message))): ?>
|
||||
<div class="pc-announcements-274-message">
|
||||
<?php echo $message; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($has_link): ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php echo $close_button; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Get announcements for shortcode
|
||||
*/
|
||||
public function get_announcements_for_shortcode($atts) {
|
||||
$atts = shortcode_atts(array(
|
||||
'count' => 1,
|
||||
'show_image' => true,
|
||||
'show_close' => true,
|
||||
'class' => ''
|
||||
), $atts, 'pc_announcements_274');
|
||||
|
||||
$announcements = $this->get_active_announcements();
|
||||
|
||||
if (empty($announcements)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$output = '';
|
||||
$count = min(intval($atts['count']), count($announcements));
|
||||
$show_image = filter_var($atts['show_image'], FILTER_VALIDATE_BOOLEAN);
|
||||
$show_close = filter_var($atts['show_close'], FILTER_VALIDATE_BOOLEAN);
|
||||
$custom_class = sanitize_html_class($atts['class']);
|
||||
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$announcement = $announcements[$i];
|
||||
$output .= $this->render_announcement_html($announcement, $show_image, $show_close, $custom_class);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render announcement as HTML string
|
||||
*/
|
||||
private function render_announcement_html($announcement, $show_image = true, $show_close = true, $custom_class = '') {
|
||||
$title = esc_html($announcement->title);
|
||||
$message = wpautop(wp_kses_post($announcement->message));
|
||||
$image_url = esc_url($announcement->image_url);
|
||||
$banner_color = esc_attr($announcement->banner_color);
|
||||
$link_url = esc_url($announcement->link_url);
|
||||
$close_text = __('Close', 'pc-announcements-274');
|
||||
$class_names = array('pc-announcements-274-announcement');
|
||||
|
||||
if (!empty($custom_class)) {
|
||||
$class_names[] = $custom_class;
|
||||
}
|
||||
|
||||
$banner_style = '';
|
||||
if (!empty($banner_color) && $banner_color !== '#0d47a1') {
|
||||
$banner_style = 'style="background: ' . $banner_color . ';"';
|
||||
}
|
||||
|
||||
$has_link = !empty($link_url);
|
||||
$link_attrs = $has_link ? 'href="' . $link_url . '" target="_blank" rel="noopener noreferrer"' : '';
|
||||
|
||||
$html = '<div class="' . implode(' ', $class_names) . '" data-announcement-id="' . $announcement->id . '" ' . $banner_style . '>';
|
||||
$html .= '<div class="pc-announcements-274-container">';
|
||||
$html .= '<div class="pc-announcements-274-content">';
|
||||
|
||||
if ($has_link) {
|
||||
$html .= '<a class="pc-announcements-274-link" ' . $link_attrs . '>';
|
||||
}
|
||||
|
||||
if ($show_image && !empty($image_url)) {
|
||||
$html .= '<div class="pc-announcements-274-image">';
|
||||
$html .= '<img src="' . $image_url . '" alt="' . esc_attr($title) . '" loading="lazy">';
|
||||
$html .= '</div>';
|
||||
}
|
||||
|
||||
$html .= '<div class="pc-announcements-274-text">';
|
||||
|
||||
if (!empty($title)) {
|
||||
$html .= '<h3 class="pc-announcements-274-title">' . $title . '</h3>';
|
||||
}
|
||||
|
||||
if (!empty(trim($message))) {
|
||||
$html .= '<div class="pc-announcements-274-message">' . $message . '</div>';
|
||||
}
|
||||
|
||||
$html .= '</div>';
|
||||
|
||||
if ($has_link) {
|
||||
$html .= '</a>';
|
||||
}
|
||||
|
||||
$html .= '</div>';
|
||||
|
||||
if ($show_close && !$has_link) {
|
||||
$html .= '<button class="pc-announcements-274-close" aria-label="' . esc_attr($close_text) . '">';
|
||||
$html .= '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">';
|
||||
$html .= '<path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>';
|
||||
$html .= '</svg>';
|
||||
$html .= '</button>';
|
||||
}
|
||||
|
||||
$html .= '</div>';
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
424
chat/templates/Announcements/public/css/public-style.css
Normal file
424
chat/templates/Announcements/public/css/public-style.css
Normal file
@@ -0,0 +1,424 @@
|
||||
/* PC Announcements 274 - Public Styles */
|
||||
|
||||
/* CSS Custom Properties */
|
||||
:root {
|
||||
--pc-announcements-274-bg-primary: #0d47a1;
|
||||
--pc-announcements-274-bg-secondary: #1565c0;
|
||||
--pc-announcements-274-text-primary: #ffffff;
|
||||
--pc-announcements-274-text-secondary: rgba(255, 255, 255, 0.9);
|
||||
--pc-announcements-274-border-color: rgba(255, 255, 255, 0.2);
|
||||
--pc-announcements-274-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
--pc-announcements-274-shadow-hover: 0 4px 8px rgba(0, 0, 0, 0.15);
|
||||
--pc-announcements-274-close-color: rgba(255, 255, 255, 0.8);
|
||||
--pc-announcements-274-close-hover: #ffffff;
|
||||
--pc-announcements-274-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||
--pc-announcements-274-font-size: 16px;
|
||||
--pc-announcements-274-line-height: 1.5;
|
||||
--pc-announcements-274-border-radius: 8px;
|
||||
--pc-announcements-274-z-index: 9999;
|
||||
--pc-announcements-274-transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
/* Main Announcement Container */
|
||||
.pc-announcements-274-announcement {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
background: linear-gradient(135deg, var(--pc-announcements-274-bg-primary), var(--pc-announcements-274-bg-secondary));
|
||||
border-bottom: 1px solid var(--pc-announcements-274-border-color);
|
||||
box-shadow: var(--pc-announcements-274-shadow);
|
||||
font-family: var(--pc-announcements-274-font-family);
|
||||
font-size: var(--pc-announcements-274-font-size);
|
||||
line-height: var(--pc-announcements-274-line-height);
|
||||
color: var(--pc-announcements-274-text-primary);
|
||||
z-index: var(--pc-announcements-274-z-index);
|
||||
transition: var(--pc-announcements-274-transition);
|
||||
}
|
||||
|
||||
.pc-announcements-274-announcement:hover {
|
||||
box-shadow: var(--pc-announcements-274-shadow-hover);
|
||||
}
|
||||
|
||||
/* Content Container */
|
||||
.pc-announcements-274-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 16px 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Content Layout */
|
||||
.pc-announcements-274-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* Image Styles */
|
||||
.pc-announcements-274-image {
|
||||
flex-shrink: 0;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: var(--pc-announcements-274-border-radius);
|
||||
overflow: hidden;
|
||||
border: 2px solid var(--pc-announcements-274-border-color);
|
||||
box-shadow: var(--pc-announcements-274-shadow);
|
||||
}
|
||||
|
||||
.pc-announcements-274-image img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Text Content */
|
||||
.pc-announcements-274-text {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.pc-announcements-274-title {
|
||||
margin: 0 0 4px 0;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
line-height: 1.3;
|
||||
color: var(--pc-announcements-274-text-primary);
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.pc-announcements-274-message {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
color: var(--pc-announcements-274-text-secondary);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.pc-announcements-274-message p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.pc-announcements-274-message p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Link Styles */
|
||||
.pc-announcements-274-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
transition: var(--pc-announcements-274-transition);
|
||||
}
|
||||
|
||||
.pc-announcements-274-link:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.pc-announcements-274-link:focus {
|
||||
outline: 2px solid var(--pc-announcements-274-close-hover);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
/* Close Button */
|
||||
.pc-announcements-274-close {
|
||||
flex-shrink: 0;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: none;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-radius: 50%;
|
||||
color: var(--pc-announcements-274-close-color);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: var(--pc-announcements-274-transition);
|
||||
padding: 0;
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
.pc-announcements-274-close:hover {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
color: var(--pc-announcements-274-close-hover);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.pc-announcements-274-close:focus {
|
||||
outline: 2px solid var(--pc-announcements-274-close-hover);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.pc-announcements-274-close svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
.pc-announcements-274-announcement.pc-announcements-274-hidden {
|
||||
animation: pc-announcements-274-slide-up 0.4s cubic-bezier(0.4, 0, 0.2, 1) forwards;
|
||||
}
|
||||
|
||||
.pc-announcements-274-announcement.pc-announcements-274-show {
|
||||
animation: pc-announcements-274-slide-down 0.4s cubic-bezier(0.4, 0, 0.2, 1) forwards;
|
||||
}
|
||||
|
||||
@keyframes pc-announcements-274-slide-up {
|
||||
0% {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
max-height: 200px;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(-100%);
|
||||
opacity: 0;
|
||||
max-height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pc-announcements-274-slide-down {
|
||||
0% {
|
||||
transform: translateY(-100%);
|
||||
opacity: 0;
|
||||
max-height: 0;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
max-height: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 768px) {
|
||||
.pc-announcements-274-container {
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
.pc-announcements-274-content {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.pc-announcements-274-image {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.pc-announcements-274-title {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.pc-announcements-274-message {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.pc-announcements-274-close {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.pc-announcements-274-container {
|
||||
padding: 10px 12px;
|
||||
}
|
||||
|
||||
.pc-announcements-274-image {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.pc-announcements-274-title {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.pc-announcements-274-message {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.pc-announcements-274-close {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.pc-announcements-274-close svg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
/* High Contrast Mode Support */
|
||||
@media (prefers-contrast: high) {
|
||||
.pc-announcements-274-announcement {
|
||||
border-bottom: 2px solid #000;
|
||||
}
|
||||
|
||||
.pc-announcements-274-image {
|
||||
border: 2px solid #000;
|
||||
}
|
||||
|
||||
.pc-announcements-274-close {
|
||||
border: 2px solid var(--pc-announcements-274-text-primary);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reduced Motion Support */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.pc-announcements-274-announcement,
|
||||
.pc-announcements-274-close,
|
||||
.pc-announcements-274-announcement:hover {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.pc-announcements-274-close:hover {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.pc-announcements-274-announcement.pc-announcements-274-hidden,
|
||||
.pc-announcements-274-announcement.pc-announcements-274-show {
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.pc-announcements-274-announcement.pc-announcements-274-hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dark Mode Support */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--pc-announcements-274-bg-primary: #1a237e;
|
||||
--pc-announcements-274-bg-secondary: #283593;
|
||||
--pc-announcements-274-text-primary: #ffffff;
|
||||
--pc-announcements-274-text-secondary: rgba(255, 255, 255, 0.85);
|
||||
--pc-announcements-274-border-color: rgba(255, 255, 255, 0.1);
|
||||
--pc-announcements-274-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||
--pc-announcements-274-shadow-hover: 0 4px 8px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print Styles */
|
||||
@media print {
|
||||
.pc-announcements-274-announcement {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* RTL Support */
|
||||
[dir="rtl"] .pc-announcements-274-content {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
[dir="rtl"] .pc-announcements-274-close {
|
||||
margin-left: 0;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
[dir="rtl"] .pc-announcements-274-close:only-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
/* Custom Theme Variations */
|
||||
.pc-announcements-274-announcement.pc-announcements-274-success {
|
||||
--pc-announcements-274-bg-primary: #2e7d32;
|
||||
--pc-announcements-274-bg-secondary: #388e3c;
|
||||
}
|
||||
|
||||
.pc-announcements-274-announcement.pc-announcements-274-warning {
|
||||
--pc-announcements-274-bg-primary: #f57c00;
|
||||
--pc-announcements-274-bg-secondary: #fb8c00;
|
||||
}
|
||||
|
||||
.pc-announcements-274-announcement.pc-announcements-274-error {
|
||||
--pc-announcements-274-bg-primary: #c62828;
|
||||
--pc-announcements-274-bg-secondary: #d32f2f;
|
||||
}
|
||||
|
||||
.pc-announcements-274-announcement.pc-announcements-274-info {
|
||||
--pc-announcements-274-bg-primary: #0277bd;
|
||||
--pc-announcements-274-bg-secondary: #0288d1;
|
||||
}
|
||||
|
||||
/* Compact Version */
|
||||
.pc-announcements-274-announcement.pc-announcements-274-compact {
|
||||
--pc-announcements-274-font-size: 14px;
|
||||
}
|
||||
|
||||
.pc-announcements-274-announcement.pc-announcements-274-compact .pc-announcements-274-container {
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
.pc-announcements-274-announcement.pc-announcements-274-compact .pc-announcements-274-image {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.pc-announcements-274-announcement.pc-announcements-274-compact .pc-announcements-274-title {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.pc-announcements-274-announcement.pc-announcements-274-compact .pc-announcements-274-message {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* No Image Variant */
|
||||
.pc-announcements-274-announcement.pc-announcements-274-no-image .pc-announcements-274-content {
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.pc-announcements-274-announcement.pc-announcements-274-no-image .pc-announcements-274-text {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
/* Hidden State - Animation */
|
||||
.pc-announcements-274-announcement[aria-hidden="true"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Focus Management */
|
||||
.pc-announcements-274-announcement:focus-within {
|
||||
outline: 2px solid var(--pc-announcements-274-close-hover);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
/* Accessibility Improvements */
|
||||
.pc-announcements-274-announcement[role="banner"] {
|
||||
max-height: none;
|
||||
}
|
||||
|
||||
.pc-announcements-274-announcement[role="banner"].pc-announcements-274-hidden {
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Browser-specific fixes */
|
||||
@supports (-webkit-appearance: none) {
|
||||
.pc-announcements-274-close {
|
||||
-webkit-appearance: none;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@supports not (display: grid) {
|
||||
.pc-announcements-274-content {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.pc-announcements-274-text {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
219
chat/templates/Announcements/public/js/public-script.js
Normal file
219
chat/templates/Announcements/public/js/public-script.js
Normal file
@@ -0,0 +1,219 @@
|
||||
jQuery(document).ready(function($) {
|
||||
'use strict';
|
||||
|
||||
// Close announcement functionality
|
||||
$('.pc-announcements-274-close').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
var $announcement = $(this).closest('.pc-announcements-274-announcement');
|
||||
var announcementId = $announcement.data('announcement-id');
|
||||
|
||||
// Add hiding class for animation
|
||||
$announcement.addClass('pc-announcements-274-hidden');
|
||||
|
||||
// Store dismissal in localStorage for this session
|
||||
if (typeof(Storage) !== "undefined" && announcementId) {
|
||||
var dismissed = localStorage.getItem('pc_announcements_274_dismissed') || '[]';
|
||||
var dismissedArray = JSON.parse(dismissed);
|
||||
|
||||
if (dismissedArray.indexOf(announcementId) === -1) {
|
||||
dismissedArray.push(announcementId);
|
||||
localStorage.setItem('pc_announcements_274_dismissed', JSON.stringify(dismissedArray));
|
||||
}
|
||||
}
|
||||
|
||||
// Remove from DOM after animation
|
||||
setTimeout(function() {
|
||||
$announcement.attr('aria-hidden', 'true').hide();
|
||||
|
||||
// Adjust body padding if needed
|
||||
adjustBodyPadding();
|
||||
}, 400);
|
||||
});
|
||||
|
||||
// Adjust body padding to prevent content jump when announcement is hidden
|
||||
function adjustBodyPadding() {
|
||||
var $announcement = $('.pc-announcements-274-announcement');
|
||||
if ($announcement.length === 0) {
|
||||
$('body').css('padding-top', '');
|
||||
return;
|
||||
}
|
||||
|
||||
if ($announcement.is(':visible')) {
|
||||
var announcementHeight = $announcement.outerHeight();
|
||||
var currentPadding = parseInt($('body').css('padding-top')) || 0;
|
||||
|
||||
if (currentPadding < announcementHeight) {
|
||||
$('body').css('padding-top', announcementHeight + 'px');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize padding adjustment
|
||||
$(window).on('load', function() {
|
||||
adjustBodyPadding();
|
||||
});
|
||||
|
||||
// Handle window resize
|
||||
$(window).on('resize', function() {
|
||||
adjustBodyPadding();
|
||||
});
|
||||
|
||||
// Check for dismissed announcements on page load
|
||||
function checkDismissedAnnouncements() {
|
||||
if (typeof(Storage) !== "undefined") {
|
||||
var dismissed = localStorage.getItem('pc_announcements_274_dismissed') || '[]';
|
||||
var dismissedArray = JSON.parse(dismissed);
|
||||
|
||||
$('.pc-announcements-274-announcement').each(function() {
|
||||
var announcementId = $(this).data('announcement-id');
|
||||
if (announcementId && dismissedArray.indexOf(announcementId) !== -1) {
|
||||
$(this).attr('aria-hidden', 'true').hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
checkDismissedAnnouncements();
|
||||
|
||||
// Re-check padding after checking dismissed announcements
|
||||
setTimeout(function() {
|
||||
adjustBodyPadding();
|
||||
}, 100);
|
||||
|
||||
// Keyboard navigation
|
||||
$('.pc-announcements-274-close').on('keydown', function(e) {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
$(this).click();
|
||||
}
|
||||
});
|
||||
|
||||
// Escape key to close announcement
|
||||
$(document).on('keydown', function(e) {
|
||||
if (e.key === 'Escape') {
|
||||
var $visibleAnnouncement = $('.pc-announcements-274-announcement:visible');
|
||||
if ($visibleAnnouncement.length > 0) {
|
||||
$visibleAnnouncement.find('.pc-announcements-274-close').first().focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Auto-hide functionality (optional - could be enabled with a data attribute)
|
||||
function initAutoHide() {
|
||||
$('.pc-announcements-274-announcement[data-auto-hide]').each(function() {
|
||||
var $announcement = $(this);
|
||||
var autoHideTime = parseInt($announcement.data('auto-hide')) * 1000;
|
||||
|
||||
if (autoHideTime > 0) {
|
||||
setTimeout(function() {
|
||||
if ($announcement.is(':visible')) {
|
||||
$announcement.find('.pc-announcements-274-close').click();
|
||||
}
|
||||
}, autoHideTime);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
initAutoHide();
|
||||
|
||||
// Add animation classes on initial load
|
||||
$('.pc-announcements-274-announcement:visible').addClass('pc-announcements-274-show');
|
||||
|
||||
// Handle dynamic content loading (if announcements are loaded via AJAX)
|
||||
function reinitializeAnnouncements() {
|
||||
adjustBodyPadding();
|
||||
checkDismissedAnnouncements();
|
||||
initAutoHide();
|
||||
|
||||
$('.pc-announcements-274-announcement:visible').addClass('pc-announcements-274-show');
|
||||
}
|
||||
|
||||
// Expose reinitialize function for global use
|
||||
window.pcAnnouncements274Reinitialize = reinitializeAnnouncements;
|
||||
|
||||
// Smooth scroll to top when announcement appears (optional)
|
||||
function smoothScrollToTop() {
|
||||
if ($('.pc-announcements-274-announcement:visible').length > 0) {
|
||||
$('html, body').animate({
|
||||
scrollTop: 0
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
|
||||
// Only scroll to top on initial page load if announcement is present
|
||||
if (performance.navigation.type === 0) { // First page load
|
||||
setTimeout(function() {
|
||||
if ($('.pc-announcements-274-announcement:visible').length > 0) {
|
||||
var $announcement = $('.pc-announcements-274-announcement:visible');
|
||||
var announcementId = $announcement.data('announcement-id');
|
||||
|
||||
// Don't scroll if it was just dismissed
|
||||
if (typeof(Storage) !== "undefined" && announcementId) {
|
||||
var dismissed = localStorage.getItem('pc_announcements_274_dismissed') || '[]';
|
||||
var dismissedArray = JSON.parse(dismissed);
|
||||
|
||||
if (dismissedArray.indexOf(announcementId) === -1) {
|
||||
smoothScrollToTop();
|
||||
}
|
||||
} else {
|
||||
smoothScrollToTop();
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// Handle announcement stacking if multiple are shown
|
||||
function handleStacking() {
|
||||
var $announcements = $('.pc-announcements-274-announcement:visible');
|
||||
var offset = 0;
|
||||
|
||||
$announcements.each(function(index) {
|
||||
$(this).css('top', offset + 'px');
|
||||
offset += $(this).outerHeight();
|
||||
});
|
||||
}
|
||||
|
||||
handleStacking();
|
||||
|
||||
// Re-handle stacking on window resize
|
||||
$(window).on('resize', function() {
|
||||
handleStacking();
|
||||
});
|
||||
|
||||
// Accessibility: Focus management
|
||||
function manageFocus() {
|
||||
$('.pc-announcements-274-announcement').attr('role', 'banner');
|
||||
$('.pc-announcements-274-close').attr('tabindex', '0');
|
||||
}
|
||||
|
||||
manageFocus();
|
||||
|
||||
// Performance: Debounce resize events
|
||||
function debounce(func, wait) {
|
||||
var timeout;
|
||||
return function executedFunction() {
|
||||
var context = this;
|
||||
var args = arguments;
|
||||
var later = function() {
|
||||
timeout = null;
|
||||
func.apply(context, args);
|
||||
};
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
};
|
||||
}
|
||||
|
||||
var debouncedResize = debounce(function() {
|
||||
adjustBodyPadding();
|
||||
handleStacking();
|
||||
}, 250);
|
||||
|
||||
$(window).on('resize', debouncedResize);
|
||||
|
||||
// Log for debugging (remove in production)
|
||||
if (window.console && window.console.log && false) { // Set to true for debugging
|
||||
console.log('PC Announcements 274: Initialized');
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user