Objektiver til foto og video

Hos Goecker finder du objektiver til både foto og video fra blandt andre Canon, Sony, Nikon, Fujifilm, Leica, Sigma, Tamron og Panasonic. Vælg mellem faste objektiver, zoomobjektiver, vidvinkel, tele, makro og meget mere til en lang række kamerafatninger og systemer.

Brug kategorierne og filtrene til at finde et objektiv, der passer til dit kamera og dit behov.

Sammenlign produkter

Vælg op til 3 produkter, som du ønsker at sammenligne

Fjern alle produkter

Fjern

Sortering

Error executing template "/Designs/Swift/Paragraph/Swift_ProductListGridView_Custom.cshtml"
System.Exception: Error Running ExecuteReader: Transaction (Process ID 68) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction., Sql: "SELECT
	                    -- Object columns
	                    O.DefinitionKey
	                    ,O.LastModified AS OjectLastModified
	                    ,O.ObjectId
	                    ,O.XmlObjectId
	                    ,O.ShopId
	                    ,O.LanguageId
	                    -- Value columns
	                    ,V.LastModified AS ValueLastModified
	                    ,V.XmlReferenceObjectId
	                    ,V.XmlReferenceObjectKey
	                    ,V.ValueId
	                    ,V.[Text]
                        ,V.FieldKey
                        ,V.SortOrder
                    FROM [LWI_Spec_Objects] AS O
                    JOIN [LWI_Spec_Values] AS V ON
	                    V.ShopId = O.ShopId
	                    AND V.LanguageId = O.LanguageId
	                    AND V.XmlObjectKey = O.DefinitionKey
	                    AND V.XmlObjectId = O.XmlObjectId
                    WHERE
                        O.DefinitionKey IN ('Product')
                        AND O.XmlObjectId IN ('70673')
                        AND O.ShopId IN ('SHOP1')
                        AND O.LanguageId IN ('LANG1')
                    ORDER BY O.DefinitionKey, O.LanguageId, O.ShopId, O.XmlObjectId
                    ", Params: '' ---> System.Data.SqlClient.SqlException: Transaction (Process ID 68) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
   at System.Data.SqlClient.SqlDataReader.get_MetaData()
   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
   at Glimpse.Ado.AlternateType.GlimpseDbCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at NLWI.Platforms.Dynamicweb9.Database.ADatabaseRepository.ExecuteReader(Int32 timeout, String query, Object[] ps)
   --- End of inner exception stack trace ---
   at NLWI.Platforms.Dynamicweb9.Database.ADatabaseRepository.ExecuteReader(Int32 timeout, String query, Object[] ps)
   at NLWI.Platforms.Dynamicweb9.Database.ADatabaseRepository.ExecuteReader(String query, Object[] ps)
   at NLWI.Platforms.Dynamicweb9.Specs.Repositories.SpecificationRepository.GetSpecificationObjects(HashSet`1 keys)
   at NLWI.Platforms.Dynamicweb9.Specs.Services.CachedSpecificationService.<GetSpecificationObjects>b__12_1(HashSet`1 k)
   at NLWI.Core.Platform.Caching.DictionaryCaching.GetOrInsert[TKey,TVal](HashSet`1 keys, Func`2 buildCacheKey, Func`2 lookupMethod, CacheOptions cacheOptions)
   at NLWI.Platforms.Dynamicweb9.Specs.Services.CachedSpecificationService.GetSpecificationObjects(HashSet`1 specificationObjectIdentifiers)
   at NLWI.Platforms.Dynamicweb9.Specs.Services.CachedProductSpecificationService.GetProductSpecifications(Dictionary`2 autoIdMappings)
   at NLWI.Platforms.Dynamicweb9.Specs.Services.CachedProductSpecificationService.GetProductSpecifications(HashSet`1 productAutoIds)
   at NLWI.Platforms.Dynamicweb9.Specs.Services.CachedProductSpecificationService.GetProductSpecifications(Int64 productAutoId)
   at CompiledRazorTemplates.Dynamic.RazorEngine_7b2c4b1a16504c9e951757b9eeb35aa6.<RenderProductList>b__10_0(TextWriter __razor_helper_writer) in C:\inetpub\solutions\Goecker-2022-Prod\Files\Templates\Designs\Swift\Paragraph\Swift_ProductListGridView_Custom.cshtml:line 298
   at CompiledRazorTemplates.Dynamic.RazorEngine_7b2c4b1a16504c9e951757b9eeb35aa6.Execute() in C:\inetpub\solutions\Goecker-2022-Prod\Files\Templates\Designs\Swift\Paragraph\Swift_ProductListGridView_Custom.cshtml:line 196
   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.Ecommerce.CustomerExperienceCenter.Favorites 4 @using System.Linq 5 @using Dynamicweb.Core 6 @using Dynamicweb.Environment 7 @using NLWI.Core.Factory 8 @using NLWI.Platforms.Dynamicweb9.Specs.ViewModels 9 @using NLWI.Platforms.Dynamicweb9.Specs.Services 10 @using NORRIQ.CustomCode.Razor 11 @using NORRIQ.CustomCode.StockLocations 12 @using System.Text; 13 @using System.Web; 14 @using Dynamicweb; 15 @using Dynamicweb.Core.Encoders 16 @using System.Globalization 17 18 @* CUSTOMIZED STANDARD SWIFT (v1.15.0) TEMPLATE *@ 19 20 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 21 22 @helper RenderAddedModal(bool isRental = false) 23 { 24 string productsFeedUrl = $"/Default.aspx?ID={GetPageIdByNavigationTag("productsfeed")}&feed=true&redirect=false"; 25 string checkoutUrl = isRental ? $"/Default.aspx?ID={GetPageIdByNavigationTag("rentalcheckout")}" : $"/Default.aspx?ID={GetPageIdByNavigationTag("checkout")}"; 26 string cartUrl = "/Default.aspx?ID=" + (GetPageIdByNavigationTag("CartService")); 27 if (!cartUrl.Contains("LayoutTemplate")) 28 { 29 cartUrl += cartUrl.Contains("?") ? "&LayoutTemplate=Swift_MiniCart.cshtml" : "?LayoutTemplate=Swift_MiniCart.cshtml"; 30 } 31 32 <div class="modal fade product-added-modal js-product-added-modal" data-productsfeedurl="@productsFeedUrl" tabindex="-1" role="dialog"> 33 <input type="hidden" class="js-translation choose" value="@HttpUtility.HtmlEncode(Translate("Smartpage.Product.AddedModal.Choose", "Vælg"))" /> 34 <input type="hidden" class="js-translation period-price" value="@HttpUtility.HtmlAttributeEncode(Translate("Smartpage:Rental.PeriodPrice", "Pris for periode:"))" /> 35 <input type="hidden" class="js-translation daily-price" value="@HttpUtility.HtmlAttributeEncode(Translate("Smartpage:Rental.DailyPrice", "Dagspris:"))" /> 36 37 <div class="modal-dialog" role="document"> 38 <div class="modal-content"> 39 <div class="modal-header"> 40 <div class="d-flex flex-column"> 41 <h3 class="modal-title">@Translate("Smartpage.Product.AddedModal.Header", "Tilføjet til kurv")</h3> 42 @if (isRental) 43 { 44 <p> 45 @Translate("Smartpage.Rental.PeriodDays", "Skydedage") 46 <span class="js-rental-periodfrom"></span> - <span class="js-rental-periodto"></span> 47 </p> 48 } 49 </div> 50 <div class="cross-icon cursor-pointer" onclick="hideModal(this)"></div> 51 </div> 52 <div class="spinner-border js-loader powerstep-loader text-dark d-none"> 53 <span class="visually-hidden">Loading..</span> 54 </div> 55 <div class="modal-body container pt-2 pb-0 px-3 m-0 text-center text-lg-start"> 56 <div class="js-product-modal-orderline row gap-2 gap-lg-0 d-flex flex-column flex-lg-row justify-content-between pb-2 border-bottom"> 57 <div class="col-lg-6 col-12 d-flex align-items-center flex-column flex-lg-row gap-3 gap-lg-0"> 58 <img class="js-product-modal-orderline-image mr-2" /> 59 <a class="js-product-modal-orderline-name text-decoration-none fw-bold px-md-3 px-lg-0"> 60 </a> 61 </div> 62 <div class="col-lg-6 col-12 d-flex flex-column align-items-center align-items-lg-end justify-content-center"> 63 @if (!isRental) 64 { 65 <div class="d-flex mr-2"> 66 <span class="js-product-modal-orderline-price"></span> 67 </div> 68 } 69 else 70 { 71 <div class="d-flex mr-2"> 72 <span class="me-2">@Translate("Smartpage:Rental.DailyPrice", "Dagspris:")</span> <span class="js-product-modal-orderline-dailyprice"></span> 73 </div> 74 <div class="d-flex"> 75 <span class="me-2">@Translate("Smartpage:Rental.PeriodPrice", "Pris for periode:")</span> <span class="js-product-modal-orderline-periodprice"></span> 76 </div> 77 } 78 </div> 79 </div> 80 <div class="row border-bottom"> 81 <h5 class="fw-bold py-3 fs-sm-7 fs-md-6">@Translate("Smartpage.Product.AddedModal.Recommendation", "Til ovenstående produkt anbefaler vi:")</h5> 82 </div> 83 <div class="js-product-modal-relatedproducts d-flex flex-column"></div> 84 </div> 85 86 <div class="modal-footer border-top-0 justify-content-end"> 87 @if (!isRental) 88 { 89 <form method="post" action="@cartUrl" class="js-relatedproducts-form"> 90 <input type="hidden" name="cartcmd" value="addmulti" /> 91 <input type="hidden" name="redirect" value="false" /> 92 93 <div class="js-products-inputs"></div> 94 95 <button class="btn btn-primary js-add-to-cart-button disabled" onclick="swift.Cart.Update(event)">@Translate("Tilføj til kurv")</button> 96 </form> 97 } 98 else 99 { 100 <form class="js-relatedproducts-form"> 101 <div class="js-products-inputs"></div> 102 <button class="btn btn-primary js-add-to-rental disabled" onclick="addRelatedRentalProducts(event, this)">@Translate("Tilføj til kurv")</button> 103 </form> 104 } 105 </div> 106 <div class="modal-footer justify-content-between"> 107 <button type="button" class="btn btn-primary" onclick="hideModal(this)">@Translate("Smartpage.Product.AddedModal.BackToShop", "Tilbage til shop")</button> 108 <a href="@checkoutUrl" class="btn btn-primary">@Translate("Smartpage.Product.AddedModal.Checkout", "Til checkout")</a> 109 </div> 110 </div> 111 </div> 112 </div> 113 } 114 @using NLWI.Platforms.Dynamicweb9.Specs.ViewModels 115 116 @functions { 117 string GetProductImage(ProductSpecifications specs) 118 { 119 string imageUrl = "/Files/Images/Perfion/default.png"; 120 121 if (specs.HasKey("Primærbillede")) 122 { 123 imageUrl = specs.GetByKey("Primærbillede").Value; 124 } 125 126 return imageUrl; 127 } 128 129 Dictionary<string, string> GetAllProductImages(ProductSpecifications specs) 130 { 131 Dictionary<string, string> images = new Dictionary<string, string>(); 132 133 foreach (var img in specs.GetByGroup("Billeder")) 134 { 135 if (!images.ContainsKey(img.Value) && img.Key != "Brandlogo") 136 { 137 images.Add(img.Value, img.Caption); 138 } 139 } 140 141 return images; 142 } 143 } 144 145 @functions 146 { 147 bool isLazyLoadingForProductInfoEnabled = Dynamicweb.Ecommerce.DynamicwebLiveIntegration.TemplatesHelper.IsLazyLoadingForProductInfoEnabled; 148 string liveInfoClass = ""; 149 string productInfoFeed = ""; 150 151 string showPricesWithVat = ""; 152 bool neverShowVat = false; 153 154 bool isDetailPage = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("ProductID")); 155 156 ProductListViewModel productList = new ProductListViewModel(); 157 } 158 159 @{ 160 if (Dynamicweb.Context.Current.Items.Contains("ProductList")) 161 { 162 productList = (ProductListViewModel)Dynamicweb.Context.Current.Items["ProductList"]; 163 } 164 165 showPricesWithVat = HttpContext.Current.Session["Smartpage:ShowPricesWithVat"] != null ? Convert.ToString(HttpContext.Current.Session["Smartpage:ShowPricesWithVat"]) : Pageview.Area.EcomPricesWithVat.ToLower(); 166 neverShowVat = string.IsNullOrEmpty(showPricesWithVat); 167 168 if (isLazyLoadingForProductInfoEnabled) 169 { 170 if (Dynamicweb.Context.Current.Items.Contains("ProductInfoFeed")) 171 { 172 productInfoFeed = Dynamicweb.Context.Current.Items["ProductInfoFeed"]?.ToString(); 173 if (!string.IsNullOrEmpty(productInfoFeed)) 174 { 175 productInfoFeed = $"data-product-info-feed=\"{productInfoFeed}\""; 176 } 177 } 178 liveInfoClass = "js-live-info"; 179 } 180 181 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 182 string themePadding = theme != string.Empty ? "p-3" : string.Empty; 183 } 184 185 @if (!isDetailPage) 186 { 187 if (!string.IsNullOrEmpty(theme)) 188 { 189 <div class="h-100@(theme) @themePadding item_@Model.Item.SystemName.ToLower()" @productInfoFeed> 190 @RenderProductList() 191 </div> 192 } 193 else 194 { 195 <div class="pt-3 item_@Model.Item.SystemName.ToLower()" @productInfoFeed> 196 @RenderProductList() 197 </div> 198 } 199 } 200 201 @helper RenderProductList() 202 { 203 var productSpecificationService = ObjectFactory.GetInstance<IProductSpecificationService>(); 204 var stockService = ObjectFactory.GetInstance<StockService>(); 205 var featurePostFix = Pageview.AreaSettings.GetItem("CustomSettings").GetRawValueString("FeaturePostFix_Custom", ""); 206 207 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 208 bool anonymousUser = Pageview.User == null; 209 bool hidePrice = anonymousUsersLimitations.Contains("price") && anonymousUser || Pageview.AreaSettings.GetBoolean("ErpDownHidePrices") && !Dynamicweb.Ecommerce.DynamicwebLiveIntegration.TemplatesHelper.IsWebServiceConnectionAvailable(); 210 211 string productTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ProductTheme")) ? " theme " + Model.Item.GetRawValueString("ProductTheme").Replace(" ", "").Trim().ToLower() : ""; 212 string productThemePadding = productTheme != string.Empty ? "p-3" : string.Empty; 213 214 string url = Dynamicweb.Context.Current.Request.RawUrl; 215 bool hideFavoritesSelector = !string.IsNullOrEmpty(Model.Item.GetString("HideFavoritesSelector")) ? Model.Item.GetBoolean("HideFavoritesSelector") : false; 216 bool showFavoritesSelectorMasterProduct = !string.IsNullOrEmpty(Model.Item.GetString("ShowFavoritesSelectorMasterProduct")) ? Model.Item.GetBoolean("ShowFavoritesSelectorMasterProduct") : false; 217 string staticVariantsLayout = Model.Item.GetRawValueString("StaticVariantsLayout", "hide"); 218 219 string groupId = productList?.Group?.Id != null ? productList.Group.Id : ""; 220 221 string cartUrl = "/Default.aspx?ID=" + (GetPageIdByNavigationTag("CartService")); 222 if (!cartUrl.Contains("LayoutTemplate")) 223 { 224 cartUrl += cartUrl.Contains("?") ? "&LayoutTemplate=Swift_MiniCart.cshtml" : "?LayoutTemplate=Swift_MiniCart.cshtml"; 225 } 226 227 var badgeParms = new Dictionary<string, object>(); 228 badgeParms.Add("saleBadgeType", Model.Item.GetRawValue("SaleBadgeType")); 229 badgeParms.Add("saleBadgeCssClassName", Model.Item.GetRawValue("SaleBadgeDesign")); 230 badgeParms.Add("newBadgeCssClassName", Model.Item.GetRawValue("NewBadgeDesign")); 231 badgeParms.Add("newPublicationDays", Model.Item.GetInt32("NewPublicationDays")); 232 badgeParms.Add("campaignBadgesValues", Model.Item.GetRawValueString("CampaignBadges")); 233 234 bool saleBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("SaleBadgeDesign")) && Model.Item.GetRawValueString("SaleBadgeDesign") != "none" ? true : false; 235 bool newBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("NewBadgeDesign")) && Model.Item.GetRawValueString("NewBadgeDesign") != "none" ? true : false; 236 237 string googleAnalyticsTrackingID = Pageview.AreaSettings.GetString("GoogleAnalyticsTrackingID"); 238 string googleAnalyticsMeasurementID = Pageview.AreaSettings.GetString("GoogleAnalyticsMeasurementID"); 239 var cookieOptInLevel = CookieManager.GetCookieOptInLevel(); 240 bool allowTracking = cookieOptInLevel == CookieOptInLevel.All || (cookieOptInLevel == CookieOptInLevel.Functional && CookieManager.GetCookieOptInCategories().Contains("Statistical")); 241 242 var favoriteParameters = new Dictionary<string, object>(); 243 if (!anonymousUser && !hideFavoritesSelector) 244 { 245 int defaultFavoriteListId = 0; 246 247 IEnumerable<FavoriteList> favoreiteLists = Pageview.User.GetFavoriteLists(); 248 if (favoreiteLists.Count() == 1) 249 { 250 foreach (FavoriteList list in favoreiteLists) 251 { 252 defaultFavoriteListId = list.ListId; 253 } 254 } 255 256 favoriteParameters.Add("ListId", defaultFavoriteListId); 257 } 258 259 if (productList.TotalProductsCount > 0) 260 { 261 int pageSizeSetting = 30; 262 int pageSize = productList.PageSize; 263 pageSize += pageSizeSetting; 264 265 int loadedProducts = productList.PageSize > productList.TotalProductsCount ? productList.TotalProductsCount : productList.PageSize; 266 267 <div class="grid grid-2 grid-lg-3"> 268 @* 269 20250512: Removed by AE 270 @RenderAddedModal(false) 271 *@ 272 273 <script> 274 window.addEventListener('CookieInformationConsentGiven', function (event) { 275 if (CookieInformation.getConsentGivenFor('cookie_cat_statistic')) { 276 gtag("event", "view_item_list", { 277 item_list_id: "product_list_gridview", 278 item_list_name: "Product list (Gridview)", 279 items: [ 280 @foreach (ProductViewModel product in productList.Products) 281 { 282 <text>{ 283 item_id: "@product.Number", 284 item_name: "@product.Name", 285 currency: "@product.Price.CurrencyCode", 286 price: @product.Price.Price 287 },</text> 288 } 289 ] 290 }); 291 } 292 }, false); 293 </script> 294 295 296 @foreach (ProductViewModel product in productList.Products) 297 { 298 var specs = product.GetSpecifications(); 299 var availableStockLocations = product.StockUnits.Where(a => a.StockLevel > 0).Select(a => a.StockLocationName).ToList(); 300 var inStock = availableStockLocations.Any(); 301 302 string variantIdForLink = !string.IsNullOrEmpty(product.VariantId) ? $"&VariantID={product.VariantId}" : ""; 303 variantIdForLink = string.IsNullOrEmpty(variantIdForLink) && !string.IsNullOrEmpty(product.DefaultVariantId) ? $"&VariantID={product.DefaultVariantId}" : variantIdForLink; 304 305 string link = "Default.aspx?ID=" + GetPageIdByNavigationTag("Shop"); 306 link += $"&GroupID={product.PrimaryOrDefaultGroup.Id}"; 307 link += $"&ProductID={product.Id}"; 308 link += variantIdForLink; 309 link = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(link); 310 311 string imagePath = product?.DefaultImage?.Value ?? ""; 312 imagePath = Dynamicweb.Context.Current.Server.UrlEncode(imagePath); 313 314 string ratio = Model.Item.GetRawValueString("ImageAspectRatio", ""); 315 ratio = ratio != "0" ? ratio : ""; 316 string ratioCssClass = ratio != "" ? " ratio" : ""; 317 string ratioVariable = ratio != "" ? "--bs-aspect-ratio: " + ratio : ""; 318 319 string imagePathXs = "/Admin/Public/GetImage.ashx?width=" + 480 + "&image=" + imagePath + "&format=webp"; 320 string imagePathS = "/Admin/Public/GetImage.ashx?width=" + 640 + "&image=" + imagePath + "&format=webp"; 321 string imagePathFallBack = "/Admin/Public/GetImage.ashx?width=" + 640 + "&image=" + imagePath + "&format=webp"; 322 323 string imageTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ImageTheme")) ? " theme " + Model.Item.GetRawValueString("ImageTheme").Replace(" ", "").Trim().ToLower() : ""; 324 string imageThemePadding = imageTheme != string.Empty ? "p-3" : string.Empty; 325 string imageOutlineStyle = imageTheme == string.Empty ? "style=\"border: 1px solid transparent\"" : string.Empty; 326 327 string imageId = "ProductImage_" + product.Id + product.VariantId; 328 string priceId = "ProductPrice_" + product.Id + product.VariantId; 329 330 @* Alternative image *@ 331 var supportedImageFormats = new string[] { ".jpg", ".webp", ".png", ".gif" }; 332 string defaultImage = product.DefaultImage != null ? product.DefaultImage.Value : ""; 333 var selectedAssetCategories = Model.Item.GetRawValueString("AlternativeImageAssets"); 334 IEnumerable<MediaViewModel> alternativeImagesList = product.AssetCategories.Where(x => selectedAssetCategories.Contains(x.SystemName)).SelectMany(x => x.Assets); 335 336 if (alternativeImagesList.FirstOrDefault() != null) 337 { 338 alternativeImagesList = alternativeImagesList.OrderByDescending(x => x.Value.Equals(defaultImage)); 339 340 if (alternativeImagesList.First().Value == defaultImage) 341 { 342 alternativeImagesList = alternativeImagesList.Skip(1); 343 } 344 } 345 346 string alternativeImage = alternativeImagesList.FirstOrDefault() != null ? alternativeImagesList.FirstOrDefault().Value : ""; 347 alternativeImage = !string.IsNullOrEmpty(alternativeImage) ? "/Admin/Public/GetImage.ashx?width=" + 640 + "&image=" + alternativeImage + "&format=webp" : ""; 348 349 @* Badges *@ 350 DateTime createdDate = product.Created.Value; 351 bool showBadges = saleBadgeEnabled && product.Discount.Price != 0 ? true : false; 352 showBadges = (newBadgeEnabled && Model.Item.GetInt32("NewPublicationDays") == 0) || (newBadgeEnabled && (createdDate.AddDays(Model.Item.GetInt32("NewPublicationDays")) > DateTime.Now)) ? true : showBadges; 353 showBadges = !string.IsNullOrEmpty(Model.Item.GetRawValueString("CampaignBadges")) ? true : showBadges; 354 355 @* Main features *@ 356 IEnumerable<string> selectedDisplayGroups = Model.Item.GetRawValueString("MainFeatures").Split(',').ToList(); 357 List<CategoryFieldViewModel> mainFeatures = new List<CategoryFieldViewModel>(); 358 359 foreach (var selection in selectedDisplayGroups) 360 { 361 foreach (CategoryFieldViewModel group in product.FieldDisplayGroups.Values) 362 { 363 if (selection == group.Id) 364 { 365 mainFeatures.Add(group); 366 } 367 } 368 } 369 370 //CUSTOM 371 var disablePrice = product.ProductFields.ContainsKey("Custom_DisablePrice") ? Convert.ToBoolean(product.ProductFields["Custom_DisablePrice"].Value) : false; 372 var disablePurchase = product.ProductFields.ContainsKey("Custom_DisablePurchase") ? Convert.ToBoolean(product.ProductFields["Custom_DisablePurchase"].Value) : false; 373 var disableStock = product.ProductFields.ContainsKey("Custom_DisableStock") ? Convert.ToBoolean(product.ProductFields["Custom_DisableStock"].Value) : false; 374 var enableContact = product.ProductFields.ContainsKey("Custom_EnableContact") ? Convert.ToBoolean(product.ProductFields["Custom_EnableContact"].Value) : false; 375 var enableBookDemo = product.ProductFields.ContainsKey("Custom_EnableBookDemo") ? Convert.ToBoolean(product.ProductFields["Custom_EnableBookDemo"].Value) : false; 376 377 var productDiscountInfo = Custom.Discounts.Services.DiscountInfoService.GetDiscountExtenderInfoByProductId(product.Id)?.Where(x => !string.IsNullOrEmpty(x.CampaignLabel)); 378 //--CUSTOM 379 380 <article class="position-relative@(productTheme) product-list-item js-product @liveInfoClass" data-product-id="@product.Id" itemscope itemtype="https://schema.org/Product"> 381 382 @if (specs.HasKey("Ikon" + featurePostFix) 383 || (productDiscountInfo != null && productDiscountInfo.Any())) 384 { 385 <div class="product-label"> 386 @foreach (var label in specs.GetAllByKey("Ikon" + featurePostFix)) 387 { 388 var referenceSpecfication = label.GetReferenceSpecification(); 389 var txtcolor = "#ffffff"; 390 if (!string.IsNullOrEmpty(referenceSpecfication.GetByKey("LinkFarvekode").Value)) 391 { 392 txtcolor = referenceSpecfication.GetByKey("LinkFarvekode").Value; 393 } 394 if (referenceSpecfication.HasKey("LinkURL")) 395 { 396 <a href="@(referenceSpecfication.GetByKey("LinkURL").Value)" class="product-label-item" style="background-color:@(referenceSpecfication.GetByKey("Farvekode").Value);color:@txtcolor;"> 397 @referenceSpecfication.GetByKey("Label").Value 398 </a> 399 } 400 else 401 { 402 <span class="product-label-item" style="background-color:@(referenceSpecfication.GetByKey("Farvekode").Value);color:@txtcolor;"> 403 @referenceSpecfication.GetByKey("Label").Value 404 </span> 405 } 406 } 407 408 @*CUSTOM*@ 409 @if (productDiscountInfo != null) 410 { 411 foreach (var discount in productDiscountInfo) 412 { 413 <span class="product-label-item" style="background-color: @discount.CampaignLabelColor; color: @(!string.IsNullOrEmpty(discount.CampaignLabelTextColor) ? discount.CampaignLabelTextColor : "#ffffff");"> 414 @discount.CampaignLabel 415 </span> 416 } 417 } 418 @*CUSTOM*@ 419 420 </div> 421 } 422 423 @if (!anonymousUser) 424 { 425 if (!hideFavoritesSelector && product.VariantInfo.VariantInfo == null) 426 { 427 <div class="position-absolute top-0 end-0 my-3" style="z-index: 2"> 428 @RenderPartial("Components/ToggleFavorite.cshtml", product, favoriteParameters) 429 </div> 430 } 431 else if (showFavoritesSelectorMasterProduct) 432 { 433 <div class="position-absolute top-0 end-0 my-3" style="z-index: 2"> 434 @RenderPartial("Components/ToggleFavorite.cshtml", product, favoriteParameters) 435 </div> 436 } 437 } 438 439 @if (showBadges) 440 { 441 <div class="position-absolute top-0 left-0 p-1 p-lg-2 ps-0 ps-lg-0" style="z-index: 2"> 442 @RenderPartial("Components/EcommerceBadge.cshtml", product, badgeParms) 443 </div> 444 } 445 446 <div class="d-flex flex-column d-block h-100 text-center"> 447 @{ 448 string clickProductLink = string.Empty; 449 if (allowTracking) 450 { 451 clickProductLink = "onclick=\"return clickProductLink('" + @product.Id + "', '" + @product.Name + "', '" + @product.VariantName + "', '" + @product.Price.CurrencyCode + "', '" + @product.Price.Price + "')\""; 452 } 453 } 454 <a href="@link" class="text-decoration-none d-flex flex-column" @clickProductLink> 455 @if (allowTracking) 456 { 457 <script> 458 function clickProductLink(productId, productName, productVariant, productCurrency, productPrice) { 459 if (typeof gtag !== "undefined") { 460 gtag("event", "select_item", { 461 item_list_id: "product_list_gridview", 462 item_list_name: "Product list (Gridview)", 463 items: [ 464 { 465 item_id: productId, 466 item_name: productName, 467 currency: productCurrency, 468 item_list_id: "product_list_gridview", 469 item_list_name: "Product list (Gridview)", 470 item_variant: productVariant, 471 price: productPrice 472 } 473 ] 474 }); 475 } 476 } 477 </script> 478 } 479 480 <div class="@productThemePadding order-2"> 481 <div class="flex-grow-1"> 482 <h3 class="h6 mb-0 text-break" itemprop="name"> 483 @product.Name @if (!string.IsNullOrEmpty(product.VariantName)) 484 {<text>(@product.VariantName)</text>} 485 </h3> 486 @if (!Model.Item.GetBoolean("HideProductNumber")) 487 { 488 <p class="fs-7 opacity-85 mb-2">@product.Number</p> 489 } 490 @if (mainFeatures.Count > 0) 491 { 492 <ul class="p-0 lh-sm opacity-75" style="list-style-position: inside"> 493 @foreach (CategoryFieldViewModel mainFeatureGroup in mainFeatures) 494 { 495 foreach (var field in mainFeatureGroup.Fields) 496 { 497 @RenderField(field.Value) 498 } 499 } 500 </ul> 501 } 502 </div> 503 </div> 504 505 <div class="overflow-hidden order-1 @(imageTheme)" @imageOutlineStyle> 506 <div class="ratio" style="@(ratioVariable)"> 507 <div class="d-flex justify-content-center align-items-center"> 508 @if (string.IsNullOrEmpty(alternativeImage)) 509 { 510 <img id="@imageId" itemprop="image" 511 srcset=" 512 @imagePathXs 480w, 513 @imagePathS 640w" 514 sizes="(min-width: 992px) 33vw, 50vw" 515 src="@imagePathFallBack" 516 loading="lazy" 517 decoding="async" 518 class="mw-100 mh-100 @imageThemePadding" 519 alt="@product.Name"> 520 } 521 else 522 { 523 <img id="@imageId" itemprop="image" 524 src="@imagePathFallBack" 525 loading="lazy" 526 decoding="async" 527 class="mw-100 mh-100 @imageThemePadding" 528 alt="@product.Name" 529 onmouseover="this.src='@alternativeImage'" 530 onmouseout="this.src='@imagePathFallBack'"> 531 } 532 </div> 533 </div> 534 535 @if (product.VariantInfo.VariantInfo != null && staticVariantsLayout == "images") 536 { 537 int variantGroupCount = 0; 538 int showMaxVariantGroups = 2; 539 int showMaxVariants = 3; 540 var productVariantTheme = productTheme != "" ? productTheme : "bg-white"; 541 542 <div class="position-relative"> 543 <div id="StaticVariants_@product.Id" class="static-variants w-100 d-none d-lg-block position-absolute left-0 bottom-0 @productTheme" style="pointer-events: none;"> 544 545 @foreach (var variantGroup in product.VariantGroups()) 546 { 547 int variantsCount = 0; 548 549 <div class="d-flex gap-2 mb-2"> 550 @foreach (var variant in variantGroup.Options) 551 { 552 if (variantGroupCount < showMaxVariantGroups) 553 { 554 var optionsCount = variantGroup.Options.Count(); 555 556 if (variantsCount < showMaxVariants) 557 { 558 string optionWidth = !string.IsNullOrEmpty(variant.Color) ? "w-25" : ""; 559 560 <article class="static-variants-option @optionWidth @(productVariantTheme)" title="@product.Name @variant.Name" style="pointer-events: initial;"> 561 @if (!string.IsNullOrEmpty(variant.Color)) 562 { 563 string defaultProductImage = Dynamicweb.Context.Current.Server.UrlEncode(product.DefaultImage.Value); 564 string variantImage = Dynamicweb.Context.Current.Server.UrlEncode(variant.Image.Value); 565 string defaultPrice = !hidePrice ? product.Price.PriceFormatted : "0"; 566 string variantPrice = !hidePrice ? product.Price.PriceFormatted : "0"; 567 568 if (isLazyLoadingForProductInfoEnabled) 569 { 570 <figure class="w-100 d-block m-0" data-price-formatted="" onmouseover="swift.StaticVariants.SwitchProduct(event, '@product.Id', this.getAttribute('data-price-formatted'), '@variantImage')" onmouseout="swift.StaticVariants.SwitchProduct(event, '@product.Id', this.getAttribute('data-price-formatted'), '@defaultProductImage')"> 571 <div class="d-flex align-items-center justify-content-center"> 572 <img src="/admin/public/GetImage.ashx?image=@variantImage&width=75&height=75&crop=5&FillCanvas=true&format=webp&Quality=70" height="75" width="75" class="p-1 text-small" loading="lazy" decoding="async" alt="@product.Name, @variant.Name"> 573 </div> 574 </figure> 575 } 576 else 577 { 578 <figure class="w-100 d-block m-0" onmouseover="swift.StaticVariants.SwitchProduct(event, '@product.Id', '@defaultPrice', '@variantImage')" onmouseout="swift.StaticVariants.SwitchProduct(event, '@product.Id', '@variantPrice', '@defaultProductImage')"> 579 <div class="d-flex align-items-center justify-content-center"> 580 <img src="/admin/public/GetImage.ashx?image=@variantImage&width=75&height=75&crop=5&FillCanvas=true&format=webp&Quality=70" height="75" width="75" class="p-1 text-small" loading="lazy" decoding="async" alt="@product.Name, @variant.Name"> 581 </div> 582 </figure> 583 } 584 } 585 else 586 { 587 <div class="d-flex align-items-center justify-content-center"> 588 @variant.Name 589 </div> 590 } 591 <div class="visually-hidden"> 592 <h4>@product.Name, @variant.Name</h4> 593 @if (!hidePrice) 594 { 595 if (isLazyLoadingForProductInfoEnabled) 596 { 597 <span class="text-price js-text-price"></span> 598 } 599 else 600 { 601 <span class="text-price">@product.Price.PriceFormatted</span> 602 } 603 } 604 </div> 605 </article> 606 } 607 608 variantsCount++; 609 610 if (variantsCount == showMaxVariants && optionsCount != showMaxVariants) 611 { 612 int left = optionsCount - showMaxVariants; 613 <div class="variant-option ms-1 d-flex justify-content-center align-items-center"> 614 <span>+@left</span> 615 </div> 616 } 617 } 618 } 619 </div> 620 621 variantGroupCount++; 622 } 623 </div> 624 </div> 625 } 626 </div> 627 </a> 628 <div class="@productThemePadding mt-auto pt-0"> 629 630 @if (!disableStock) //CUSTOM 631 { 632 <div> 633 @if (inStock && availableStockLocations.Any()) 634 { 635 <span class="icon-stock icon-green position-relative" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="@HttpUtility.HtmlAttributeEncode(string.Join("<br />", availableStockLocations))" data-bs-html="true">@Translate("label_in_Stock", "På lager")</span> 636 } 637 else 638 { 639 <span class="icon-stock icon-red position-relative">@Translate("label_not_in_stock", "Ikke på lager")</span> 640 } 641 </div> 642 643 <script> 644 window.addEventListener('DOMContentLoaded', function () { 645 var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')) 646 var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) { 647 return new bootstrap.Tooltip(tooltipTriggerEl) 648 }) 649 }, false); 650 </script> 651 } 652 653 @if (!hidePrice && !disablePrice) //CUSTOM 654 { 655 string priceMin = ""; 656 string priceMax = ""; 657 658 <div class="mt-2"> 659 <div itemprop="offers" itemscope itemtype="https://schema.org/Offer"> 660 <span itemprop="priceCurrency" content="@product.Price.CurrencyCode" class="d-none"></span> 661 662 @if (showPricesWithVat == "false" && !neverShowVat) 663 { 664 if (isLazyLoadingForProductInfoEnabled) 665 { 666 <span itemprop="price" content="" class="d-none"></span> 667 <span class="text-decoration-line-through js-text-decoration-line-through opacity-75 me-3 text-price js-text-price d-none" data-show-if="LiveProductInfo.product.Price.Price != LiveProductInfo.product.PriceBeforeDiscount.Price"></span> 668 } 669 else 670 { 671 string beforePrice = product.PriceBeforeDiscount.PriceWithoutVatFormatted; 672 string informativePrice = product.PriceInformative.PriceWithoutVatFormatted; 673 674 <span itemprop="price" content="@product.Price.PriceWithoutVat.ToString("0.00", CultureInfo.InvariantCulture)" class="d-none"></span> 675 if (product.Price.Price != product.PriceBeforeDiscount.Price) 676 { 677 <span class="text-decoration-line-through opacity-75 me-3 text-price">@beforePrice</span> 678 } 679 else if (product.PriceInformative.Price > 0) 680 { 681 <span class="text-decoration-line-through opacity-75 me-3 text-price">@informativePrice</span> 682 } 683 } 684 } 685 else 686 { 687 if (isLazyLoadingForProductInfoEnabled) 688 { 689 <span itemprop="price" content="" class="d-none"></span> 690 <span class="text-decoration-line-through js-text-decoration-line-through opacity-75 me-3 text-price js-text-price d-none" data-show-if="LiveProductInfo.product.Price.Price != LiveProductInfo.product.PriceBeforeDiscount.Price"></span> 691 } 692 else 693 { 694 string beforePrice = product.PriceBeforeDiscount.PriceFormatted; 695 string informativePrice = product.PriceInformative.PriceWithVatFormatted; 696 697 <span itemprop="price" content="@product.Price.Price.ToString("0.00", CultureInfo.InvariantCulture)" class="d-none"></span> 698 if (product.Price.Price != product.PriceBeforeDiscount.Price) 699 { 700 <span class="text-decoration-line-through opacity-75 me-3 text-price">@beforePrice</span> 701 } 702 else if (product.PriceInformative.Price > 0) 703 { 704 <span class="text-decoration-line-through opacity-75 me-3 text-price">@informativePrice</span> 705 } 706 } 707 } 708 709 @if (showPricesWithVat == "false" && !neverShowVat) 710 { 711 if (isLazyLoadingForProductInfoEnabled) 712 { 713 <span class="text-price js-text-price"><div class="spinner-border" role="status"></div></span> 714 } 715 else 716 { 717 string price = product.Price.PriceWithoutVatFormatted; 718 if (product?.VariantInfo?.VariantInfo != null) 719 { 720 priceMin = product?.VariantInfo?.PriceMin?.PriceWithoutVatFormatted != null ? product.VariantInfo.PriceMin.PriceWithoutVatFormatted : ""; 721 priceMax = product?.VariantInfo?.PriceMax?.PriceWithoutVatFormatted != null ? product.VariantInfo.PriceMax.PriceWithoutVatFormatted : ""; 722 } 723 if (priceMin != priceMax) 724 { 725 price = priceMin + " - " + priceMax; 726 } 727 <span class="text-price">@price</span> 728 } 729 } 730 else 731 { 732 if (isLazyLoadingForProductInfoEnabled) 733 { 734 <span class="text-price js-text-price"><div class="spinner-border" role="status"></div></span> 735 } 736 else 737 { 738 string price = product.Price.PriceFormatted; 739 if (product?.VariantInfo?.VariantInfo != null) 740 { 741 priceMin = product?.VariantInfo?.PriceMin?.PriceFormatted != null ? product.VariantInfo.PriceMin.PriceFormatted : ""; 742 priceMax = product?.VariantInfo?.PriceMax?.PriceFormatted != null ? product.VariantInfo.PriceMax.PriceFormatted : ""; 743 } 744 if (priceMin != priceMax) 745 { 746 price = priceMin + " - " + priceMax; 747 } 748 <span class="text-price">@price</span> 749 } 750 } 751 </div> 752 @if (showPricesWithVat == "false" && !neverShowVat) 753 { 754 if (isLazyLoadingForProductInfoEnabled) 755 { 756 <div class="fs-7 opacity-85 text-price js-text-price-with-vat d-none" data-suffix="@Translate("Incl. VAT")"></div> 757 } 758 else 759 { 760 string price = product.Price.PriceWithVatFormatted; 761 if (product?.VariantInfo?.VariantInfo != null) 762 { 763 priceMin = product?.VariantInfo?.PriceMin?.PriceWithVatFormatted != null ? product.VariantInfo.PriceMin.PriceWithVatFormatted : ""; 764 priceMax = product?.VariantInfo?.PriceMax?.PriceWithVatFormatted != null ? product.VariantInfo.PriceMax.PriceWithVatFormatted : ""; 765 } 766 if (priceMin != priceMax) 767 { 768 price = priceMin + " - " + priceMax; 769 } 770 <div class="fs-7 opacity-85 text-price">@price @Translate("Incl. VAT")</div> 771 } 772 } 773 </div> 774 } 775 776 <div class="icon-compare mt-2 d-none d-sm-flex justify-content-center align-items-center fs-7" 777 data-number="@HttpUtility.HtmlAttributeEncode(product.Number)" 778 data-image="@HttpUtility.HtmlAttributeEncode(imagePath)" 779 data-name="@HttpUtility.HtmlAttributeEncode(product.Name)" 780 data-link="@HttpUtility.HtmlAttributeEncode(link)" 781 onclick="toggleCompareProduct(event, this)"> 782 <span class="square-icon js-square-icon d-flex" data-product-number="@HttpUtility.HtmlAttributeEncode(product.Number)"></span> 783 <span>@Translate("Sammenlign")</span> 784 </div> 785 786 @if (product.VariantInfo.VariantInfo != null && staticVariantsLayout == "swatches") 787 { 788 var optionCount = product.VariantInfo.VariantInfo.Count(); 789 var showMaxVariants = 5; 790 791 <div class="d-flex flex-row gap-1 align-items-center"> 792 @foreach (VariantInfoViewModel variant in product.VariantInfo.VariantInfo.Take(showMaxVariants)) 793 { 794 <span class="colorbox colorbox-sm rounded-circle border me-1" style="background-color: @variant.OptionColor"></span> 795 } 796 @if (optionCount > showMaxVariants) 797 { 798 int left = optionCount - showMaxVariants; 799 <span class="ms-2">+@left</span> 800 } 801 </div> 802 } 803 804 <div class="mt-3"> 805 <form method="post" action="@cartUrl"> 806 <input type="hidden" name="redirect" value="false" /> 807 <input type="hidden" name="ProductId" value="@product.Id" /> 808 <input type="hidden" name="ProductName" value="@HtmlEncoder.HtmlEncode(product.Name)" /> 809 <input type="hidden" name="ProductVariantName" value="@HtmlEncoder.HtmlEncode(product.VariantName)" /> 810 <input type="hidden" name="ProductCurrency" value="@Dynamicweb.Ecommerce.Common.Context.Currency.Code" /> 811 <input type="hidden" name="ProductPrice" value="@(showPricesWithVat == "false" && !neverShowVat ? product.Price.PriceWithoutVat.ToString("0.00", CultureInfo.InvariantCulture) : product.Price.Price.ToString("0.00", CultureInfo.InvariantCulture))" /> 812 <input type="hidden" name="ProductReferer" value="component_ProductListGridView_Custom"> 813 <input type="hidden" name="cartcmd" value="add" /> 814 <input type="hidden" name="quantity" value="1" /> 815 <input type="hidden" class="js-product-id" value="@product.Id" /> 816 817 @if (!string.IsNullOrEmpty(product.VariantId)) 818 { 819 <input type="hidden" name="VariantId" value="@product.VariantId" /> 820 } 821 822 @*//CUSTOM*@ 823 <div class="d-flex flex-column gap-2"> 824 @if (enableContact) 825 { 826 var enableContactlink = Pageview.AreaSettings.GetItem("CustomSettings").GetLink("Custom_EnableContactLink"); 827 if (enableContactlink != null) 828 { 829 <a href="@(enableContactlink.Url)" class="btn btn-tertiary flex-fill" title="@HttpUtility.HtmlAttributeEncode(Translate("Contact us about price and delivery >>"))"> 830 @Translate("Contact us about price and delivery >>") 831 </a> 832 } 833 } 834 835 @if (enableBookDemo) 836 { 837 var enableBookDemolink = Pageview.AreaSettings.GetItem("CustomSettings").GetLink("Custom_EnableBookDemoLink"); 838 if (enableBookDemolink != null) 839 { 840 <a href="@(enableBookDemolink.Url)" class="btn btn-tertiary flex-fill" title="@HttpUtility.HtmlAttributeEncode(Translate("Contact us about book demo >>"))"> 841 @Translate("Contact us about book demo >>") 842 </a> 843 } 844 } 845 846 @if (!disablePurchase) 847 { 848 if (!specs.GetByKey("Preorder").Value.IsYes()) 849 { 850 <button type="button" onclick="swift.Cart.Update(event)" class="btn btn-primary flex-fill js-add-to-cart-button" title="@HttpUtility.HtmlAttributeEncode(Translate("Add to cart"))" id="AddToCartButton@(product.Id)"> 851 @Translate("Add to cart") 852 </button> 853 } 854 else 855 { 856 <button type="button" class="btn btn-secondary flex-fill" onclick="Form(this).addData('@HttpUtility.HtmlEncode(product.Name)','@product.Id')" data-bs-toggle="modal" data-bs-target="#preorderModal"> 857 @Translate("Preorder") 858 </button> 859 } 860 } 861 </div> 862 @*//CUSTOM*@ 863 </form> 864 </div> 865 866 </div> 867 868 </div> 869 </article> 870 } 871 </div> 872 873 <div class="my-3" id="LoadMoreButton"> 874 <div class="text-center d-flex flex-column gap-3"> 875 <div class="opacity-85">@loadedProducts @Translate("out of") @productList.TotalProductsCount @Translate("products")</div> 876 @if (productList.PageCount != 1) 877 { 878 string sortBySelection = Dynamicweb.Context.Current.Request?.Form["SortBy"] ?? ""; 879 sortBySelection = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SortBy")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SortBy") : sortBySelection; 880 881 string searchQuery = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("q")) ? Dynamicweb.Context.Current.Request.QueryString.Get("q") : ""; 882 string searchLayout = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout") : ""; 883 884 <form method="get" action="@url" data-response-target-element="content" class="w-100"> 885 @foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) 886 { 887 foreach (FacetViewModel facetItem in facetGroup.Facets) 888 { 889 foreach (FacetOptionViewModel facetOption in facetItem.Options) 890 { 891 if (facetOption.Selected) 892 { 893 <input type="hidden" name="@facetItem.QueryParameter" value="[@facetOption.Value]"> 894 } 895 } 896 } 897 } 898 899 <input type="hidden" name="PageSize" value="@pageSize"> 900 <input type="hidden" name="SortBy" value="@sortBySelection"> 901 <input type="hidden" name="RequestType" value="UpdateList"> 902 903 @if (!string.IsNullOrEmpty(searchQuery)) 904 { 905 <input type="hidden" name="q" value="@HttpUtility.HtmlAttributeEncode(searchQuery)"> 906 <input type="hidden" name="SearchLayout" value="@searchLayout"> 907 } 908 909 @{ 910 string nextPageLink = "/Default.aspx?ID=" + Pageview.Page.ID + "&PageSize=" + pageSize + "&SortBy=" + sortBySelection; 911 912 foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) 913 { 914 foreach (FacetViewModel facetItem in facetGroup.Facets) 915 { 916 foreach (FacetOptionViewModel facetOption in facetItem.Options) 917 { 918 if (facetOption.Selected) 919 { 920 nextPageLink += "&" + facetItem.QueryParameter + "=[" + facetOption.Value + "]"; 921 } 922 } 923 } 924 } 925 926 nextPageLink += !string.IsNullOrEmpty(searchQuery) ? "&q=" + searchQuery : ""; 927 } 928 929 <a href="@nextPageLink" class="btn btn-primary" onclick="swift.ProductList.Update(event)" id="LoadMoreButton_@Model.ID">@Translate("Load more products")</a> 930 </form> 931 } 932 </div> 933 </div> 934 } 935 else 936 { 937 if (!Pageview.IsVisualEditorMode) 938 { 939 <div class="alert alert-dark m-0"> 940 @Translate("We did not find anything matching your search result") 941 </div> 942 } 943 else 944 { 945 <div class="alert alert-dark m-0" role="alert"> 946 <span>@Translate("Product list: The list will be shown here, if any")</span> 947 </div> 948 } 949 } 950 } 951 952 @helper RenderField(FieldValueViewModel field) 953 { 954 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 955 956 if (fieldValue != "") 957 { 958 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 959 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 960 961 if (field.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 962 { 963 fieldValue = ""; 964 965 foreach (FieldOptionValueViewModel option in field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>) 966 { 967 fieldValue = option.Name; 968 } 969 } 970 971 bool isColor = false; 972 if (fieldValue.Contains("#") && (Translate(field.Name) == Translate("Color") || Translate(field.Name) == Translate("Colour"))) 973 { 974 isColor = true; 975 } 976 977 if (!string.IsNullOrEmpty(fieldValue)) 978 { 979 if (!isColor) 980 { 981 <li>@(field.Name): @fieldValue</li> 982 } 983 else 984 { 985 <li class="position-relative"> 986 <span class="colorbox-sm" style="background-color: @fieldValue"></span> 987 </li> 988 } 989 } 990 } 991 }

