diff --git a/astra-child-hoponhopoff.zip b/astra-child-hoponhopoff.zip index 49954ce..b6409eb 100644 Binary files a/astra-child-hoponhopoff.zip and b/astra-child-hoponhopoff.zip differ diff --git a/astra-child-hoponhopoff/assets/chrome.js b/astra-child-hoponhopoff/assets/chrome.js index 3f15a38..5e246a2 100644 --- a/astra-child-hoponhopoff/assets/chrome.js +++ b/astra-child-hoponhopoff/assets/chrome.js @@ -63,6 +63,31 @@ } } + /* ---------- header search: expand, then submit ---------- */ + var search = document.querySelector(".header__search"); + if (search) { + var searchInput = search.querySelector(".header__search-input"); + var searchBtn = search.querySelector(".header__search-btn"); + if (searchInput && searchBtn) { + searchBtn.addEventListener("click", function (e) { + if (!search.classList.contains("is-open")) { + e.preventDefault(); + search.classList.add("is-open"); + searchInput.focus(); + } else if (!searchInput.value.trim()) { + e.preventDefault(); + search.classList.remove("is-open"); /* empty → collapse instead of submit */ + } + /* open + has text → let the form submit to the tours archive (?vc_q=) */ + }); + document.addEventListener("click", function (e) { + if (!search.contains(e.target) && !searchInput.value.trim()) { + search.classList.remove("is-open"); + } + }); + } + } + /* ---------- footer: back to top ---------- */ var toTop = document.querySelector(".ring-badge--top"); if (toTop) { diff --git a/astra-child-hoponhopoff/functions.php b/astra-child-hoponhopoff/functions.php index 84ba3dd..0bfc379 100644 --- a/astra-child-hoponhopoff/functions.php +++ b/astra-child-hoponhopoff/functions.php @@ -17,19 +17,34 @@ add_action( 'wp_enqueue_scripts', function () { // Design typeface (same as the plugin's pages). wp_enqueue_style( 'hoho-fonts', 'https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;700;800&display=swap', array(), null ); - // Header/footer design, scoped to .hoho so it can't fight Astra. - wp_enqueue_style( 'hoho-chrome', get_stylesheet_directory_uri() . '/assets/chrome.css', array( 'astra-parent' ), '1.0.0' ); + // Header/footer design, scoped to .hoho so it can't fight Astra. Depend on + // the Astra stylesheet (when present) so our rules load AFTER it and win ties. + $deps = array( 'astra-parent' ); + if ( wp_style_is( 'astra-theme-css', 'registered' ) ) { + $deps[] = 'astra-theme-css'; + } + wp_enqueue_style( 'hoho-chrome', get_stylesheet_directory_uri() . '/assets/chrome.css', $deps, '1.0.1' ); - // Header interactions: burger, submenu, sticky, back-to-top. - wp_enqueue_script( 'hoho-chrome', get_stylesheet_directory_uri() . '/assets/chrome.js', array(), '1.0.0', true ); + // Header interactions: burger, submenu, sticky, back-to-top, search toggle. + wp_enqueue_script( 'hoho-chrome', get_stylesheet_directory_uri() . '/assets/chrome.js', array(), '1.0.1', true ); - // On pages without a full-bleed hero to overlay, the header renders solid and - // sticky (added by chrome.js as .is-solid) so it stays readable and doesn't - // cover content. Hero pages keep the transparent overlay + is-stuck on scroll. wp_add_inline_style( 'hoho-chrome', - '.hoho .site-header.is-solid{position:sticky;inset-block-start:0;padding-block:var(--sp-2);' - . 'background:rgba(0,0,0,.85);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);}' + implode( + '', + array( + // Solid, sticky header on pages without a hero to overlay (added by + // chrome.js as .is-solid) so it stays readable and doesn't cover content. + '.hoho .site-header.is-solid{position:sticky;inset-block-start:0;padding-block:var(--sp-2);background:rgba(0,0,0,.85);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);}', + // Force the design font over Astra inside the header/footer. + '.hoho,.hoho h1,.hoho h2,.hoho h3,.hoho p,.hoho a,.hoho span,.hoho li,.hoho button,.hoho input{font-family:"Plus Jakarta Sans",system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;}', + // Expanding header search field. + '.hoho .header__search{display:flex;align-items:center;gap:.25rem;}', + '.hoho .header__search-input{width:0;min-width:0;padding:0;border:0;outline:0;opacity:0;height:var(--control-h);border-radius:var(--r-pill);background:rgba(255,255,255,.15);color:#fff;transition:width .25s var(--ease),opacity .2s var(--ease),padding .25s var(--ease);}', + '.hoho .header__search.is-open .header__search-input{width:min(52vw,15rem);padding:0 1rem;opacity:1;}', + '.hoho .header__search-input::placeholder{color:rgba(255,255,255,.7);}', + ) + ) ); }, 20 ); diff --git a/astra-child-hoponhopoff/inc/header.php b/astra-child-hoponhopoff/inc/header.php index e1658bf..f9a8898 100644 --- a/astra-child-hoponhopoff/inc/header.php +++ b/astra-child-hoponhopoff/inc/header.php @@ -32,12 +32,12 @@ $hoho_archive = $hoho_archive ? $hoho_archive : home_url( '/' );
- - - - + diff --git a/viator-collector/includes/class-vc-display.php b/viator-collector/includes/class-vc-display.php index 793d139..16058bc 100644 --- a/viator-collector/includes/class-vc-display.php +++ b/viator-collector/includes/class-vc-display.php @@ -62,9 +62,18 @@ class VC_Display { || is_tax( array( 'viator_destination', 'viator_tag', 'viator_category' ) ) ) { return true; } - // A Page hosting the full-listing shortcode also wants full width. + // Any Page hosting a Viator shortcode (hero, sections, listing, …) also + // wants the full-width, no-sidebar canvas. $post = ( is_singular() ) ? get_post() : null; - return $post && has_shortcode( $post->post_content, 'viator_listing' ); + if ( ! $post ) { + return false; + } + foreach ( self::SHORTCODES as $shortcode ) { + if ( has_shortcode( $post->post_content, $shortcode ) ) { + return true; + } + } + return false; } /** @@ -134,9 +143,15 @@ class VC_Display { // Design typeface. wp_enqueue_style( 'vc-fonts', 'https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;700;800&display=swap', array(), null ); - // One scoped stylesheet (#vc-app) covers listing, single, and homepage - // sections — ported from the "Hop On Hop Off" design. - wp_enqueue_style( 'vc-design', VC_PLUGIN_URL . 'assets/css/vc-design.css', array( 'vc-fonts' ), VC_VERSION ); + // One scoped stylesheet (.vc-app) covers listing, single, and homepage + // sections — ported from the "Hop On Hop Off" design. Depend on the Astra + // theme stylesheet (when present) so our rules load AFTER it and win ties. + $deps = array( 'vc-fonts' ); + if ( wp_style_is( 'astra-theme-css', 'registered' ) ) { + $deps[] = 'astra-theme-css'; + } + wp_enqueue_style( 'vc-design', VC_PLUGIN_URL . 'assets/css/vc-design.css', $deps, VC_VERSION ); + wp_add_inline_style( 'vc-design', self::astra_overrides() ); // Front-end interactions: card rails, FAQ accordion, testimonials // marquee, date field, and auto-submit on quick filter toggles. @@ -146,6 +161,32 @@ class VC_Display { add_action( 'wp_footer', 'vc_print_icon_sprite' ); } + /** + * CSS that neutralises Astra's content spacing/width on Viator pages and + * makes the design typography win over the theme. Injected after vc-design.css. + */ + private static function astra_overrides() { + return implode( + '', + array( + // Full-bleed: strip Astra's page-builder article padding/width so + // the hero and sections reach the viewport edges (fixes the extra + // top gap above the hero and the non-full-width sections). + '.vc-fullwidth .site-main>article,.vc-fullwidth .ast-page-builder-template .site-main>article{padding:0;margin:0;border:0;}', + '.vc-fullwidth #primary{margin:0;padding:0;}', + '.vc-fullwidth .site-content .ast-container{max-width:none;padding-inline:0;}', + '.vc-fullwidth .ast-container{max-width:none;}', + '.vc-fullwidth .entry-content{margin-block:0;}', + '.vc-fullwidth .site-content{padding:0;}', + // Typography: force the design font over Astra inside our scopes. + '.vc-app,.vc-app h1,.vc-app h2,.vc-app h3,.vc-app h4,.vc-app h5,.vc-app h6,' + . '.vc-app p,.vc-app a,.vc-app span,.vc-app li,.vc-app button,.vc-app input,' + . '.vc-app select,.vc-app textarea,.vc-app blockquote' + . '{font-family:"Plus Jakarta Sans",system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;}', + ) + ); + } + /** * Read + sanitize the current filter state from the query string. Shared by * the query builder and the archive template so both stay in sync. diff --git a/viator-collector/includes/class-vc-sections.php b/viator-collector/includes/class-vc-sections.php index ad773de..a257dba 100644 --- a/viator-collector/includes/class-vc-sections.php +++ b/viator-collector/includes/class-vc-sections.php @@ -41,16 +41,25 @@ class VC_Sections { public static function hero( $atts ) { $atts = shortcode_atts( array( - 'title' => __( 'Set out on the journey.', 'viator-collector' ), - 'eyebrow' => __( 'Tour & Travel', 'viator-collector' ), - 'image' => '', + 'title' => __( 'Set out on the journey.', 'viator-collector' ), + 'eyebrow' => __( 'Tour & Travel', 'viator-collector' ), + 'image' => '', + 'image_id' => '', // WordPress media attachment ID (responsive). ), $atts, self::HERO ); - $img = $atts['image'] ? $atts['image'] : vc_hero_image_url(); - if ( ! $img ) { + // Prefer a media-library image (responsive srcset); fall back to a URL, + // the plugin's Hero image setting, then the bundled image. + $img = ''; + if ( '' !== $atts['image_id'] ) { + $img = absint( $atts['image_id'] ); + } elseif ( '' !== $atts['image'] ) { + $img = $atts['image']; + } elseif ( vc_hero_image_url() ) { + $img = vc_hero_image_url(); + } else { $img = vc_asset_url( 'img/hero.png' ); } $archive = get_post_type_archive_link( 'viator_tour' ); @@ -64,7 +73,7 @@ class VC_Sections {
- +
diff --git a/viator-collector/includes/helpers.php b/viator-collector/includes/helpers.php index e7beaf2..adc0884 100644 --- a/viator-collector/includes/helpers.php +++ b/viator-collector/includes/helpers.php @@ -506,6 +506,45 @@ function vc_asset_url( $rel ) { return VC_PLUGIN_URL . 'assets/' . ltrim( (string) $rel, '/' ); } +/** + * Hero markup. When the source is a WordPress media item (an attachment + * ID, or a URL that resolves to one), it is rendered with wp_get_attachment_image + * so the browser gets responsive `srcset`/`sizes` and device-appropriate files. + * Anything else (external URLs, bundled fallbacks) falls back to a plain . + * + * @param int|string $src Attachment ID or image URL. + * @param string $class CSS class. + * @param bool $eager Prioritise loading (above-the-fold hero). + */ +function vc_hero_img_html( $src, $class = 'hero__img', $eager = true ) { + $loading = $eager ? 'eager' : 'lazy'; + + $id = is_numeric( $src ) ? (int) $src : (int) attachment_url_to_postid( (string) $src ); + if ( $id ) { + $img = wp_get_attachment_image( + $id, + 'full', + false, + array( + 'class' => $class, + 'loading' => $loading, + 'alt' => '', + 'sizes' => '100vw', + 'fetchpriority' => $eager ? 'high' : 'auto', + ) + ); + if ( $img ) { + return $img; + } + } + + if ( ! $src ) { + return ''; + } + $fetch = $eager ? ' fetchpriority="high"' : ''; + return ''; +} + /** * Print the "Hop On Hop Off" SVG icon sprite once per request. The sprite * holds every plus the #ringPathScroll circular text path diff --git a/viator-collector/templates.zip b/viator-collector/templates.zip new file mode 100644 index 0000000..dc16199 Binary files /dev/null and b/viator-collector/templates.zip differ diff --git a/viator-collector/templates/listing.php b/viator-collector/templates/listing.php index 6582b7e..58f49b1 100644 --- a/viator-collector/templates/listing.php +++ b/viator-collector/templates/listing.php @@ -82,7 +82,7 @@ if ( ! $vc_hero_img ) { ?>
- +
diff --git a/viator-collector/viator-collector.php b/viator-collector/viator-collector.php index b8080e2..d22543a 100644 --- a/viator-collector/viator-collector.php +++ b/viator-collector/viator-collector.php @@ -4,13 +4,13 @@ defined('ABSPATH') || exit; /** * Plugin Name: Viator Collector * Description: Import Viator tours using the Viator Partner API and display them with native WordPress post types, templates, and shortcodes. - * Version: 1.8.0 + * Version: 1.8.1 * Author: Amir Bagheri * License: GPL-2.0-or-later * Text Domain: viator-collector */ -define('VC_VERSION', '1.8.0'); +define('VC_VERSION', '1.8.1'); define('VC_PLUGIN_FILE', __FILE__); define('VC_PLUGIN_DIR', plugin_dir_path(__FILE__)); define('VC_PLUGIN_URL', plugin_dir_url(__FILE__));