### Welcome Message and Setup Logic Source: https://github.com/webasyst/dummy-theme/blob/master/hub/themes/dummy/main.html This section handles the display of a welcome message and guides new users through the initial setup process. It checks if the hub is empty and if the welcome setup is enabled or if a hub ID is present. ```Webasyst Template {if empty($topics) && $wa->currentUrl() == $wa_app_url} {* User went to frontend before completing the 'welcome' setup in backend. *} {if $wa->setting('welcome')} [\`Welcome to your new hub!\`] ================================ {sprintf('[\`Please complete the initial [setup](%s) in app backend.\`]', $wa_backend_url|cat:'hub/?action=welcome')} {* This is a new empty hub. *} {elseif waRequest::param('hub_id')} [\`Welcome to your new hub!\`] ================================ {sprintf('[\`Start by [writing a topic](%s).\`]', $wa_app_url|cat:'add/')} {/if} {else} {$content} {/if} ``` -------------------------------- ### Webasyst Template Example Source: https://github.com/webasyst/dummy-theme/blob/master/blog/themes/dummy/footer.html Demonstrates basic Webasyst template syntax for displaying copyright information and account details, along with a link to the blogging platform. ```Webasyst Template {strip} © {time()|wa_datetime:"Y"} [{$wa->accountName()}]({$wa_url}) [\`[Blogging platform](http://www.webasyst.com/store/app/blog/) by Webasyst\`] {/strip} ``` -------------------------------- ### Webasyst Frontend Template Example Source: https://github.com/webasyst/dummy-theme/blob/master/hub/themes/dummy/footer.html Demonstrates Webasyst template syntax for handling frontend events, iterating through data, displaying dynamic information like dates and account names, and embedding links. ```Webasyst Template {strip} {\* @event frontend\_footer.%plugin\_id% \*} {foreach $frontend\_footer as $\_}{$\_}{/foreach} © {time()|wa\_datetime:"Y"} [{$wa->accountName()}]({$wa_url}) [\`[Feedback software](http://www.webasyst.com/store/app/hub/) by Webasyst\`] {/strip} ``` -------------------------------- ### Navigation Links Source: https://github.com/webasyst/dummy-theme/blob/master/hub/themes/dummy/tag.html Provides examples of creating navigation links using Markdown-like syntax, allowing users to sort or filter content by popularity, recency, or unanswered status. ```markdown [[`Popular topics`]](?sort=popular) [[`Most recent`]](?sort=recent) [[`Unanswered`]](?sort=unanswered) ``` -------------------------------- ### Template Comments and Event Hooks Source: https://github.com/webasyst/dummy-theme/blob/master/hub/themes/dummy/tag.html Shows how to use block comments in the template engine, including a specific example of an event hook comment for frontend tag processing. ```smarty {* @event frontend_tag.%plugin_id% *} ``` -------------------------------- ### Product Page Initialization Source: https://github.com/webasyst/dummy-theme/blob/master/shop/themes/dummy/product.html Initializes the product page functionality using jQuery. It binds event handlers and sets up dynamic content loading based on product data. ```javascript ( function($) { initProductPage({ wrapper: $("#js-product-page"), skus_features_html: $("{$_skus_features_html|json_encode}") }); })(jQuery); ``` -------------------------------- ### Countdown Timer Initialization Source: https://github.com/webasyst/dummy-theme/blob/master/shop/themes/dummy/home.slider.html Initializes a countdown timer for elements with the class 's-promo-countdown'. It retrieves start and end dates from data attributes and creates a new CountDown instance if the constructor is available. ```javascript ( function($) { $(".s-promo-countdown").each( function() { var $wrapper = $(this), options = { $wrapper: $wrapper, start: $wrapper.data('start').replace(/-/g, '/'), end: $wrapper.data('end').replace(/-/g, '/') }; if (typeof CountDown == "function") { new CountDown(options); } else { $wrapper.remove(); } }); })(jQuery); ``` -------------------------------- ### Global Settings and Promo Fetch Source: https://github.com/webasyst/dummy-theme/blob/master/shop/themes/dummy/home.html Sets global theme variables and fetches promotional data. It initializes the theme to hide the sidebar and mark the current page as the homepage, then retrieves promotional links and associated data. ```smarty {$wa->globals("hideSidebar", true)} {$wa->globals("isHomePage", true)} {$promocards = $wa->shop->promos('link', '900')} ``` -------------------------------- ### Initialize Post Component with jQuery Source: https://github.com/webasyst/dummy-theme/blob/master/blog/themes/dummy/post.preview.html This JavaScript snippet initializes a 'Post' component using jQuery. It passes configuration options such as the wrapper element selector, search query status, and retina display preference. This is typically used to enhance the interactivity and display of blog posts on the frontend. ```JavaScript ( function($) { new Post({ wrapper: $("#b-post-{$post.id}"), search_query: {if !empty($is_search_post)}"{$blog_query|escape}"{else}false{/if}, use_retina: {if blogPhotosBridge::is2xEnabled()}true{else}false{/if}, is_review: true }); })(jQuery); ``` -------------------------------- ### Configure Sorting Fields and Active Sort Source: https://github.com/webasyst/dummy-theme/blob/master/shop/themes/dummy/products.sorting.html Defines an associative array of available sorting fields with their display names and retrieves the currently active sort parameter from the web application's GET request, defaulting to 'create_datetime'. ```smarty {$sort_fields = [ 'name' => '[`Name`]', 'price' => '[`Price`]', 'total_sales' => '[`Bestsellers`]', 'rating' => '[`Customer rating`]', 'create_datetime' => '[`Date added`]', 'stock' => '[`In stock`]' ]} {$active_sort = $wa->get('sort', 'create_datetime')} ``` -------------------------------- ### Query Parameter Handling Source: https://github.com/webasyst/dummy-theme/blob/master/hub/themes/dummy/header.html This snippet demonstrates how to retrieve and escape a query parameter named 'query' from the GET request. It uses Smarty's default filter for empty values and escapes the output to prevent XSS vulnerabilities. ```smarty $\_query = $smarty.get.query|default:''|escape ``` -------------------------------- ### Product Page Template Structure Source: https://github.com/webasyst/dummy-theme/blob/master/shop/themes/dummy/product.page.html This snippet demonstrates the core structure of a product page template. It includes placeholders for the page title, main content, and dynamic generation of navigation links for product overview, reviews, and other associated pages. The template uses Webasyst's proprietary syntax for variable interpolation and control structures. ```Webasyst Template {$page.title|escape} ==================== [[\`Overview`]]({\$wa->shop->productUrl(\$product)}) [[`Reviews`] ({\$reviews_total_count})] ({\$wa->shop->productUrl(\$product, 'reviews')}) {foreach $product.pages as $p} [{$p.name|escape}]({\$wa->shop->productUrl(\$product, 'page', ['page_url' => $p.url]}) {/foreach} {$page.content} ``` -------------------------------- ### Display Shop Business Hours (Smarty) Source: https://github.com/webasyst/dummy-theme/blob/master/site/themes/dummy/header.layout.html Fetches and displays the shop's business hours for the current week. It handles cases where the shop is open on a given day, showing start and end times, or marks the day as off. It also includes logic to fetch schedule data if the 'use_shop_schedule' setting is enabled. ```smarty {if $wa->shop} {if !empty($theme_settings.use_shop_schedule) && method_exists($wa->shop, 'schedule')} {$_schedule = $wa->shop->schedule()} {_wd("shop", "Business hours")} {foreach $_schedule.current_week as $_day} {$_day.name|escape} {if !empty($_day.work)} {$_day.start_work|escape} — {$_day.end_work|escape} {else} {_wd("shop", "day off")} {/if} {/foreach} {elseif !empty($theme_settings.manual_schedule)} {$theme_settings.manual_schedule|escape} {/if} {$_phone = $wa->shop->settings('phone')} {if !empty($_phone)} {$_phone} {/if} {/if} ``` -------------------------------- ### Product Listing Rendering Source: https://github.com/webasyst/dummy-theme/blob/master/shop/themes/dummy/home.slider.html Iterates through the `$_products` array to display product information, including images, names, summaries, prices, and badges. It uses helper functions for image URLs, currency formatting, and badge HTML. ```php-template {elseif !empty($_products)} {foreach $_products as $product} {$_product_image_src = $wa->shop->productImgUrl($product, "0x320@2x")} {$_name = $product.name} {if $product.summary} {$_name = "`$product.name` — {strip_tags($product.summary)|escape}"} {/if}* [{* ![{$_name}]({$_product_image_src}) *}]({$product.frontend_url} "{$_name}") [{$product.name}]({$product.frontend_url} "{$_name}") ----------------------------------------------------- {if $product.summary}{strip_tags($product.summary)|truncate:255}{/if} {shop_currency_html($product.price)} {if !empty($product.summary)} {/if} {$badge_html = $wa->shop->badgeHtml($product.badge)} {if !empty($badge_html)} {$badge_html} {/if} {/foreach} {/if} ``` -------------------------------- ### Blog Listing and Navigation Source: https://github.com/webasyst/dummy-theme/blob/master/blog/themes/dummy/sidebar.html Displays a list of blogs available within the system and provides links to each blog. Includes a fallback for displaying all posts if no specific blogs are found. ```Webasyst Template {foreach $wa->blog->blogs() as $blog}* [{$blog.name}]({$blog.link}) {foreachelse}* [[`All posts`]]({$wa->blog->url()}) {/foreach} ``` -------------------------------- ### Conditional Password Form Rendering Source: https://github.com/webasyst/dummy-theme/blob/master/site/themes/dummy/forgotpassword.html This snippet demonstrates how to conditionally display a password form in a Webasyst template. It checks if a variable `$set_password` is not empty. If true, it renders the set password form; otherwise, it renders the forgot password form. Both forms utilize helper methods from the `$wa` object, passing an error variable and an option to show the title. ```Webasyst Template {strip} {$wa->globals("hideSidebar", true)} {if !empty($set_password)} {$wa->setPasswordForm($error, [ 'show_title' => true ])} {else} {$wa->forgotPasswordForm($error, [ 'show_title' => true ])} {/if} {/strip} ``` -------------------------------- ### Product Image Gallery Initialization Source: https://github.com/webasyst/dummy-theme/blob/master/shop/themes/dummy/product.html Initializes the product photo gallery functionality using jQuery, targeting a specific wrapper element for dynamic image handling. ```JavaScript ( function($) { new ProductPhotos({ $wrapper: $("#s-product-photos") }); })(jQuery); ``` -------------------------------- ### JavaScript: Product Initialization and Lazy Loading Source: https://github.com/webasyst/dummy-theme/blob/master/shop/themes/dummy/products.html Initializes the product display components using JavaScript, including setting up comparison functionality and handling lazy loading for pagination. It dynamically loads the 'products.js' script if it's not already available. ```JavaScript ( function($) { var is_products_exist = (typeof Products === "function"); function initProducts() { var $products = $("#s-products-wrapper").removeAttr("id"); new Products({ $wrapper: $products, compare: { url: "{$wa->getUrl("/frontend/compare")}", title: "[`Compare selected products`]" } }); var initLazyLoading = {if isset($pages_count) && $pages_count > 1 && $theme_settings.pagination == "lazyloading"}true{else}false{/if}; if (initLazyLoading) { new LazyLoading({ $wrapper: $products, names: { list: ".s-products-list", items: ".s-product-wrapper", paging: ".s-paging-wrapper" } }); } } if (!is_products_exist) { $.getScript("{$wa_theme_url}js/products.js?v{$wa_theme_version}", function() { initProducts(); }); } else { initProducts(); } })(jQuery); ``` -------------------------------- ### Initialize Checkout JavaScript Module Source: https://github.com/webasyst/dummy-theme/blob/master/shop/themes/dummy/checkout.html Loads the `checkout.js` script using jQuery's `getScript` and then initializes a new `Checkout` class instance. This is typically used to enable interactive features for the checkout page. It requires jQuery to be loaded and the `checkout.js` file to be accessible at the specified theme URL. ```javascript ( function($) { $.getScript("{$wa_theme_url}js/checkout.js", function() { new Checkout({ $wrapper: $(".s-checkout-page") }) }); })(jQuery); ``` -------------------------------- ### Helpdesk Sidebar Pages Source: https://github.com/webasyst/dummy-theme/blob/master/helpdesk/themes/dummy/sidebar.html Fetches and renders a list of helpdesk pages in the sidebar using the previously defined `renderNavItem` function. This provides a structured way to navigate helpdesk content. ```smarty {* SIDEBAR NAV *} {$_pages = $wa->helpdesk->pages()} {if !empty($_pages)} {foreach $_pages as $page} {renderNavItem page=$page} {/foreach} {/if} {/if} ``` -------------------------------- ### Product Page Structure and Navigation Source: https://github.com/webasyst/dummy-theme/blob/master/shop/themes/dummy/product.html Renders the main product page layout, including the image gallery, product name, cart inclusion, and tabbed navigation for overview, features, reviews, and custom pages. It dynamically includes content based on product data. ```Webasyst Template {$product.name|escape} ====================== {* IMAGE GALLERY *} {if $product.images} {$video = $product->video} {* MAIN IMAGE *} {if $video} {if !empty($_video.images[0])} {$_thumb = $_video.images[0]} {$_absolute_thumb_uri = "{$wa->url(true)}{$_thumb|substr:1}"} {/if} {/if} [{$wa->shop->productImgHtml($product, '750', [ 'itemprop' => 'image', 'alt' => $product.name|escape ])}]({$wa->shop->productImgUrl($product, '970')}) {* THUMBS *} {if count($product.images) > 1 || (count($product.images) === 1 && $video)} {foreach $product.images as $image}* {* @hint link id needed for change product image on sku change event *} [{$wa->shop->imgHtml($image, '96x96')}]({$wa->shop->imgUrl($image, '970')}) {/foreach} {if $video}* {* @hint link id needed for change product image on sku change event *} [![]({$video.images[0]})]({$video.url}) {/if} {/if} {/if} {* PRODUCT CART *} {include file="product.cart.html" inline} {if !empty($frontend_product)} {* @event frontend_product.%plugin_id%.cart *} {foreach $frontend_product as $_}{$_}.cart{/foreach} {* @event frontend_product.%plugin_id%.block_aux *} {foreach $frontend_product as $_}{$_}.block_aux{/foreach} {/if} {* TABS *} [[`Overview`]]({$wa->shop->productUrl($product)}) {if $product.features} [[`Features`]]({$wa->shop->productUrl($product)}) {/if} [[`Reviews` ({$reviews_total_count})]]({$wa->shop->productUrl($product, 'reviews')}) {foreach $product.pages as $page} [{$page.name|escape}]({$wa->shop->productUrl($product, 'page', ['page_url' => $page.url])}) {/foreach} {* @event frontend_product.%plugin_id%.menu *} {foreach $frontend_product as $_}{$_}.menu{/foreach} {* TABS CONTENT *} {* OVERVIEW *} {if $product.description} {$product.description} {/if} {* CATEGORIES *} {if count($product.categories) > 1} [`Categories`]: {foreach $product.categories as $c} {if $c.status} [{$c.name|escape}]({$wa->getUrl('/frontend/category', ['category_url' => $c.full_url])}) {/if} {/foreach} {/if} {* TAGS *} {if $product.tags} [`Tags`]: {foreach $product.tags as $t} [{$t}]({$wa->getUrl('/frontend/tag', ['tag' => str_replace('%2F', '/', urlencode($t))])}) {/foreach} {/if} {* PRODUCT FEATURES *} {if $product.features} {if !empty($_skus_features_html[$product.sku_id])}{$_skus_features_html[$product.sku_id]}{/if} {/if} {* PRODUCT REVIEWS *} ### {sprintf('[`%s reviews`]', $product.name|escape)} {if !empty($rates)} {if ($product.rating > 0)} [`Average customer rating:`] {$wa->shop->ratingHtml($product.rating, 16)} ([{$reviews_total_count}](reviews/)) {if $product.rating > 0} {sprintf('[`%s out of 5 stars`]', $product.rating)} {/if} {/if} {$_total_count = 0} {foreach $rates as $_rate => $_count} {$_total_count = $_total_count + $_count} {/foreach} {* foreach $rates as $_rate => $_count *} {for $i = 5 to 0 step -1} {if empty($rates[$i]) || !$rates[$i]}{$_count = 0}{else}{$_count = $rates[$i]}{/if} {if $i || $_count} {/if} {/for} {$_count} {for $j=1 to $i} {forelse} [`no rate`] {/for} {/if} {foreach $reviews as $review} {include file="review.html" reply_allowed=false inline} {/foreach} {if !$reviews} {sprintf('[`Be the first to [write a review](%s) of this product!`]', 'reviews/')} {/if} {if !empty($reviews)} [[`Reviews` ({$reviews_total_count})](reviews/) {/if} [[`Write a review`](reviews/#publish) {* @event frontend_product.%plugin_id%.block *} {foreach $frontend_product as $_}{$_}.block{/foreach} {* RELATED PRODUCTS *} {$crossselling = $product->crossSelling(12)} {if !empty($crossselling)} ``` -------------------------------- ### List Webasyst Apps (Smarty) Source: https://github.com/webasyst/dummy-theme/blob/master/site/themes/dummy/header.layout.html Iterates through available Webasyst applications and generates a markdown-formatted list of links to each app. This snippet checks if any apps are available before rendering the list. ```smarty {if $wa->apps()} {foreach $wa->apps() as $a}* [{$a.name}]({$a.url}) {/foreach} {/if} ``` -------------------------------- ### Image Gallery Interaction with Swipebox Source: https://github.com/webasyst/dummy-theme/blob/master/shop/themes/dummy/review.html This JavaScript code initializes an image gallery interaction for review images. It uses jQuery to attach a click event to elements with the class 'js-show-image'. When clicked, it collects image URLs and descriptions, then opens them using the Swipebox library for a mobile-friendly lightbox experience. ```javascript ( function($) { var $document = $(document), $review = $(".s-review-item[data-id=\"" + {$review.id|escape} + "\"]"); $review.on("click", ".js-show-image", function(event) { event.preventDefault(); var $image = $(this), images = []; $review.find(".js-show-image").each(function () { var $_image = $(this); images.push({ href: $_image.attr("href"), title: escape($_image.attr("title")) }); }); var k = $image.prevAll('.js-show-image').length; if (k) { images = images.slice(k).concat(images.slice(0, k)); } $.swipebox(images, { useSVG : false, hideBarsDelay: false, afterOpen: function() { $document.on("scroll", closeSwipe); function closeSwipe() { var $closeButton = $("#swipebox-close"); if ($closeButton.length) { $closeButton.trigger("click"); } $document.off("scroll", closeSwipe); } } }); function escape(string) { return $("
").text(string).html(); } }); })(jQuery); ``` -------------------------------- ### Conditional Helpdesk Welcome Message Source: https://github.com/webasyst/dummy-theme/blob/master/helpdesk/themes/dummy/home.html This snippet displays a welcome message for the helpdesk section only if no categories are currently defined. It includes a link to the helpdesk backend for adding frequently asked questions. ```PHP Template {strip} {if empty($categories)} [`Welcome to new helpdesk section on your site!`] ===================================================== {sprintf_wp('Start by [filling database of frequently asked questions](%s) in your helpdesk backend.', $wa_backend_url|cat:'helpdesk/#/faq/new/')} {/if} {/strip} ``` -------------------------------- ### Review Image Upload JavaScript Initialization Source: https://github.com/webasyst/dummy-theme/blob/master/shop/themes/dummy/reviews.html Initializes the JavaScript functionality for handling image uploads in the review section. It configures maximum file sizes, upload limits, and locale-specific messages for user feedback. ```javascript ( function($) { {$_max_post_size = waRequest::getPostMaxSize()} {$_max_file_size = waRequest::getUploadMaxFilesize()} {$_max_post_size_mb = floor($_max_post_size * 10/(1024))/10} {$_max_file_size_mb = floor($_max_file_size * 10/(1024))/10} new ReviewImagesSection({ wrapper: $("#js-review-images-section"), max_post_size: {$_max_post_size|json_encode}, max_file_size: {$_max_file_size|json_encode}, max_files: 10, templates: { "file": "[(`Add a description`)](javascript:void(0);)\n .st0 { fill:none;stroke:rgba(0,0,0,0.5);stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10; }", "error": "%text%" }, patterns: { "file": "images[%index%]", "desc": "images_data[%index%][description]" }, locales: { "files_limit": {_w("You can upload a maximum of 10 photos.")|json_encode}, "file_type": {_w("Unsupported image type. Use PNG, GIF and JPEG image files only.")|json_encode}, "post_size": {_w("Total size of selected files cannot be greater than")|json_encode} + " " + {$_max_post_size_mb|json_encode} + {_w("KB")|json_encode} + ".", "file_size": {_w("Each file’s size cannot be greater than")|json_encode} + " " + {$_max_file_size_mb|json_encode} + {_w("KB")|json_encode} + "." } }); })(jQuery); ``` -------------------------------- ### Webasyst Template: Product List Rendering Source: https://github.com/webasyst/dummy-theme/blob/master/shop/themes/dummy/products.html Renders a list of products, iterating through each product to display its name, image, price, rating, and availability. It includes logic for handling stock status, badges, and conditional display of buttons like 'Compare' and 'Add to Cart'. ```Webasyst Template {strip} {if !empty($products)} {$add2cart_label = '[`Buy`]'} {if $wa->shop->cart->total() > 0} {$add2cart_label = _wd('shop', 'Add to cart')} {/if} {if !empty($theme_settings.list_features)} {$features = $wa->shop->features($products)} {/if} {$_types = ["thumbs" => "thumbs-view", "table" => "table-view"]} {$_type = $_types["thumbs"]} {if !empty($type)} {$_type = $_types[$type]} {else} {$_settings_type = ifset($theme_settings.related_view_type)} {if !empty($_settings_type) && $_settings_type == "table"} {$_type = $_types["table"]} {/if} {/if} {if !empty($sorting)} {include file="./products.sorting.html" inline} {/if} {foreach $products as $product} {$available = $wa->shop->settings('ignore_stock_count') || $product.count === null || $product.count > 0} {$badge_html = $wa->shop->badgeHtml($product.badge)} {$_product_image_src = $wa->shop->productImgUrl($product, "200")} {if !$_product_image_src} {$_product_image_src = "`$wa_theme_url`img/dummy200.png"} {/if} [![{$product.name}]({$_product_image_src})]({$product.frontend_url} "{$product.name}") ##### [{$product.name}]({$product.frontend_url} "{$product.name}") {if $product.summary} {strip_tags($product.summary)|truncate:100} {/if} {if $available} 1}data-url="{$product.frontend_url}{if strpos($product.frontend_url, '?')}&{else}?{/if}cart=1" method="post" action="{$wa->getUrl('/frontendCart/add')}"> {/if} {if $available} {shop_currency_html($product.price)} {if $product.compare_price > 0} {shop_currency_html($product.compare_price)} {/if} {else} {shop_currency_html($product.price)} **{if $wa->shop->settings('ignore_stock_count')} {_wd('shop', 'Pre-order only')} {else} {_wd('shop', 'Out of stock')} {/if}** {/if} {if $product.rating > 0} {$wa->shop->ratingHtml($product.rating, 16)} {_w('%d review', '%d reviews', $product.rating_count)} {else} [`No review's`] {/if} {if !($product.sku_count > 1)} {/if} {if empty($hide_buttons)} {if empty($disable_compare)} [](javascript:void(0); "[`Compare`]"){/if} {if $available} {/if} {/if} {if $available} {/if} {if !empty($badge_html)} {$badge_html} {/if} {/foreach} {if isset($pages_count) && $pages_count > 1} {wa_pagination total=$pages_count attrs=["class" => "s-paging-list"]} {/if} {/if} {/strip} ``` -------------------------------- ### Blog Post Stream Rendering Source: https://github.com/webasyst/dummy-theme/blob/master/blog/themes/dummy/stream.html Renders a stream of blog posts, handling search results and preview inclusion. It uses conditional logic for search versus regular display and includes post previews via an external file. ```smarty {if !$is_lazyloading and !empty($stream_title)} {$stream_title|escape} ======================= {/if} {foreach $posts as $post} {if !$is_search} {include file="./post.preview.html" post=$post inline} {else} {include file="./post.preview.html" post=$post is_search_post=true inline} {/if} {/foreach} ``` -------------------------------- ### Initialize Product JavaScript Class Source: https://github.com/webasyst/dummy-theme/blob/master/shop/themes/dummy/product.cart.html This JavaScript snippet initializes a `Product` class, likely responsible for client-side product interactions like SKU selection, price updates, and adding to cart. It checks if the `Product` class is already defined; if not, it loads the `product.js` script dynamically. The class is then instantiated with configuration data passed from the Smarty template, including dialog status, currency info, SKUs, services, and features. ```JavaScript ( function($) { var is_product_exist = (typeof Product === "function"); (!is_product_exist) ? $.getScript("{$wa_theme_url}js/product.js?v{$wa_theme_version}", initProduct) : initProduct(); function initProduct() { new Product({ $form: $("#s-product-form{if $_is_dialog}-dialog{/if}"), is_dialog: {if $_is_dialog}true{else}false{/if}, currency: {json_encode($currency_info)}, skus: {$product.skus|json_encode}, services: {if count($product.skus) > 1 or $product.sku_type}{json_encode($sku_services)}{else}false{/if}, features: {if $product.sku_type}{json_encode($sku_features_selectable)}{else}false{/if}, default_sku_features: {$default_sku_features|default:""|json_encode} }); } })(jQuery); ``` -------------------------------- ### Webasyst Theme Conditional Rendering Source: https://github.com/webasyst/dummy-theme/blob/master/site/themes/dummy/main.html This snippet implements conditional logic for a Webasyst theme. It checks if the current URL matches the application URL and if the page is empty (no ID or content). If both conditions are true, it includes a welcome page; otherwise, it renders the main content. This is common for setting up default or welcome views in Webasyst applications. ```php {strip} {\$_is_main_page = ( $wa->currentUrl() == $wa_app_url && ( empty($page.id) && empty($page.content) ) )} {if $\$_is_main_page} {include file="./page.welcome.html" inline} {else} {$content} {/if} {/strip} ``` -------------------------------- ### Render Sidebar Navigation Pages Source: https://github.com/webasyst/dummy-theme/blob/master/hub/themes/dummy/sidebar.html Fetches and renders a list of pages for the sidebar navigation. It uses the previously defined `renderNavItem` function to handle hierarchical page structures. Dependencies include `$wa->hub->pages()` and the `renderNavItem` function. ```webasyst-template {\* SIDEBAR NAV \*} {$\$\_pages = $wa->hub->pages()} {if !empty($\$\_pages)} {foreach $\_pages as $page} {renderNavItem page=$page} {/foreach} {/if} ``` -------------------------------- ### Product Review Display Logic Source: https://github.com/webasyst/dummy-theme/blob/master/shop/themes/dummy/reviews.html This snippet demonstrates the core logic for displaying product reviews, including nested replies and handling different review depths. It iterates through reviews and includes a 'review.html' template for each. ```smarty {strip} {$wa->title(sprintf('[`%s reviews`]', $product.name))} {$current_user_id = $wa->userId()} {function review_reviews} {$depth=-1} {foreach $reviews as $review} {if $review.depth < $depth} {$loop=($depth-$review.depth)} {section name="end-review" loop=$loop} {/section} {$depth=$review.depth} {/if} {if $review.depth == $depth} {/if} {if $review.depth > $depth} {$depth=$review.depth} {/if} {include file="review.html" inline reply_allowed=$reply_allowed single_view=true review=$review} {/foreach} {section name="end-review" loop=$depth} {/section} {/function} {sprintf('[`%s reviews`]', $product.name|escape)} ===================================================== {if empty($current_user_id) && $require_authorization} {sprintf( '[`To add a review please [sign up](%s) or [login](%s)`]', $wa->signupUrl(), $wa->loginUrl()) } {else} {if !empty($current_user_id)} **![]({$wa->user()->getPhoto(20)}){$wa->user('name')}** [(`log out`)](?logout) {else} {if $auth_adapters} * [`Guest`](#) {foreach $auth_adapters as $adapter} {$adapter_id = $adapter->getId()} * [![]({$adapter->getIcon()}){$adapter->getName()}]({$adapter->getCallbackUrl(0)}&app=shop{if !$require_authorization}&guest=1{/if}) {/foreach} {/if} {if !empty($auth_adapters[$current_auth_source])} {$adapter = $auth_adapters[$current_auth_source]} [`Your name`] **![]({$adapter->getIcon()}){$current_auth.name|escape}** [(`log out`)](?logout) {/if} {/if} #### [`Rate product`] {for $i = 1 to 5} {/for} {$_images_enabled = $wa->setting("allow_image_upload", false, "shop")} {if !empty($_images_enabled)} #### [`Images`] {strip} [`Upload photos`] [`or drag & drop here (max. 10 photos)`] {/strip} {strip} {capture assign="_file_template"} [(`Add a description`)](javascript:void(0);) .st0 { fill:none;stroke:rgba(0,0,0,0.5);stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10; } {/capture} {/strip} {strip} {capture assign="_error_template"} %text% {/capture} {/strip} ( function($) { {$_max_post_size = waRequest::getPostMaxSize()} {$_max_file_size = waRequest::getUploadMaxFilesize()} {$_max_post_size_mb = floor($_max_post_size * 10/(1024))/10} {$_max_file_size_mb = floor($_max_file_size * 10/(1024))/10} new ReviewImagesSection({ wrapper: $("#js-review-images-section"), max_post_size: {$_max_post_size|json_encode}, max_file_size: {$_max_file_size|json_encode}, max_files: 10, templates: { "file": {$_file_template|json_encode}, "error": {$_error_template|json_encode} }, patterns: { "file": "images[%index%]", "desc": "images_data[%index%][description]" }, locales: { "files_limit": {_w("You can upload a maximum of 10 photos.")|json_encode}, "file_type": {_w("Unsupported image type. Use PNG, GIF and JPEG image files only.")|json_encode}, "post_size": {_w("Total size of selected files cannot be greater than")|json_encode} + " " + {$_max_post_size_mb|json_encode} + {_w("KB")|json_encode} + ".", "file_size": {_w("Each file’s size cannot be greater than")|json_encode} + " " + {$_max_file_size_mb|json_encode} + {_w("KB")|json_encode} + "." } }); })(jQuery); {/if} {$_moderate_enabled = $wa->setting('moderation_reviews', 0, 'shop')} {if !empty($_moderate_enabled)} [`Your review will be published after moderation.`] {/if} {if $request_captcha && empty($current_user_id)} {$wa->captcha()} {/if} {if empty($current_user_id) && !empty($review_service_agreement) && !empty($review_service_agreement_hint)} {if $review_service_agreement == 'checkbox'} post('service_agreement') || $wa->storage('shop_review_agreement')} checked{/if}> {$review_service_agreement_hint} {/if} [`cancel`](javascript:void(0);) {/if} {if count($reviews) > 0} ### {_w('%d review for ','%d reviews for ', $reviews_count)|cat:$product.name|escape} {foreach $reviews as $review} {include file="review.html" reply_allowed=$reply_allowed inline} {if !empty($review.comments)} {review_reviews reviews=$review.comments} {else} {/if} {/foreach} {else} [`Write a review`] {/if} {/strip} ```