Component builder for: Product detail

Error executing template "/Designs/Swift/Paragraph/Swift_ProductPriceTable_Custom.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
   at CompiledRazorTemplates.Dynamic.RazorEngine_356e56e2264a4504afe52bc08f7ac2d0.Execute() in D:\dynamicweb.net\Solutions\twodayco3\carbi.cloud.dynamicweb-cms.com\Files\Templates\Designs\Swift\Paragraph\Swift_ProductPriceTable_Custom.cshtml:line 27
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader)
   at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
   at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()

1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb.Ecommerce.ProductCatalog 3 4 @{ 5 ProductViewModel product = null; 6 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 7 { 8 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 9 } 10 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 11 { 12 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 13 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 14 15 if (productList?.Products is object) 16 { 17 product = productList.Products[0]; 18 } 19 } 20 21 string cultureInfo = Pageview.Area.CultureInfo.Name; 22 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 23 bool anonymousUser = Pageview.User == null; 24 bool hidePrice = anonymousUsersLimitations.Contains("price") && anonymousUser; 25 hidePrice = Pageview.IsVisualEditorMode ? false : hidePrice; 26 27 double priceWithoutVat = product.PriceInformative.PriceWithoutVat; 28 string priceFormattedPrice = priceWithoutVat.ToString("#,0.00", System.Globalization.CultureInfo.GetCultureInfo(cultureInfo)); 29 var priceCurrencyCode = product.PriceInformative.CurrencyCode; 30 } 31 32 @if (!hidePrice) 33 { 34 bool isLazyLoadingForProductInfoEnabled = Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsLazyLoadingForProductInfoEnabled"]); 35 36 if (Pageview.IsVisualEditorMode && product.Prices.Count == 0) 37 { 38 product.Prices.Add(new PriceListViewModel { Price = new PriceViewModel { Price = 95, PriceFormatted = "€95" }, Quantity = 1 }); 39 product.Prices.Add(new PriceListViewModel { Price = new PriceViewModel { Price = 85, PriceFormatted = "€85" }, Quantity = 2 }); 40 } 41 42 string layout = Model.Item.GetRawValueString("Layout", "list"); 43 44 if (product.PriceInformative.Price != 0) 45 { 46 <div class="text-price"><span class="fs-3"><b>@priceCurrencyCode @priceFormattedPrice</b></span> @Translate(" - Vejl. pris ekskl. moms")</div> 47 } 48 } 49 else if (Pageview.IsVisualEditorMode) 50 { 51 <div class="alert alert-dark m-0" role="alert"> 52 <span>@Translate("No products available")</span> 53 </div> 54 } 55

Color

  • Open input
  • Waste bin for office
  • Clean lines in the design
  • Concealed feets and hinges
  • Integrated bag holder

Product model
Model 221
Product - gross weight
15,40 kg
Other informations
Slanted top edge
Material
Steel
Material thickness
1.3 mm
Capacity
100 ltr.
Input
19 x 19 cm
Hidden wheels
No - purchased separately
Adjustable feet
Yes
Bag holder
Yes
Innerbin option
No
Foot pedal
No
Lid with handle
No
Application
Indoors
Front door with soft close
No
Top lid with gas spring
No
Optional RAL color
Yes - at an additional cost
Brand
Bica

Description

Flexible waste bin from Bica ensures easy and user-friendly waste sorting at work. The waste bin is designed with an integrated bag holder and open input for easy waste sorting. Combine with other Bica models with the same depth.

FUNCTIONS
The waste bin is equipped with an integrated and strong bag holder so that the bag stays in place. The removable lid also hides the bag, so the waste bin maintains a stylish design. The waste bin is equipped with adjustable feet, which are concealed behind the plinth.

DESIGN
To achieve high hygiene and minimal maintenance, the waste bin is made of powder-coated steel. The stylish design and clean lines make it a piece of furniture that can naturally be integrated into the interior.
Because of the material you will experience a long-lasting product which is produced on high-tech machines with a focus on precision and quality.

Note: The product is discontinued. 1 piece. left in stock.

Error executing template "Designs/Swift/Paragraph/Swift_ProductDetailsMediaTable_Custom.cshtml"
System.ArgumentNullException: Value cannot be null.
Parameter name: source
   at System.Linq.OrderedEnumerable`2..ctor(IEnumerable`1 source, Func`2 keySelector, IComparer`1 comparer, Boolean descending)
   at System.Linq.Enumerable.OrderByDescending[TSource,TKey](IEnumerable`1 source, Func`2 keySelector)
   at CompiledRazorTemplates.Dynamic.RazorEngine_284aa79599b94ba8a937c16a223ca952.Execute() in D:\dynamicweb.net\Solutions\twodayco3\carbi.cloud.dynamicweb-cms.com\Files\Templates\Designs\Swift\Paragraph\Swift_ProductDetailsMediaTable_Custom.cshtml:line 59
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader)
   at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
   at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()

