diff --git a/assets/css/frontend/widget-batch5.css b/assets/css/frontend/widget-batch5.css index 530b4817..ddc37d63 100644 --- a/assets/css/frontend/widget-batch5.css +++ b/assets/css/frontend/widget-batch5.css @@ -2431,3 +2431,51 @@ a.main-color > .icon-cover-card:hover, /* batch31-33 residual */ .aksrt-fi__img.aksrt-lazy { width: 100%; height: 100%; object-fit: cover; display: block; position: absolute; inset: 0; } .aksrt-fi__video { width: 100%; height: 100%; object-fit: cover; position: absolute; inset: 0; } + + +/* batch34-36 residual */ +.widget-hot-posts--graphic .hot-posts-graphic { margin-bottom: 12px; border-radius: 8px; overflow: hidden; } +.widget-hot-posts--graphic .hot-posts-graphic .graphic { position: relative; overflow: hidden; border-radius: 8px; background: var(--surface-2, #f3f4f6); } +.widget-hot-posts--graphic .hot-posts-graphic img.fit-cover { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; } +.widget-hot-posts--graphic .linear-mask { + position: absolute; inset: 0; + background: linear-gradient(to top, rgba(0,0,0,.62), transparent 55%); + pointer-events: none; +} +.widget-hot-posts--graphic .abs-center.left-bottom { position: absolute; left: 0; right: 0; bottom: 0; color: #fff; } +.widget-hot-posts--graphic .hot-posts-graphic__title { font-weight: 600; line-height: 1.35; } +.widget-hot-posts--graphic .hot-post-item { position: relative; align-items: flex-start; gap: 0; } +.widget-hot-posts--graphic .hot-post-item__thumb { + flex: 0 0 72px; width: 72px; height: 54px; border-radius: 8px; overflow: hidden; + position: relative; background: var(--surface-2, #f3f4f6); +} +.widget-hot-posts--graphic .hot-post-item__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; } +.widget-hot-posts--graphic badge.img-badge.left.hot { + position: absolute; top: 6px; left: 6px; z-index: 2; + padding: 2px 6px; border-radius: 4px; font-size: 11px; line-height: 1.2; color: #fff; +} +.widget-hot-posts--graphic badge.img-badge.jb-red { background: #f04438; } +.widget-hot-posts--graphic badge.img-badge.jb-yellow { background: #f79009; color: #111; } +.widget-hot-posts--graphic badge.img-badge.b-gray { background: #667085; } +.widget-hot-posts--graphic badge.img-badge.em12 { font-size: 12px; } +.pagenav.ajax-pag { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; align-items: center; margin-top: 12px; } +.pagenav.ajax-pag .page-numbers { + display: inline-flex; min-width: 32px; height: 32px; padding: 0 8px; + align-items: center; justify-content: center; border-radius: 8px; + background: var(--surface-2, #f3f4f6); color: inherit; text-decoration: none; font-size: 13px; +} +.pagenav.ajax-pag .page-numbers.current { background: var(--theme-color, #f04494); color: #fff; } +.pagenav.ajax-pag .page-numbers.dots { background: transparent; min-width: auto; } +.widget-tab-posts__skeleton .placeholder-row { + display: flex; gap: 10px; align-items: center; padding: 8px 0; +} +.widget-tab-posts__skeleton .thumb-placeholder { + width: 56px; height: 42px; border-radius: 6px; background: var(--surface-2, #eee); +} +.widget-tab-posts__skeleton .placeholder.k1, +.widget-tab-posts__skeleton .placeholder.s1 { + height: 12px; border-radius: 4px; background: var(--surface-2, #eee); +} +.widget-tab-posts__skeleton .placeholder.k1 { width: 80%; } +.widget-tab-posts__skeleton .placeholder.s1 { width: 48%; } +.posts-mini-lists.aksrt-main-posts { /* zibll mini outer */ } diff --git a/assets/js/widget-set.js b/assets/js/widget-set.js index 8726220f..5ee91678 100644 --- a/assets/js/widget-set.js +++ b/assets/js/widget-set.js @@ -25,11 +25,15 @@ var orderby = tab.getAttribute('data-orderby') || 'date'; var cat = tab.getAttribute('data-cat') || '0'; var tabCount = tab.getAttribute('data-tab-count') || '0'; + var style = widget.getAttribute('data-style') || 'mini'; + var paginate = widget.getAttribute('data-paginate') || 'none'; var qs = new URLSearchParams({ count: defaultCount, orderby: orderby, cat: cat, tab_count: tabCount, + style: style, + paginate: paginate, }); var url = rest + (rest.indexOf('?') > -1 ? '&' : '?') + qs.toString(); panel.classList.add('is-ajax-loading'); @@ -42,7 +46,8 @@ .then(function (j) { var d = (j && j.data) || j || {}; var html = d.html || ''; - panel.innerHTML = html || '
'; + var pag = d.paginate_html || d.paginateHtml || ''; + panel.innerHTML = (html || '') + (pag || ''); panel.setAttribute('data-loaded', '1'); panel.classList.remove('is-ajax-loading'); }) diff --git a/inc/helpers/aksrt-ajax-list.php b/inc/helpers/aksrt-ajax-list.php index f870ef22..9013a057 100644 --- a/inc/helpers/aksrt-ajax-list.php +++ b/inc/helpers/aksrt-ajax-list.php @@ -109,3 +109,83 @@ if (!function_exists('aksrt_get_remote_modal_link')) { return '<' . $tag . $attrs . '>' . esc_html($text) . '' . $tag . '>'; } } + +if (!function_exists('aksrt_get_ajax_number_paginate')) { + /** + * Numbered AJAX pager (zibll zib_get_ajax_number_paginate subset). + * + * Links use class next-page ajax-next + ajax-replace so ajax-list.js + * replaces .ajax-item rows inside the nearest .ajaxpager. + * + * @param int $count_all Total items. + * @param int $page Current page (1-based). + * @param int $per_page Per page. + * @param string $ajax_url Base REST/URL (page query key replaced). + * @param string $pag_class Wrapper class. + * @param string $next_class Link base class. + * @param string $query_key Page query arg (default page). + */ + function aksrt_get_ajax_number_paginate( + int $count_all, + int $page = 1, + int $per_page = 10, + string $ajax_url = '', + string $pag_class = 'ajax-pag', + string $next_class = 'next-page ajax-next', + string $query_key = 'page' + ): string { + $page = max(1, $page); + $per_page = max(1, $per_page); + $total_pages = (int) ceil(max(0, $count_all) / $per_page); + if ($total_pages < 2 || $count_all <= 0) { + return ''; + } + + $base = $ajax_url !== '' ? $ajax_url : '#'; + // Ensure %#% placeholder for page numbers. + if (strpos($base, '%#%') === false) { + $base = add_query_arg($query_key, '%#%', $base); + } + + $end_size = 1; + $mid_size = 2; + $links = []; + $dots = false; + + // Prev. + if ($page > 1) { + $url = esc_url(str_replace('%#%', (string) ($page - 1), $base)); + $links[] = ''; + } + + for ($n = 1; $n <= $total_pages; $n++) { + $in_window = $n <= $end_size + || $n > $total_pages - $end_size + || ($n >= $page - $mid_size && $n <= $page + $mid_size); + if (!$in_window) { + if ($dots) { + continue; + } + $links[] = '…'; + $dots = true; + continue; + } + $dots = false; + if ($n === $page) { + $links[] = '' . (int) $n . ''; + } else { + $url = esc_url(str_replace('%#%', (string) $n, $base)); + $links[] = '' . (int) $n . ''; + } + } + + // Next. + if ($page < $total_pages) { + $url = esc_url(str_replace('%#%', (string) ($page + 1), $base)); + $links[] = ''; + } + + return '+ +
++ +
+ +
++
@@ -304,9 +402,13 @@ class WidgetMainPosts extends \WP_Widget { $style = 'list'; } $orderby = sanitize_key((string) ($new_instance['orderby'] ?? 'date')); - if (!in_array($orderby, ['date', 'modified', 'views', 'comments', 'likes', 'rand'], true)) { + if (!in_array($orderby, ['date', 'modified', 'views', 'comments', 'likes', 'favorites', 'downloads', 'rand'], true)) { $orderby = 'date'; } + $paginate = sanitize_key((string) ($new_instance['paginate'] ?? 'none')); + if (!in_array($paginate, ['none', 'ajax', 'number'], true)) { + $paginate = 'none'; + } return [ 'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')), 'count' => max(1, min(30, (int) ($new_instance['count'] ?? 6))), @@ -314,7 +416,9 @@ class WidgetMainPosts extends \WP_Widget { 'orderby' => $orderby, 'cat' => max(0, (int) ($new_instance['cat'] ?? 0)), 'limit_day' => max(0, (int) ($new_instance['limit_day'] ?? 0)), - 'paginate' => sanitize_key((string) ($new_instance['paginate'] ?? 'none')) === 'ajax' ? 'ajax' : 'none', + 'topics' => sanitize_text_field((string) ($new_instance['topics'] ?? '')), + 'pay_type' => sanitize_key((string) ($new_instance['pay_type'] ?? '')), + 'paginate' => $paginate, 'show_thumb' => !empty($new_instance['show_thumb']) ? 1 : 0, 'show_meta' => !empty($new_instance['show_meta']) ? 1 : 0, 'show_number' => !empty($new_instance['show_number']) ? 1 : 0, diff --git a/src/AKSRT/Widgets/WidgetOnelinePosts.php b/src/AKSRT/Widgets/WidgetOnelinePosts.php index e942f9bb..68a3f343 100644 --- a/src/AKSRT/Widgets/WidgetOnelinePosts.php +++ b/src/AKSRT/Widgets/WidgetOnelinePosts.php @@ -63,6 +63,30 @@ class WidgetOnelinePosts extends \WP_Widget { $query['orderby'] = 'date'; $query['order'] = 'DESC'; } + $topics_raw = trim((string) ($instance['topics'] ?? '')); + if ($topics_raw !== '' && taxonomy_exists('topics')) { + $topic_ids = array_values(array_filter(array_map('intval', preg_split('/[,,\s]+/', $topics_raw) ?: []))); + if ($topic_ids) { + $query['tax_query'] = [[ + 'taxonomy' => 'topics', + 'field' => 'term_id', + 'terms' => $topic_ids, + ]]; + } + } + $pay_type = sanitize_key((string) ($instance['pay_type'] ?? '')); + if ($pay_type !== '' && $pay_type !== '0' && $pay_type !== 'no') { + if ($pay_type === 'any' || $pay_type === 'paid') { + $query['meta_query'] = [ + 'relation' => 'OR', + ['key' => '_aksrt_pay_price', 'value' => 0, 'compare' => '>', 'type' => 'NUMERIC'], + ['key' => '_aksrt_pay_type', 'value' => ['reading', 'download', 'gallery', 'video', 'vip'], 'compare' => 'IN'], + ['key' => '_aksrt_visibility', 'value' => ['pay', 'credits'], 'compare' => 'IN'], + ]; + } else { + $query['meta_query'] = [['key' => '_aksrt_pay_type', 'value' => $pay_type]]; + } + } return $query; } @@ -212,6 +236,21 @@ class WidgetOnelinePosts extends \WP_Widget { ++ +
++ +
$orderby, 'cat' => max(0, (int) ($new_instance['cat'] ?? 0)), 'limit_day' => max(0, (int) ($new_instance['limit_day'] ?? 0)), + 'topics' => sanitize_text_field((string) ($new_instance['topics'] ?? '')), + 'pay_type' => sanitize_key((string) ($new_instance['pay_type'] ?? '')), ]; } } diff --git a/src/AKSRT/Widgets/WidgetPaidPosts.php b/src/AKSRT/Widgets/WidgetPaidPosts.php index e4a35b26..17b4ad7a 100644 --- a/src/AKSRT/Widgets/WidgetPaidPosts.php +++ b/src/AKSRT/Widgets/WidgetPaidPosts.php @@ -61,6 +61,14 @@ class WidgetPaidPosts extends \WP_Widget { } else { $query['orderby'] = 'date'; } + $cat = max(0, (int) ($instance['cat'] ?? 0)); + if ($cat > 0) { + $query['cat'] = $cat; + } + $limit_day = max(0, (int) ($instance['limit_day'] ?? 0)); + if ($limit_day > 0) { + $query['date_query'] = [['after' => $limit_day . ' days ago']]; + } return $query; } @@ -157,9 +165,6 @@ class WidgetPaidPosts extends \WP_Widget { $paginate = sanitize_key((string) ($instance['paginate'] ?? 'ajax')); $instance['paginate'] = $paginate; $payload = self::query_payload($instance, 1); - if ($payload['html'] === '' && empty($payload['total'])) { - return; - } echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped $title = apply_filters('widget_title', (string) ($instance['title'] ?? ''), $instance, $this->id_base); @@ -206,6 +211,16 @@ class WidgetPaidPosts extends \WP_Widget { ++ +
++ +
sanitize_text_field((string) ($new_instance['title'] ?? '')), 'count' => max(1, min(20, (int) ($new_instance['count'] ?? 6))), - 'orderby' => $orderby, + 'orderby' => $orderby, + 'cat' => max(0, (int) ($new_instance['cat'] ?? 0)), + 'limit_day' => max(0, (int) ($new_instance['limit_day'] ?? 0)), 'paginate' => sanitize_key((string) ($new_instance['paginate'] ?? 'ajax')) === 'none' ? 'none' : 'ajax', ]; } diff --git a/src/AKSRT/Widgets/WidgetProductList.php b/src/AKSRT/Widgets/WidgetProductList.php index 10cceac7..c9c67078 100644 --- a/src/AKSRT/Widgets/WidgetProductList.php +++ b/src/AKSRT/Widgets/WidgetProductList.php @@ -189,14 +189,32 @@ class WidgetProductList extends \WP_Widget { $paginate_html = '