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.
Se også: Objektivadaptere · Modlysblænder · Telekonvertere · Objektivfiltre · Kikkerter
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.
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.