Find det rigtige objektiv til foto og video

Det rigtige objektiv afhænger både af dit kamera, motivet og den måde, du arbejder på. Hos Goecker finder du objektiver til foto og video fra blandt andre Canon, Sony, Nikon, Fujifilm, Leica, Sigma, Tamron og Panasonic – fra kompakte faste brændvidder og alsidige zoomobjektiver til vidvinkel, tele og makro.

Objektivets brændvidde, lysstyrke, autofokus og eventuelle billedstabilisering har stor betydning for, hvordan det fungerer i praksis. Et vidvinkelobjektiv kan eksempelvis være velegnet til landskab, arkitektur og interiør, mens længere teleobjektiver ofte bruges til sport, natur og motiver på større afstand. Til portrætter, reportage og hverdagsfotografering findes både faste objektiver og zoomobjektiver i en lang række brændvidder.

Arbejder du med video, kan egenskaber som lydsvag autofokus, manuel betjening, focus breathing og stabilisering også have betydning. Til professionelle filmproduktioner findes desuden dedikerede cine-objektiver udviklet til videoproduktion.

Hvordan vælger jeg det rigtige objektiv til mit kamera?

Det første, du skal være opmærksom på, er kamerafatningen. Objektivet skal være kompatibelt med dit kamera, hvad enten du eksempelvis bruger Canon RF, Sony E/FE, Nikon Z, Fujifilm X, L-Mount eller et andet objektivsystem.

