Error executing template "Designs/RoadPro/eCom/Product/ProductRedirect.cshtml" System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: Collection was modified; enumeration operation may not execute. at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource) at System.Collections.Generic.Dictionary`2.Enumerator.MoveNext() at Dynamicweb.Modules.Searching.Rules.Parser.UnescapeStrings(String s) at Dynamicweb.Modules.Searching.Rules.Parser.ParseSimpleExpression(String expression) at Dynamicweb.Modules.Searching.Rules.Parser.Parse(String input) at Dynamicweb.ItemPublisher.FilterHelper.ToXml(String filter) at Dynamicweb.ItemPublisher.Frontend.GetContentBySettings(String settings) --- End of inner exception stack trace --- at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at Dynamicweb.Extensibility.AddIns.AddInManager.InvokeFunction(Object instance, String functionName, Object[] arguments) at Dynamicweb.Rendering.TemplateBase`1.RenderItemList(Object settings) at CompiledRazorTemplates.Dynamic.RazorEngine_1fa3fc96003943e490c7cc48ce659379.Execute() in F:\Domains\Sites\dev-rpro.mydwsite3.com\Files\Templates\Designs\RoadPro\eCom\Product\ProductRedirect.cshtml:line 582 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 RazorTemplateBase<RazorTemplateModel<Template>> 2 @using Dynamicweb.Rendering; 3 4 @if(!string.IsNullOrEmpty(System.Web.HttpContext.Current.Request.Params["detail"]) && GetInteger("Ecom:Product.PrimaryOrCurrentPageID") != Pageview.Page.ID) 5 { 6 string redirect = "/Default.aspx?ID=" + GetString("Ecom:Product.PrimaryOrCurrentPageID") + "&ProductID=" + GetString("Ecom:Product.ID"); 7 if(!string.IsNullOrEmpty(System.Web.HttpContext.Current.Request.QueryString["variantID"])) 8 { 9 redirect += "&variantID=" + System.Web.HttpContext.Current.Request.QueryString["variantID"].ToString(); 10 } 11 System.Web.HttpContext.Current.Response.Redirect(Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(redirect)); 12 } 13 @inherits RazorTemplateBase<RazorTemplateModel<Template>> 14 @using System 15 @using Dynamicweb.Rendering; 16 @using System; 17 @using System.IO; 18 @using System.Web; 19 @using System.Text; 20 @using System.Collections.Generic; 21 @using System.Linq 22 @using System.Text.RegularExpressions; 23 @using Dynamicweb.Content.Items 24 @{ string designName = GetString("Template:DesignBaseUrl").Replace("/Files/Templates/Designs/", "").Replace("/", "");}@functions{ 25 public static string GetImage(string sourceString, int imageWidth, int imageHeight, int imageWidthTablet = 0, int imageHeightTablet = 0, int imageWidthMobile = 0, int imageHeightMobile = 0, string imageFormat = "jpg", int imageCompression = 0, int imageCrop = 5, string background = "", string designName = "RoadPro") 26 { 27 Dynamicweb.Frontend.PageView currentPageview = Dynamicweb.Frontend.PageView.Current(); 28 string currDevice = currentPageview.Device.ToString(); 29 string alternativeImage = !String.IsNullOrEmpty(currentPageview.Area.Item["NoImage"].ToString()) ? currentPageview.Area.Item["NoImage"].ToString() : "/Files/Templates/Designs/"+ designName + "/images/alternativeImage.jpg"; 30 string widthString = ""; 31 string heightString = ""; 32 string getImageFormat = imageFormat != "jpg" ? "&Format=" + imageFormat : ""; 33 string getImageCompression = imageCompression != 0 ? "&Compression=" + imageCompression : ""; 34 string bgColor = !string.IsNullOrEmpty(background) ? "&Background="+background : ""; 35 int getImageWidth = imageWidth != 0 ? imageWidth : 0; 36 int getImageHeight = imageHeight != 0 ? imageHeight : 0; 37 38 if (currDevice == Dynamicweb.Frontend.Devices.DeviceType.Tablet.ToString()) 39 { 40 getImageWidth = imageWidthTablet != 0 ? imageWidthTablet : getImageWidth; 41 getImageHeight = imageHeightTablet != 0 ? imageHeightTablet : getImageHeight; 42 } 43 else if (currDevice == Dynamicweb.Frontend.Devices.DeviceType.Mobile.ToString()) 44 { 45 getImageWidth = imageWidthMobile != 0 ? imageWidthMobile : getImageWidth; 46 getImageHeight = imageHeightMobile != 0 ? imageHeightMobile : getImageHeight; 47 } 48 49 if (getImageWidth != 0) 50 { 51 widthString = "&Width=" + getImageWidth; 52 } 53 if (getImageHeight != 0) 54 { 55 heightString = "&Height=" + getImageHeight; 56 } 57 58 string output = "/Admin/Public/GetImage.ashx?Image=" + sourceString + widthString + heightString + "&altFmImage_path=" + alternativeImage + getImageFormat + getImageCompression + "&Crop=" + imageCrop + bgColor; 59 return output; 60 } 61 } 62 @inherits RazorTemplateBase<RazorTemplateModel<Template>> 63 @using Dynamicweb.Rendering; 64 65 @functions{ 66 private string GetImagePathUrl(string small, string medium, string large, string pattern) 67 { 68 string imagePath; 69 70 if (!string.IsNullOrEmpty(small)) 71 imagePath = small; 72 else if (!string.IsNullOrEmpty(medium)) 73 imagePath = medium; 74 else if (!string.IsNullOrEmpty(large)) 75 imagePath = large; 76 else 77 imagePath = pattern; 78 79 return imagePath; 80 } 81 } 82 @functions{ 83 public string GetCurrentUrl() 84 { 85 string currentUrl = Pageview.GlobalTags.GetTagByName("Global:Request.Scheme").Value.ToString() + "://" + Pageview.GlobalTags.GetTagByName("Global:Request.Host").Value.ToString() + Pageview.GlobalTags.GetTagByName("Global:Pageview.Url").Value.ToString(); 86 87 return currentUrl; 88 } 89 } 90 @{ 91 // General API 92 Dynamicweb.Content.Items.Item areaItem = Pageview.Area.Item; 93 bool isLoggedIn = Dynamicweb.Security.UserManagement.User.IsExtranetUserLoggedIn(); 94 bool isFrontEnd = Dynamicweb.Environment.ExecutingContext.IsFrontEnd(); 95 string currentPageId = Pageview.Page.ID.ToString(); 96 // ---- 97 string titleKey = "title"; 98 string title = ""; 99 string imageKey = "image"; 100 string image = ""; 101 string document = ""; 102 string documentKey = "document"; 103 //Product 104 bool showQuantity = (areaItem["ShowQuantityField"] ?? "").ToString() == "True" ? true : false; 105 bool productIsFavorite = GetBoolean("Ecom:Product.IsProductInFavoriteList"); 106 bool isGiftCard = GetInteger("Ecom:Product.Type") == 3; 107 string variantDefaultId = GetString("Ecom:Product.DefaultVariantComboID"); 108 string variantCurrentId = GetString("Ecom:Product.VariantID"); 109 string variantId = (!string.IsNullOrEmpty(variantCurrentId)) ? variantCurrentId : variantDefaultId; 110 string stockStatus = GetInteger("Ecom:Product.Stock") > 0 ? "fa-check" : "fa-close"; 111 string productId = GetString("Ecom:Product.ID"); 112 string productLanguage = GetString("Ecom:Product.LanguageID"); 113 string productName = GetString("Ecom:Product.Name"); 114 string productNumber = GetString("Ecom:Product.Number"); 115 string productIntro = GetString("Ecom:Product.ShortDescription"); 116 string productDescription = GetString("Ecom:Product.LongDescription"); 117 string pointPrice = GetString("Ecom:Product.PointPrice"); 118 string productDetails = GetString("Ecom:Product:Field.Features.Value.Clean"); 119 string productWarranty = GetString("Ecom:Product:Field.Warranty.Value.Clean"); 120 string productPrice = GetString("Ecom:Product.Price"); 121 string brand = GetString("Ecom:Product:Field.Brand"); 122 string productLink = GetString("Ecom:Product.Link.Clean"); 123 int productStock = GetInteger("Ecom:Product.AvailableAmount"); 124 bool newProduct = GetBoolean("Ecom:Product:Field.New"); 125 //Image 126 string imagePatternName = productNumber.Replace("/", "_"); 127 string pattern = imagePatternName + ".*"; 128 string pattern2 = imagePatternName + "_*"; 129 string productImage = GetImagePathUrl(GetString("Ecom:Product.ImageSmall.Clean"), GetString("Ecom:Product.ImageMedium.Clean"), GetString("Ecom:Product.ImageLarge.Clean"), pattern); 130 string productGetImage = GetImage(productImage, 350, 350); 131 string imagesFolder = "/Files/Files/"+designName+"/Products/"; 132 string imagePattern = imagesFolder + imagePatternName + ".jpg"; 133 List<Dictionary<string, string>> imagesList = new List<Dictionary<string, string>>(); 134 List<Dictionary<string, string>> documentsList = new List<Dictionary<string, string>>(); 135 string folderPath = Path.GetDirectoryName(HttpContext.Current.Server.MapPath("/Files/Files/" + designName+"/Products/" + imagePatternName + ".jpg")); 136 string warrantyFolderPath = Path.GetDirectoryName(HttpContext.Current.Server.MapPath("/Files/Files/" + designName+"/Documents/")); 137 // Favorites 138 string productRemoveFromList = "/Default.aspx?Id="+currentPageId+ "&ProductID=" + productId +"&CCRemoveFromMyLists="+productId+"&CCRemoveFromListVariantID="+variantId+"&CCRemoveFromListLanguageID="+productLanguage; 139 string productAddToList = "/Default.aspx?Id="+currentPageId+ "&ProductID=" + productId +"&CCAddToMyLists="+productId+"&CCAddToListVariantID="+variantId+"&CCAddToListLanguageID="+productLanguage; 140 string favoriteUrl = productIsFavorite ? productRemoveFromList : productAddToList; 141 // Downloads 142 string downloadsFilter = "Products contains 'p_"+productId+",' or Products contains 'p_"+productId+":' or Products ends with 'p_"+productId+"'"; 143 // Reviews 144 string subject = (areaItem["Subject"] ?? Translate("newReview","New review")).ToString(); 145 string senderName = (areaItem["SenderName"] ?? (areaItem["CompanyName"] ?? "").ToString()).ToString(); 146 string senderEmail = (areaItem["SenderEmail"] ?? (areaItem["Email"] ?? "").ToString()).ToString(); 147 string notifyEmail = (areaItem["NotifyEmail"] ?? (areaItem["Email"] ?? "").ToString()).ToString(); 148 Dictionary<string, string> iconFiles = new Dictionary<string, string>(); 149 iconFiles.Add("pdf", "fa-file-pdf-o"); 150 iconFiles.Add("jpg", "fa-picture-o"); 151 iconFiles.Add("png", "fa-picture-o"); 152 iconFiles.Add("zip", "fa-file-archive-o"); 153 iconFiles.Add("rar", "fa-file-archive-o"); 154 // Loops 155 List<LoopItem> loopVariantCombinations = GetLoop("VariantCombinations"); 156 List<LoopItem> loopVariantGroups = GetLoop("VariantGroups"); 157 List<LoopItem> loopProdPrices = GetLoop("Product.Prices"); 158 List<LoopItem> loopDetails = GetLoop("Details"); 159 160 string currentDomain = Pageview.GlobalTags.GetTagByName("Global:Request.Scheme").Value.ToString() + "://" + Pageview.GlobalTags.GetTagByName("Global:Request.Host").Value.ToString(); 161 162 string findStore = areaItem["FindAStore"].ToString(); 163 164 // Get Images from folder 165 if (Directory.Exists(folderPath)) 166 { 167 string temp = @"\"; 168 foreach (string file in Directory.GetFiles(folderPath, pattern).Concat(Directory.GetFiles(folderPath, pattern2))) 169 { 170 Dictionary<string, string> dct_image = new Dictionary<string, string>(); 171 image = "/Files/Files/"+designName+"/Products/" + file.Substring((file.LastIndexOf(@temp) + 1), (file.Length - file.LastIndexOf(@temp) - 1)); 172 string metafield = "title"; 173 var metadata = Dynamicweb.Content.Files.Metadata.EditorFactory.GetMetadataForFile(image); 174 title = metadata != null ? metadata.GetValue(metafield).ToString() : productName; 175 dct_image.Add(titleKey, title); 176 dct_image.Add(imageKey, image); 177 imagesList.Add(dct_image); 178 } 179 } 180 181 // Get Warranty from folder 182 if (Directory.Exists(warrantyFolderPath)) 183 { 184 string temp = @"\"; 185 string brandDocName = brand.Replace(" ", "00000"); 186 brandDocName = string.Concat(brandDocName.Where(char.IsLetterOrDigit)).Replace("00000", " "); 187 string[] brandsParts = brandDocName.Split(' '); 188 189 foreach (string file in Directory.GetFiles(warrantyFolderPath, "*.pdf")) 190 { 191 Dictionary<string, string> dct_file = new Dictionary<string, string>(); 192 string fileName = file.Substring((file.LastIndexOf(@temp) + 1), (file.Length - file.LastIndexOf(@temp) - 1)); 193 bool hasFile = brandsParts.Any(x => fileName.Contains(x) && !string.IsNullOrEmpty(x)); 194 195 if (hasFile) 196 { 197 document = "/Files/Files/" + designName + "/Documents/" + fileName; 198 string metafield = "title"; 199 var metadata = Dynamicweb.Content.Files.Metadata.EditorFactory.GetMetadataForFile(document); 200 title = metadata != null ? metadata.GetValue(metafield).ToString() : fileName; 201 dct_file.Add(titleKey, title); 202 dct_file.Add(documentKey, document); 203 documentsList.Add(dct_file); 204 } 205 } 206 207 } 208 } 209 @using System; 210 @using System.Collections.Generic; 211 @using System.Web.Script.Serialization; 212 @{ 213 Dictionary<string, Dictionary<string, Dictionary<string, string>>> product = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>(); 214 Dictionary<string, Dictionary<string, string>> variants = new Dictionary<string, Dictionary<string, string>>(); 215 string productJSON = ""; 216 217 if(loopVariantCombinations.Count > 0){ 218 foreach (LoopItem variant in loopVariantCombinations){ 219 string variantHref = "/"+ variant.GetString("Ecom:VariantCombination.Link.Clean") + "?PID=" + Dynamicweb.Frontend.PageView.Current().CurrentParagraph.ID.ToString(), 220 productNumberVariant = variant.GetString("Ecom:Product.Number"), 221 price = variant.GetString("Ecom:Product.Price"), 222 stock = variant.GetString("Ecom:Product.AvailableAmount"), 223 smallImage = variant.GetString("Ecom:Product.ImageSmall.Clean"), 224 id = variant.GetString("Ecom:VariantCombination.VariantID"), 225 variantName = variant.GetString("Ecom:VariantCombination.VariantText"), 226 variantShortDescription = variant.GetString("Ecom:VariantCombination.VariantText"); 227 Dictionary<string, string> variantDict = new Dictionary<string, string>(); 228 229 variantDict.Add("name", variantName); 230 variantDict.Add("id", id); 231 variantDict.Add("number", productNumberVariant); 232 variantDict.Add("price", price); 233 variantDict.Add("stock", stock); 234 variantDict.Add("smallImage", smallImage); 235 variantDict.Add("productIsFavorite", variant.GetString("Ecom:Product.IsProductInFavoriteList")); 236 variantDict.Add("addToList", variant.GetString("Ecom:Product.AddToFavorites")); 237 variantDict.Add("removeFromList", variant.GetString("Ecom:Product.RemoveFromFavorites")); 238 239 variants.Add(id, variantDict); 240 } 241 product.Add("product", variants); 242 243 } 244 productJSON = new JavaScriptSerializer().Serialize(product); 245 246 } 247 248 249 <div id="product-container" data-amountrequired='@Translate("amountIsRequired","Amount is required.")' data-pageId="@currentPageId" data-productId="@productId" data-variantId="@variantId" data-errorCombination1='@Translate("combinationNotAvailable","Combination not available")' > 250 <article id="product-description" class="col-xs-12 noPadding"> 251 <div id="product-images" class="col-sm-6 col-xs-12 noPadding"> 252 <div id="product-lg-image" class="col-xs-12 noPaddingLeft"> 253 <figure class="text-center"> 254 <img class="img-responsive" src="@productGetImage" alt="@productName" title="@productName" /> 255 <div class="hidden" id="videoContainer"> 256 <a id="playPause" href="#"><i class="fa fa-play"></i></a> 257 <video id="video" width="100%" src=""> 258 Your browser does not support the video tag. 259 </video> 260 </div> 261 </figure> 262 </div> 263 264 <div id="imgThumbs" class="col-xs-12"> 265 <ul> 266 @foreach (Dictionary<String, String> imageStr in imagesList) 267 { 268 bool isAnImage = imageStr["image"].Contains(".jpg"); 269 string getimageImg = GetImage(imageStr["image"], 0, 150); 270 string getimageDataImgLarge = isAnImage ? GetImage(imageStr["image"], 800, 800) : imageStr["image"].ToString(); 271 string getimageDataImg = isAnImage ? GetImage(imageStr["image"], 600, 600) : imageStr["image"].ToString(); 272 string liClass = imagesList.IndexOf(imageStr) == 0 ? "active" : ""; 273 274 try 275 { 276 string replaced = imageStr["image"].Substring(imageStr["image"].LastIndexOf('/') + 1).Replace(productNumber, "").Replace(".jpg", "").Replace(".mp4", ""); 277 278 <li data-type='@replaced' class="@liClass"> 279 @if (isAnImage) 280 { 281 <img data-large="@getimageDataImgLarge" data-image="@getimageDataImg" class="img-responsive" src="@getimageImg" title="@imageStr["title"]" alt="@imageStr["title"]"/> 282 } 283 else 284 { 285 <video data-image="@getimageDataImg" width="100%" src="@getimageDataImg">Your browser does not support the video tag.</video> 286 <i class="fa fa-play-circle-o videoPlayIcon"></i> 287 } 288 </li> 289 } 290 catch (Exception e) 291 { 292 // e.Message 293 } 294 295 } 296 </ul> 297 </div> 298 299 </div> 300 <div id="product-info-wrapper" class="col-sm-6 col-xs-12"> 301 <p>@brand</p> 302 <h2 class="product-title padding-bottom">@productName</h2> 303 <div class="col-xs-12 noPadding productDetail"> 304 @if (!string.IsNullOrEmpty(productIntro)) 305 { 306 <div class="col-xs-12 noPadding productIntroduction">@productIntro</div> 307 } 308 @if (!string.IsNullOrEmpty(productNumber)) 309 { 310 <span>@Translate("item", "Item #"):</span> 311 @productNumber 312 } 313 </div> 314 315 <div class="col-xs-12 noPadding details"> 316 <p>@Translate("features","Features")</p> 317 @productDetails 318 </div> 319 320 <div class="col-xs-12 noPadding findStore"> 321 @{ 322 string brandFilter = brand.Replace(" ", "00000"); 323 brandFilter = string.Concat(brandFilter.Where(char.IsLetterOrDigit)).Replace("00000", " "); 324 325 findStore = findStore + "&brand=" + brandFilter; 326 327 } 328 <a class="btn-primary" href="@findStore">@Translate("findStore", "Find a Store*")</a> 329 <p>@Translate("doesNotGuaranteeInventory", "*Does not guarantee inventory")</p> 330 </div> 331 332 <div class="col-xs-12 noPadding"> 333 <div class="shareIcons"> 334 <span>@Translate("share", "Share:")</span> 335 <ul id="socialMedia"> 336 @foreach (string socialId in (areaItem["SocialNetworks"] ?? "").ToString().Split(',')) 337 { 338 Item item = ItemManager.Storage.GetById("SocialLinks", socialId); 339 string domain = "https://" + System.Web.HttpContext.Current.Request.Url.Host; 340 if (item != null && !string.IsNullOrEmpty((item["ShareURL"] ?? "").ToString())) 341 { 342 string socialName = item["Name"].ToString(); 343 string socialImage = item["Icon"].ToString(); 344 string socialLink = item["ShareURL"].ToString() + domain + HttpContext.Current.Request.RawUrl; 345 346 //START CUSTOM CODE 347 if (socialName == "TikTok") 348 { 349 var iconLink = "/Files" + socialImage; 350 <li> 351 <a title="@socialName" class="fa" target="_blank" href="@socialLink"> 352 <div style="background-color: white;mask: url('@iconLink') no-repeat center / contain; -webkit-mask: url('@iconLink') no-repeat center / contain; width:30px;height: 18.5px;"></div> 353 </a> 354 </li> 355 } 356 else 357 { 358 <li><a title="@socialName" class="@socialImage fa" target="_blank" href="@socialLink"></a></li> 359 } 360 //END CUSTOM CODE 361 } 362 } 363 </ul> 364 </div> 365 </div> 366 367 @*@if(!isGiftCard) 368 { 369 <div class="product-price inlineBlock"> 370 @productPrice 371 </div> 372 } 373 <!-- Quantity prices --> 374 @if(loopProdPrices.Any() && showQuantity){ 375 <div id="pricesContainer" class="col-xs-12 noPadding"> 376 <h2> 377 @Translate("quantityPrices", "Quantity prices") 378 </h2> 379 380 <div id="quantityContainer" class="col-xs-12 noPadding"> 381 <ul> 382 @foreach(LoopItem price in loopProdPrices) { 383 int quantity = price.GetInteger("Ecom:Product.Prices.Quantity"); 384 string priceProd = price.GetString("Ecom:Product.Prices.PriceWithoutVATFormatted"); 385 386 <li> 387 <span class="col-xs-6">@Translate("qty", "Qty") > @quantity</span> 388 <b class="col-xs-6 text-right">(@priceProd)</b> 389 </li> 390 } 391 </ul> 392 </div> 393 394 </div> 395 }*@ 396 397 @*<div class="order-now"> 398 <form name="addToCart" class="add-to-cart form-fields" action="@Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl((areaItem["MiniCart"] ?? "").ToString())" method="post" data-outofstock='@Translate("outOfStock", "Out of stock")'> 399 <input type="hidden" name="cartcmd" value="add"/> 400 <input type="hidden" name="redirect" value="false"/> 401 <input type="hidden" name="productID" value="@productId"/> 402 <input type="hidden" name="variantID" id="variantID" value="@variantId" @((string.IsNullOrEmpty(variantId)) ? "disabled='disabled'":"") /> 403 404 @if(loopVariantGroups.Any()){ 405 <div id="variantsContainer" class="col-xs-12 noPadding"> 406 @foreach(LoopItem variantGroup in loopVariantGroups){ 407 string variantGroupName = variantGroup.GetString("Ecom:VariantGroup.Name"); 408 string variantGroupId = variantGroup.GetString("Ecom:VariantGroup.ID"); 409 List<LoopItem> loopAvailableOptions = variantGroup.GetLoop("VariantAvailableOptions"); 410 411 if(loopAvailableOptions.Any()){ 412 <fieldset class="col-sm-6 col-xs-12 noPadding"> 413 <label class="text-left" for="@variantGroupId">@variantGroupName</label> 414 <select class="full-width-input" name="@(variantGroupId)_options" id="@variantGroupId"> 415 @foreach(LoopItem option in loopAvailableOptions){ 416 string optionId = option.GetString("Ecom:VariantOption.ID"); 417 string optionName = option.GetString("Ecom:VariantOption.Name"); 418 bool optionSelected = option.GetBoolean("Ecom:VariantOption.Selected"); 419 420 <option value="@optionId" @((optionSelected) ? "selected":"") >@optionName</option> 421 } 422 </select> 423 </fieldset> 424 } 425 } 426 </div> 427 } 428 429 @if(!isGiftCard) 430 { 431 <div id="stockStatus" class="col-xs-12 noPadding"><i class="fa @stockStatus"></i> @Translate("stock", "Stock")</div> 432 } 433 @if(pointPrice != "0") { 434 <div id="prodLoyaltyPoints" class="col-xs-12 noPadding"><i class="fa fa-gift"></i> @Translate("buyNowFor", "Buy now for") @pointPrice @Translate("loyaltyPoints", "loyalty points")</div> 435 } 436 437 <div class="col-xs-12 grayBox"> 438 <div class="highlight-content text-right"> 439 @if (showQuantity) 440 { 441 <fieldset class="quantity-container pull-left"> 442 <label for="quantity">@Translate("quantity", "Quantity")</label> 443 <input data-outofstock='@Translate("outOfStock", "Out of stock")' data-stocktranslate='@Translate("currentStock", "The current stock is")' class="hidden quantity quantityInput" data-stock='@GetString("Ecom:Product.Stock")' maxlength="5" id="quantity" name="quantity" type="number" value="1"/> 444 445 <select data-width="25%" name="quantitySelect"> 446 447 @if (loopVariantGroups.Any()) 448 { 449 for (int num = 1; (num < 10); num++) 450 { 451 <option value="@num">@num</option> 452 } 453 } 454 else 455 { 456 for (int num = 1; (num < 10) && num <= productStock; num++) 457 { 458 <option value="@num">@num</option> 459 } 460 } 461 462 @if (productStock >= 10 || loopVariantGroups.Any()) 463 { 464 <option value="10+">10+</option> 465 } 466 467 </select> 468 469 </fieldset> 470 } 471 else 472 { 473 <input data-outofstock='@Translate("outOfStock", "Out of stock")' data-stocktranslate='@Translate("currentStock", "The current stock is")' class="hidden quantity quantityInput" data-stock='@GetString("Ecom:Product.Stock")' maxlength="5" id="quantity" name="quantity" type="number" value="1"/> 474 } 475 476 477 @if( isGiftCard ) 478 { 479 <fieldset class="pull-left giftCardAmount"> 480 <label class="hidden" for="Amount">@Translate("amount", "Amount")</label> 481 <span>@GetString("Ecom:Product.Price.Currency.Symbol")</span> 482 <input placeholder="@Translate("amount")" type="number" name="Amount" step="0.01" min="0.01" value="@GetString("Ecom:Product.Price.Price")" /> 483 </fieldset> 484 } 485 486 <a class="btn btn-bg" id="addToCartSubmit"> 487 <i class="fa fa-shopping-cart"></i> <span data-add='@Translate("addToCart", "Add to cart")' data-added='@Translate("added", "Added")'>@Translate("addToCart", "Add to Cart")</span> 488 </a> 489 @if(GetBoolean("Ecom:Product.CanBuyForPoints")) { 490 <a class="btn btn-bg" id="addToCartPointsSubmit"> 491 <i class="fa fa-shopping-cart"></i> <span data-add='@Translate("addWithPoints", "Add with points")' data-added='@Translate("added", "Added")'>@Translate("addWithPoints", "Add with points")</span> 492 </a> 493 } 494 </div> 495 </div> 496 <div class="col-xs-12 noPadding"> 497 @if(isLoggedIn && isFrontEnd){ 498 string icon = productIsFavorite ? "fa-heart" : "fa-heart-o" ; 499 <p> 500 <a class="btn-gold-outline" data-favorite="@productIsFavorite" id="favorite" data-user="@Dynamicweb.Security.UserManagement.User.IsExtranetUserLoggedIn()" data-addText='@Translate("addToWishlist","Add to Wish list")' data-removeText='@Translate("removeFromWishlist","Remove from Wish list")' href="@favoriteUrl"><i class="fa @icon"></i> @Translate(productIsFavorite ? "removeFromWishlist" : "addToWishlist")</a> 501 </p> 502 } 503 504 @if(!string.IsNullOrEmpty(productDetails)){ 505 <div id="longDescription"> 506 <b class="lead">@Translate("details", "Details")</b> 507 @productDetails 508 </div> 509 } 510 @{ 511 string socialMedia = (areaItem["SocialNetworks"] ?? "").ToString(); 512 513 if(!string.IsNullOrEmpty(socialMedia)){ 514 <div class="shareIcons"> 515 <span>@Translate("share", "Share")</span> 516 <ul> 517 @foreach (var socialID in socialMedia.Split(',')) 518 { 519 var item = Dynamicweb.Content.Items.ItemManager.Storage.GetById("SocialLinks", socialID); 520 if (item["ShareURL"] != null && !string.IsNullOrEmpty(item["ShareURL"].ToString())) 521 { 522 string socialLink = (item["ShareURL"] ?? "").ToString(); 523 string socialName = (item["Name"] ?? "").ToString(); 524 string className = (item["Icon"] ?? "").ToString() ; 525 526 <li> 527 <a class="fa @className" target="_blank" href="@socialLink@GetCurrentUrl()"><span>@socialName</span></a> 528 </li> 529 } 530 531 } 532 </ul> 533 </div> 534 } 535 } 536 </div> 537 <input class="hidden" type="submit" value='@Translate("addToCart", "Add to Cart")' /> 538 </form> 539 </div>*@ 540 </div> 541 542 @* TABS / Long description / Product custom field(example) / Downloads (items) *@ 543 <div id="tabsContainer" class="col-xs-12 noPadding"> 544 <ul class="col-xs-12 noPadding"> 545 @if(!string.IsNullOrEmpty(productDescription)){ 546 <li class="active"> 547 <a href="#description_tab">@Translate("description", "Description")</a> 548 </li> 549 } 550 @if(documentsList.Any()){ 551 <li> 552 <a href="#warraty_tab">@Translate("warranty", "Warranty")</a> 553 </li> 554 } 555 @RenderSnippet("downloadItem") 556 @if(loopDetails.Any()) { 557 <li> 558 <a href="#productDdownloads_tab">@Translate("downloads", "Downloads") (product)</a> 559 </li> 560 } 561 </ul> 562 563 @if(!string.IsNullOrEmpty(productDescription)){ 564 <div class="active col-xs-12" id="description_tab">@productDescription</div> 565 } 566 @if (documentsList.Any()) 567 { 568 <div class="col-xs-12" id="warraty_tab"> 569 <ul> 570 @foreach (Dictionary<String, String> doc in documentsList) 571 { 572 <li> 573 <a class="downloadFile" href="@doc["document"]"><i class='fa fa-file-pdf-o'></i> @doc["title"]</a> 574 </li> 575 } 576 </ul> 577 </div> 578 } 579 580 @if(areaItem["ProductDownloads"] != null && !string.IsNullOrWhiteSpace(areaItem["ProductDownloads"].ToString())) 581 { 582 RenderItemList(new 583 { 584 ItemType = "ProductDownloads", 585 ListSourceType = "Page", 586 ListSourcePage = Pageview.Area.Item["ProductDownloads"], 587 ItemFieldsList = "*", 588 ListTemplate = "ItemPublisher/List/ProductDownloads.cshtml", 589 ListPageSize = 99, 590 IncludeParagraphItems = true, 591 Filter = downloadsFilter 592 }); 593 } 594 @if(loopDetails.Any()) { 595 <div class="col-xs-12" id="productDdownloads_tab"> 596 <ul> 597 598 @foreach (LoopItem detail in loopDetails){ 599 string file = detail.GetString("Ecom:Product:Detail.Image.Clean"); 600 var metadata = Dynamicweb.Content.Files.Metadata.EditorFactory.GetMetadataForFile(file); 601 string temp = @".", 602 metafield = "title", 603 fileTitle = metadata != null ? metadata.GetValue(metafield).ToString() : Translate("download", "Download"), 604 substringFile = file.Substring((file.LastIndexOf(temp) + 1), (file.Length - file.LastIndexOf(temp) - 1)), 605 icon = iconFiles.ContainsKey(substringFile) ? iconFiles[substringFile] : "fa-file-pdf-o" ; 606 607 <li> 608 <a class="downloadFile" href="@file"><i class='fa @icon'></i> @fileTitle</a> 609 </li> 610 } 611 </ul> 612 </div> 613 } 614 </div> 615 616 </article> 617 618 @* Related Products *@ 619 @if(GetLoop("ProductRelatedGroups").Any()){ 620 <div class="col-xs-12 noPadding" id="relatedContainer"> 621 @foreach (LoopItem group in GetLoop("ProductRelatedGroups")){ 622 List<LoopItem> relatedProducts = group.GetLoop("RelatedProducts"); 623 624 if(relatedProducts.Any()){ 625 <div class="col-xs-12 noPadding relatedContainer"> 626 <h2 class="productTitles">@group.GetString("Ecom:Product:RelatedGroup.Name")</h2> 627 628 <ul class="relatedList row"> 629 @foreach (LoopItem productItem in relatedProducts.Take(4)) 630 { 631 string relatedProductName = productItem.GetString("Ecom:Product.Name"); 632 string relatedProductNumber = productItem.GetString("Ecom:Product.Number"); 633 string relatedProductLink = productItem.GetString("Ecom:Product.PrimaryOrCurrentPageID") != Pageview.Page.ID.ToString() ? "/Default.aspx?ID=" + productItem.GetString("Ecom:Product.PrimaryOrCurrentPageID") + "&ProductID=" + productItem.GetString("Ecom:Product.ID") : "/Default.aspx?ID=" + Pageview.Page.ID.ToString() + "&ProductID=" + productItem.GetString("Ecom:Product.ID"); 634 string relatedImage = (!string.IsNullOrEmpty(productItem.GetString("Ecom:Product.ImageSmall.Clean"))) ? productItem.GetString("Ecom:Product.ImageSmall.Clean") : "/Files/Files/"+designName+"/Products/Images/" + relatedProductNumber + ".jpg"; 635 636 <li class="col-md-3 col-sm-6 col-xs-12"> 637 <figure class="col-xs-12 noPadding"> 638 <a href="@relatedProductLink"> 639 <img src="@GetImage(relatedImage, 400, 0, 0, 0, 0, 0, "jpg")" alt="@relatedProductName" title="@relatedProductName" class="img-responsive" /> 640 </a> 641 </figure> 642 <div class="col-xs-12 noPadding"> 643 @*<div class="relatedProdRatingContainer"> 644 @Rating(productItem.GetDouble("Ecom:Product.Rating")) 645 </div>*@ 646 <h3 class=" h2 col-xs-12 noPadding text-center"><a href="@relatedProductLink">@relatedProductName</a> 647 </h3> 648 @*<span class="listPrice" itemprop="price">@productItem.GetString("Ecom:Product.Price")</span>*@ 649 </div> 650 </li> 651 } 652 </ul> 653 </div> 654 } 655 } 656 </div> 657 } 658 659 @* Reviews *@ 660 @*<div class="col-xs-12 noPadding" id="reviewsContainer"> 661 <h2 class="productTitles">@Translate("reviews", "Reviews")</h2> 662 <div id="reviewWithSuccess" class="hidden"> 663 <b>@Translate("Review submited successfully!")</b><br/> 664 @Translate("Your review needs to be activated to be displayed at the website") 665 </div> 666 @{ 667 var comments = GetLoop("Comments.Newfirst"); 668 string langId = GetString("Ecom:Product.LanguageID"); 669 string pageViewUrl = string.Format("{0}#reviewsContainer", GetGlobalValue("Global:Pageview.Url")); 670 string accessUserName = GetGlobalValue("Global:Extranet.Name"); 671 string accessUserEmail = GetGlobalValue("Global:Extranet.Email"); 672 673 if (comments.Any()) 674 { 675 <ul id="productReviews" class="col-xs-12 noPadding"> 676 @foreach (LoopItem comment in comments) 677 { 678 DateTime dat_date = comment.GetDate("CreatedDate"); 679 string dateAndName = string.Format("{0} {1}, {2}, {3}", dat_date.ToString("MMM"), dat_date.Day.ToString(), dat_date.Year.ToString(), comment.GetString("Name")); 680 string email = comment.GetString("Email"); 681 string website = comment.GetString("Website"); 682 683 <li id="comment@(comment.GetString("ID"))" class="col-xs-12 noPadding"> 684 <div class="col-xs-12 col-sm-4 noPaddingLeft"> 685 @Rating(comment.GetDouble("Rating")) 686 <span class="dateAndName">@dateAndName</span> 687 <span class="email"><a href="mailto:@email">@email</a></span> 688 @if(!string.IsNullOrWhiteSpace(website)) 689 { 690 <span class="website"><a href="@website">@website.Replace("http://", "").Replace("https://", "")</a></span> 691 } 692 </div> 693 <div class="col-xs-12 col-sm-8 noPaddingRight"> 694 @comment.GetString("Text") 695 </div> 696 </li> 697 } 698 </ul> 699 } 700 701 <div class="col-xs-12 noPadding" id="reviewFormContainer"> 702 <h2>@Translate("addYourReview", "Add your review")</h2> 703 <form class="DMForms col-xs-12 noPadding" method="post" action="/Default.aspx?ID=@currentPageId" id="commentform"> 704 <input type="hidden" name="_sys_to_email" value="bot@dynamicweb.com"> 705 <input type="hidden" name="Comment.Command" id="Comment.Command" value="create"/> 706 <input type="hidden" name="Comment.Active" value="false"/> 707 <input type="hidden" name="Comment.ItemType" value="ecomProduct"/> 708 <input type="hidden" name="Comment.ItemID" value="@productId"/> 709 <input type="hidden" name="Comment.LangID" value="@langId"/> 710 <input type="hidden" name="Comment.Continue" value="@pageViewUrl"/> 711 <input type="hidden" name="Comment.ParentID" id="Comment.ParentID" value="0"/> 712 713 $1$ Notify #1# 714 <input type="hidden" name="Comment.Notify" value="true"/> 715 <input type="hidden" name="Comment.NotifyTemplate" value="Comments/Notify.cshtml"/> 716 <input type="hidden" name="Comment.NotifySubject" id="Comment.NotifySubject" value="@subject"/> 717 <input type="hidden" name="Comment.NotifySenderEmail" value="@senderEmail"/> 718 <input type="hidden" name="Comment.NotifySenderName" value="@senderName"/> 719 <input type="hidden" name="Comment.NotifyEmail" value="@notifyEmail"/> 720 721 <fieldset> 722 <label>@Translate("Rating")</label> 723 <ul id="commentRating"> 724 <li><input type="radio" name="Comment.Rating" value="5"/><i class="fa fa-star"></i></li> 725 <li><input type="radio" name="Comment.Rating" value="4"/><i class="fa fa-star"></i></li> 726 <li><input type="radio" name="Comment.Rating" value="3"/><i class="fa fa-star"></i></li> 727 <li><input type="radio" name="Comment.Rating" value="2"/><i class="fa fa-star"></i></li> 728 <li><input type="radio" name="Comment.Rating" value="1"/><i class="fa fa-star"></i></li> 729 </ul> 730 </fieldset> 731 <fieldset class="TextInput mandatory"> 732 <label for="Comment.Name">@Translate("name", "Name")</label> 733 <input type="text" name="Comment.Name" id="Comment.Name" value="@accessUserName"/> 734 </fieldset> 735 <fieldset class="TextInput"> 736 <label for="Comment.Email">@Translate("email", "E-mail")</label> 737 <input type="text" name="Comment.Email" id="Comment.Email" value="@accessUserEmail"/> 738 <span class="inputNote">@Translate("addYourEmailToBeNotifiedWhenYourReviewIsApproved", "Add your email to be notified when your review is approved.")</span> 739 </fieldset> 740 <fieldset class="Textarea mandatory"> 741 <label for="Comment.Text">@Translate("comment", "Comment")</label> 742 <textarea name="Comment.Text" id="Comment.Text" rows="10" cols="50"></textarea> 743 </fieldset> 744 745 <input class="btn btn-bg" type="submit" value="@(Translate("submit", "Submit"))"/> 746 </form> 747 </div> 748 749 } 750 </div>*@ 751 </div> 752 753 @SnippetStart("OGMeta") 754 <meta property="og:title" content='@productName' /> 755 <meta property="og:image" content='@Pageview.GlobalTags.GetTagByName("Global:Request.Scheme").Value.ToString()://@Pageview.GlobalTags.GetTagByName("Global:Request.Host").Value.ToString()@imagePattern' /> 756 <meta property="og:site_name" content='@areaItem["CompanyName"]' /> 757 <meta property="og:url" content='@Pageview.GlobalTags.GetTagByName("Global:Request.Scheme").Value.ToString()://@Pageview.GlobalTags.GetTagByName("Global:Request.Host").Value.ToString()@Pageview.GlobalTags.GetTagByName("Global:Pageview.Url").Value.ToString()' /> 758 <meta property="og:description" content='@StripHtml(productIntro)' /> 759 <meta property="og:type" content="product" /> 760 <meta property="og:locale" content='@Pageview.GlobalTags.GetTagByName("Global:Area.LongLang").Value.ToString().Replace("-", "_")' /> 761 @SnippetEnd("OGMeta") 762 763 @SnippetStart("jsOnLoad") 764 onLoadProductDetail({obj_product:@productJSON}); 765 @SnippetEnd("jsOnLoad") 766 767 @functions { 768 public static string StripHtml(string source) 769 { 770 return Regex.Replace(source, "<.*?>", string.Empty); 771 } 772 } 773 @helper Rating(double rating) 774 { 775 string starClass = string.Empty; 776 string halfStar = string.Empty; 777 778 <ul class="rating"> 779 @for(int s=5;s>0;s--){ 780 if(s == Math.Ceiling(rating)){ 781 starClass = "class='star'"; 782 halfStar = !(rating - Math.Round(rating) == 0) ? "fa-star-half-o" : "fa-star" ; 783 }else{ 784 starClass = ""; 785 halfStar = "fa-star"; 786 } 787 788 <li data-star="@s" @starClass><i class="fa @halfStar"></i></li> 789 } 790 </ul> 791 }