1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb.Ecommerce.ProductCatalog 3 @using Dynamicweb.Frontend 4 @using System.IO 5 6 @functions { 7 public ProductViewModel product { get; set; } = new ProductViewModel(); 8 public string[] supportedImageFormats { get; set; } 9 public string[] supportedVideoFormats { get; set; } 10 public string[] supportedDocumentFormats { get; set; } 11 public string[] allSupportedFormats { get; set; } 12 13 public class RatioSettings 14 { 15 public string Ratio { get; set; } 16 public string CssClass { get; set; } 17 public string CssVariable { get; set; } 18 public string Fill { get; set; } 19 } 20 21 public RatioSettings GetRatioSettings() 22 { 23 var ratioSettings = new RatioSettings(); 24 25 string ratio = Model.Item.GetRawValueString("ImageAspectRatio", ""); 26 ratio = ratio != "0" ? ratio : ""; 27 string cssClass = ratio != "" && ratio != "fill" ? " ratio" : ""; 28 string cssVariable = ratio != "" && ratio != "fill" ? "--bs-aspect-ratio: " + ratio : ""; 29 30 ratioSettings.Ratio = ratio; 31 ratioSettings.CssClass = cssClass; 32 ratioSettings.CssVariable = cssVariable; 33 ratioSettings.Fill = ratio == "fill" ? " h-100" : ""; 34 35 return ratioSettings; 36 } 37 } 38 39 @{ 40 @* Get the product data *@ 41 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 42 { 43 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 44 } 45 46 @* Supported formats *@ 47 supportedImageFormats = new string[] { ".jpg", ".jpeg", ".webp", ".png", ".gif", ".bmp", ".tiff" }; 48 supportedVideoFormats = new string[] { "youtu.be", "youtube", "vimeo", ".mp4", ".webm" }; 49 supportedDocumentFormats = new string[] { ".pdf", ".docx", ".xlsx", ".ppt", "pptx" }; 50 allSupportedFormats = supportedImageFormats.Concat(supportedVideoFormats).Concat(supportedDocumentFormats).ToArray(); 51 52 @* Collect the assets *@ 53 var selectedAssetCategories = Model.Item.GetRawValueString("ImageAssets").Split(',').ToList(); 54 bool includeImagePatternImages = Model.Item.GetBoolean("ImagePatternImages"); 55 56 @* Needed image data collection to support both DefaultImage, ImagePatterns and Image Assets *@ 57 string defaultImage = product.DefaultImage != null ? product.DefaultImage.Value : ""; 58 IEnumerable<MediaViewModel> assetsImages = product.AssetCategories?.Where(x => selectedAssetCategories.Contains(x.SystemName))?.SelectMany(x => x.Assets); 59 assetsImages = assetsImages.OrderByDescending(x => x.Value.Equals(defaultImage)); 60 IEnumerable<MediaViewModel> assetsList = new MediaViewModel[]{}; 61 62 assetsList = assetsList.Union(assetsImages); 63 assetsList = includeImagePatternImages ? assetsList.Union(product.ImagePatternImages) : assetsList; 64 assetsList = includeImagePatternImages && assetsList.Count() == 0 ? assetsList.Append(product.DefaultImage) : assetsList; 65 66 bool defaultImageFallback = Model.Item.GetBoolean("DefaultImageFallback"); 67 bool showOnlyPrimaryImage = Model.Item.GetBoolean("ShowOnlyPrimaryImage"); 68 69 int totalAssets = 0; 70 if (showOnlyPrimaryImage == false) { 71 foreach (MediaViewModel asset in assetsList) { 72 var assetValue = asset.Value.ToLower(); 73 foreach (string format in allSupportedFormats) { 74 if (assetValue.Contains(format) ) { 75 totalAssets++; 76 } 77 } 78 } 79 } 80 81 if((totalAssets == 0 && product.DefaultImage != null && selectedAssetCategories.Count() == 0) || (showOnlyPrimaryImage == true && product.DefaultImage != null)) 82 { 83 assetsList = new List<MediaViewModel>(){ product.DefaultImage }; 84 totalAssets = 1; 85 } 86 87 int videoNumber = 0; 88 89 @* Layout settings *@ 90 string spacing = Model.Item.GetRawValueString("Spacing", "p-0"); 91 spacing = spacing == "none" ? "p-0" : spacing; 92 spacing = spacing == "small" ? "p-3" : spacing; 93 spacing = spacing == "large" ? "p-5" : spacing; 94 95 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 96 97 bool hideThumbnails = Model.Item.GetBoolean("HideThumbnails"); 98 99 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 100 } 101 102 @* Get assets from selected categories or get all assets *@ 103 104 105 <div class="@spacing@(theme) item_@Model.Item.SystemName.ToLower()"> 106 @if (totalAssets != 0 && assetsList.Count() != 0) 107 { 108 if (!string.IsNullOrEmpty(Model.Item.GetString("Title")) && !Model.Item.GetBoolean("HideTitle")) 109 { 110 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "h3"); 111 112 <h3 class="@titleFontSize mb-3"> 113 @Model.Item.GetString("Title") 114 </h3> 115 } 116 117 <div class="carbi-accordion-container g-col-12 w-100 grid mx-auto"> 118 <div class="accordion g-col-12" id="carbiAccordion"> 119 <div class="accordion-item"> 120 @{ 121 bool hideHeader = Model.Item.GetBoolean("HideGroupHeaders"); 122 string buttonCollapsedState = Model.Item.GetBoolean("OpenDetailsAccordion") ? "" : "collapsed"; 123 string accordionShow = Model.Item.GetBoolean("OpenDetailsAccordion") ? "show" : ""; 124 } 125 126 <h2 class="accordion-header" id="carbi-heading-@Model.ID"> 127 <button class="accordion-button @buttonCollapsedState" type="button" data-bs-toggle="collapse" data-bs-target="#carbi-collapse-@Model.ID" aria-expanded="false" aria-controls="carbi-collapse-@Model.ID"> 128 @if (!hideHeader) 129 { 130 <h4 class="h4 mb-0">@Model.Item.GetRawValueString("Title")</h4> 131 } 132 </button> 133 </h2> 134 <div id="carbi-collapse-@Model.ID" class="accordion-collapse collapse small @accordionShow" aria-labelledby="carbi-heading-@Model.ID"> 135 <div class="table-responsive"> 136 <table class="table align-middle mb-0" style="table-layout: fixed;"> 137 <thead> 138 <tr> 139 @if (!hideThumbnails) 140 { 141 <th style="width:60px">&nbsp;</th> 142 } 143 <th>@Translate("Name")</th> 144 <th class="text-end d-none d-lg-table-cell">@Translate("Download")</th> 145 <th class="text-end" style="width:100px">@Translate("File type")</th> 146 </tr> 147 </thead> 148 <tbody class="border-top-0"> 149 @foreach (MediaViewModel asset in assetsList) 150 { 151 var assetValue = asset.Value.ToLower(); 152 string assetName = !string.IsNullOrEmpty(asset.DisplayName) ? asset.DisplayName : asset.Value.Substring(asset.Value.LastIndexOf('/') + 1); 153 154 bool isVideo = false; 155 foreach (string format in supportedVideoFormats) 156 { 157 //Videos 158 if (assetValue.Contains(format)) 159 { 160 isVideo = true; 161 } 162 } 163 164 if (!isVideo) 165 { 166 string filePath = Dynamicweb.Context.Current.Server.MapPath(assetValue); 167 long fileSize = 0; 168 169 if (File.Exists(filePath)) 170 { 171 fileSize = new System.IO.FileInfo(filePath) != null ? new System.IO.FileInfo(filePath).Length / 1024 : 0; 172 173 foreach (string format in allSupportedFormats) 174 { 175 if (assetValue.Contains(format)) 176 { 177 <tr class="position-relative"> 178 @if (!hideThumbnails) 179 { 180 @RenderAsset(asset) 181 } 182 <td> 183 <a href="@assetValue" class="text-decoration-none text-break" download title="@assetName"> 184 @assetName 185 </a> 186 </td> 187 <td class="text-end d-none d-lg-table-cell"> 188 <a href="@assetValue" class="text-decoration-none stretched-link" download title="@assetName"> 189 @fileSize KB 190 <div class="icon-2" style="z-index: 1">@ReadFile(iconPath + "download.svg")</div> 191 </a> 192 </td> 193 <td class="text-end">@format</td> 194 </tr> 195 } 196 } 197 } 198 } 199 else 200 { 201 string videoType = asset.Value.Contains("youtu.be") || asset.Value.Contains("youtube") ? "Youtube" : ""; 202 videoType = asset.Value.Contains("vimeo") ? "Vimeo" : videoType; 203 204 <tr data-bs-toggle="modal" data-bs-target="#modal_@(Model.ID)_@videoNumber" style="cursor: pointer"> 205 @if (!hideThumbnails) 206 { 207 @RenderAsset(asset) 208 } 209 <td> 210 @assetName 211 </td> 212 <td class="d-none d-lg-table-cell">&nbsp;</td> 213 <td align="right">@videoType</td> 214 </tr> 215 216 videoNumber++; 217 } 218 } 219 </tbody> 220 </table> 221 </div> 222 </div> 223 </div> 224 225 226 </div> 227 </div> 228 229 int modalVideoNumber = 0; 230 foreach (MediaViewModel asset in assetsList) 231 { 232 var assetName = asset.Value.ToLower(); 233 234 foreach (string format in supportedVideoFormats) 235 { //Videos 236 if (assetName.Contains(format)) 237 { 238 <div class="modal fade js-video-modal" id="modal_@(Model.ID)_@modalVideoNumber" tabindex="-1" aria-labelledby="productDetailsTableModalTitle_@(Model.ID)_@modalVideoNumber" aria-hidden="true"> 239 <div class="modal-dialog modal-dialog-centered modal-xl"> 240 <div class="modal-content"> 241 <div class="modal-header visually-hidden"> 242 <h5 class="modal-title" id="productDetailsTableModalTitle_@(Model.ID)_@modalVideoNumber">@product.Title</h5> 243 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 244 </div> 245 <div class="modal-body p-2 p-lg-3 h-100"> 246 @RenderVideoPlayer(asset) 247 </div> 248 </div> 249 </div> 250 </div> 251 252 modalVideoNumber++; 253 } 254 } 255 } 256 } 257 else if (Pageview.IsVisualEditorMode) 258 { 259 RatioSettings ratioSettings = GetRatioSettings(); 260 261 <div class="h-100 @theme"> 262 <div class="alert alert-dark m-0"> 263 @Translate("No assets are available") 264 </div> 265 </div> 266 } 267 268 </div> 269 270 @helper RenderAsset(MediaViewModel asset) 271 { 272 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ImageTheme")) ? " theme " + Model.Item.GetRawValueString("ImageTheme").Replace(" ", "").Trim().ToLower() : ""; 273 string assetValue = asset.Value; 274 275 <td class="@(theme) pe-2"> 276 @foreach (string format in supportedImageFormats) 277 { //Images 278 if (assetValue.Contains(format)) 279 { 280 @RenderImage(asset) 281 } 282 } 283 @foreach (string format in supportedVideoFormats) 284 { //Videos 285 if (assetValue.Contains(format)) 286 { 287 @RenderVideoScreendump(asset) 288 } 289 } 290 @foreach (string format in supportedDocumentFormats) 291 { //Documents 292 if (assetValue.Contains(format)) 293 { 294 @RenderDocument(asset) 295 } 296 } 297 </td> 298 } 299 300 @helper RenderImage(MediaViewModel asset) 301 { 302 string productName = product.Name; 303 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 304 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 305 string imageLinkPath = imagePath; 306 imagePath = $"/Admin/Public/GetImage.ashx?image={imagePath}&width=60&format=webp"; 307 308 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 309 310 RatioSettings ratioSettings = GetRatioSettings(); 311 312 <a href="@imageLinkPath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" download> 313 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 314 <img loading="lazy" src="@imagePath" class="mw-100 mh-100" alt="@productName" @assetTitle itemprop="image" /> 315 </div> 316 </a> 317 } 318 319 @helper RenderVideoScreendump(MediaViewModel asset) 320 { 321 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 322 323 string videoScreendumpPath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : ""; 324 string videoId = videoScreendumpPath.Substring(videoScreendumpPath.LastIndexOf('/') + 1); 325 videoScreendumpPath = videoScreendumpPath.Contains("youtu.be") || videoScreendumpPath.Contains("youtube") ? "https://img.youtube.com/vi/" + videoId + "/maxresdefault.jpg" : videoScreendumpPath; 326 327 string vimeoJsClass = videoScreendumpPath.Contains("vimeo") ? "js-vimeo-video-thumbnail" : ""; 328 videoScreendumpPath = videoScreendumpPath.Contains("vimeo") ? "" : videoScreendumpPath; 329 330 string productName = product.Name; 331 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 332 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 333 334 RatioSettings ratioSettings = GetRatioSettings(); 335 336 <div class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)"> 337 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 338 <div class="icon-2 position-absolute" style="z-index: 1">@ReadFile(iconPath + "play-circle.svg")</div> 339 <img src="@videoScreendumpPath" loading="lazy" decoding="async" alt="@productName" @assetTitle class="@vimeoJsClass mw-100 mh-100" data-video-id="@videoId" style="object-fit: cover;" /> 340 </div> 341 </div> 342 } 343 344 @helper RenderDocument(MediaViewModel asset) 345 { 346 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 347 string productName = product.Name; 348 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 349 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 350 string imageLinkPath = imagePath; 351 imagePath = $"/Admin/Public/GetImage.ashx?image={imagePath}&width=60&format=webp"; 352 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 353 354 RatioSettings ratioSettings = GetRatioSettings(); 355 356 <a href="@imageLinkPath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" download alt="@productName"> 357 @if (asset.Value.Contains(".pdf")) { 358 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 359 <img loading="lazy" src="@imagePath" class="mw-100 mh-100" alt="@productName" @assetTitle /> 360 </div> 361 } else { 362 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 363 <div class="icon-3 position-absolute" style="z-index: 1">@ReadFile(iconPath + "file-text.svg")</div> 364 </div> 365 } 366 </a> 367 } 368 369 @helper RenderVideoPlayer(MediaViewModel asset) 370 { 371 string assetName = !string.IsNullOrEmpty(asset.DisplayName) ? asset.DisplayName : asset.Name; 372 string assetValue = asset.Value; 373 string videoId = asset.Value.Substring(asset.Value.LastIndexOf('/') + 1); 374 string type = assetValue.Contains("youtu.be") || assetValue.Contains("youtube") ? "youtube" : ""; 375 type = assetValue.Contains("vimeo") ? "vimeo" : type; 376 type = assetValue.Contains(".mp4") || assetValue.Contains(".webm") ? "selfhosted" : type; 377 378 <div class="h-100" itemscope itemtype="https://schema.org/VideoObject"> 379 <span class="visually-hidden" itemprop="name">@assetName</span> 380 <span class="visually-hidden" itemprop="contentUrl">@asset.Value</span> 381 <span class="visually-hidden" itemprop="thumbnailUrl">@asset.Value</span> 382 @if (type != "selfhosted") 383 { 384 <div id="player_@(Pageview.CurrentParagraph.ID)_@(videoId)" 385 class="plyr__video-embed" 386 data-plyr-provider="@(type)" 387 data-plyr-embed-id="@videoId" 388 style="--plyr-color-main: var(--swift-foreground-color); height: 100%"> 389 </div> 390 391 <script type="module" src="~/Files/Templates/Designs/Swift/Assets/js/plyr.js"></script> 392 <script type="module"> 393 var player = new Plyr('#player_@(Pageview.CurrentParagraph.ID)_@(videoId)', { 394 type: 'video', 395 youtube: { 396 noCookie: true, 397 showinfo: 0 398 }, 399 fullscreen: { 400 enabled: true, 401 iosNative: true, 402 } 403 }); 404 405 document.querySelectorAll('.js-video-modal').forEach(function (modal) { 406 modal.addEventListener('hidden.bs.modal', function (event) { 407 player.media.pause(); 408 }) 409 }); 410 </script> 411 } 412 else 413 { 414 string videoType = Path.GetExtension(assetValue).ToLower(); 415 416 <video preload="auto" class="h-100 w-100" style="object-fit: cover;"> 417 <source src="@assetValue" type="video/@videoType.Replace(".", "")"> 418 </video> 419 } 420 </div> 421 } 422