Når kompatibiliteten er på plads, er især disse forhold værd at overveje:

  • Brændvidde: Bestemmer objektivets billedvinkel. Korte brændvidder giver en bredere billedvinkel, mens lange brændvidder bringer motiver på afstand tættere på.
     
  • Lysstyrke: Et objektiv med lavt f-tal kan lukke mere lys ind og giver bedre muligheder for fotografering i svagt lys og en lille dybdeskarphed.
     
  • Fast eller zoom: Et fast objektiv har én brændvidde, mens et zoomobjektiv dækker flere brændvidder og giver større fleksibilitet uden objektivskift.
     
  • Autofokus: Hurtig og præcis autofokus kan være særlig vigtig til sport, action, events og video.
     
  • Billedstabilisering: Kan være en fordel ved håndholdt fotografering og video – især ved længere brændvidder eller længere lukkertider.
     
  • Nærgrænse og makro: Hvis du arbejder med små motiver og detaljer, bør du også se på objektivets nærgrænse og makroegenskaber.

Brug filtrene på siden til at sortere efter blandt andet producent, kamerafatning, objektivtype, brændvidde, autofokus og makro.

Flere kameraobjektiver med forskellige brændvidder
Udvalg af kameraobjektiver set forfra

Fast brændvidde eller zoomobjektiv?

Et objektiv med fast brændvidde – også kaldet et prime-objektiv – har én bestemt brændvidde. Mange faste objektiver kombinerer høj lysstyrke med et relativt enkelt optisk design og er populære til blandt andet portræt, reportage, gadefotografering og arbejde i svagt lys. Den faste billedvinkel betyder samtidig, at du i højere grad arbejder med placering og afstand til motivet, når kompositionen skal ændres.

Et zoomobjektiv giver mulighed for at skifte mellem flere brændvidder uden at skifte objektiv. Det gør zoomobjektiver velegnede, når motiver og afstande ændrer sig hurtigt, eller når du ønsker at dække flere typer optagelser med ét objektiv. Der findes både kompakte standardzooms og professionelle zoomobjektiver til blandt andet vidvinkel, reportage, sport og telefoto.

Der er ikke én løsning, der passer til alle. Mange fotografer og videografer kombinerer zoomobjektiver med en eller flere faste brændvidder afhængigt af opgaven.

Få hjælp til at vælge objektiv

Er du i tvivl om kamerafatning, brændvidde eller hvilket objektiv der passer bedst til dit arbejde, hjælper vores specialister gerne med at finde den rigtige løsning. Vi kan også rådgive om filtre, adapters, telekonvertere og andet objektivtilbehør, så det samlede setup passer til dit kamera og din måde at arbejde på.

Du kan få rådgivning online eller besøge Goecker i København og Aarhus.