Error executing template "Designs/rm/eCom/Product/Boligvisning.cshtml"
System.InvalidOperationException: Sequence contains no elements
at System.Linq.ThrowHelper.ThrowNoElementsException()
at System.Linq.Enumerable.First[TSource](IEnumerable`1 source)
at CompiledRazorTemplates.Dynamic.RazorEngine_d95782f153444d17b64e02e35112771c.ExecuteAsync()
at RazorEngine.Templating.TemplateBase.Run(ExecuteContext context, TextWriter reader)
at RazorEngine.Templating.RazorEngineCore.RunTemplate(ICompiledTemplate template, TextWriter writer, Object model, DynamicViewBag viewBag)
at RazorEngine.Templating.RazorEngineService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
at RazorEngine.Templating.DynamicWrapperService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass23_0.<Run>b__0(TextWriter writer)
at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag)
at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
2 @using Custom.Tracking;
3 @using Dynamicweb;
4 @using Dynamicweb.Content.Items;
5 @using Dynamicweb.Core;
6 @using Dynamicweb.Core.Encoders;
7 @using RealMaeglerne.Library;
8 @using RealMaeglerne.Library.Models
9 @using System
10 @using System.Linq;
11
12 @functions {
13 string FormatPrice(int price, bool currencyBefore = false)
14 {
15 return currencyBefore ? "kr. " + price.ToString("#,##0") : price.ToString("#,##0") + " kr.";
16 }
17
18 string GetFullAddress(Dynamicweb.Security.UserManagement.UserGroup user)
19 {
20 if (user == null) { return string.Empty; }
21
22 var hasAddress = !string.IsNullOrEmpty(user.Address);
23 var hasZip = !string.IsNullOrEmpty(user.ZipCode);
24 var hasCity = !string.IsNullOrEmpty(user.City);
25
26 if (!hasAddress && !hasZip && !hasCity) return string.Empty;
27
28 return $"{(hasAddress ? user.Address + ", " : "")}{(hasZip ? user.ZipCode + " " : "")}{(hasCity ? user.City : "")}".TrimEnd(' ', ',');
29 }
30 }
31 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
32 @using Dynamicweb.Content.Items;
33
34 @functions{
35 void RenderErhvervsTypeCheckboxes(string productGroupFilter)
36 {
37 <div class="col-xs-6 col-md-4">
38 <div class="checkbox">
39 <label>
40 <input type="checkbox" name="propertytype" value="bolig/erhverv, kombineret erhverv og bolig, byejendom (kontor, butik, beboelse)" />
41 <span>Bolig/erhverv</span>
42 </label>
43 </div>
44 <div class="checkbox">
45 <label>
46 <input type="checkbox" name="propertytype" value="erhvervsgrund" />
47 <span>Erhvervsgrund</span>
48 </label>
49 </div>
50 <div class="checkbox">
51 <label>
52 <input type="checkbox" name="propertytype" value="boligudlejning" />
53 <span>Boligudlejningsejendom</span>
54 </label>
55 </div>
56 <div class="checkbox">
57 <label>
58 <input type="checkbox" name="propertytype" value="kontor, klinik, kontorhotel, showroom, undervisningslokaler" />
59 <span>Kontor</span>
60 </label>
61 </div>
62 </div>
63 <div class="col-xs-6 col-md-4">
64 <div class="checkbox">
65 <label>
66 <input type="checkbox" name="propertytype" value="butik / detail, butik / detailhandel" />
67 <span>Butik/detailhandel</span>
68 </label>
69 </div>
70 <div class="checkbox">
71 <label>
72 <input type="checkbox" name="propertytype" value="industri / logistik, håndværk, industri, kontor / lager, logistik" />
73 <span>Produktion/lager</span>
74 </label>
75 </div>
76 <div class="checkbox">
77 <label>
78 <input type="checkbox" name="propertytype" value="hotel - kursusejendom, restaurant" />
79 <span>Hotel og restaurant</span>
80 </label>
81 </div>
82 <div class="checkbox">
83 <label>
84 <input type="checkbox" name="propertytype" value="projekt ejendom" />
85 <span>Projektejendom</span>
86 </label>
87 </div>
88 </div>
89 <div class="col-xs-6 col-md-4">
90 <div class="checkbox">
91 <label>
92 <input type="checkbox" name="propertytype" value="andet" />
93 <span>Andet</span>
94 </label>
95 </div>
96 </div>
97
98 <input type="hidden" name="propertycategory" value="erhverv, udlejning" />
99 <input type="hidden" name="filtrering" value="@productGroupFilter" />
100 }
101 void RenderBoligtypeCheckboxes()
102 {
103 <div class="col-6 col-md-4">
104 <div class="checkbox">
105 <label>
106 <input type="checkbox" name="propertytype" value="villa" />
107 <span>Villa</span>
108 </label>
109 </div>
110 <div class="checkbox">
111 <label>
112 <input type="checkbox" name="propertytype" value="rækkehus" />
113 <span>Rækkehus</span>
114 </label>
115 </div>
116 <div class="checkbox">
117 <label>
118 <input type="checkbox" name="propertytype" value="villalejlighed" />
119 <span>Villalejlighed</span>
120 </label>
121 </div>
122 <div class="checkbox">
123 <label>
124 <input type="checkbox" name="propertytype" value="andelsbolig" />
125 <span>Andelsbolig</span>
126 </label>
127 </div>
128 </div>
129 <div class="col-6 col-md-4">
130 <div class="checkbox">
131 <label>
132 <input type="checkbox" name="propertytype" value="fritidshus, fritidsbolig" />
133 <span>Fritidsbolig</span>
134 </label>
135 </div>
136 <div class="checkbox">
137 <label>
138 <input type="checkbox" name="propertytype" value="ejerlejlighed" class="specialOption" data-disable-slider="#grundareal" data-disable-slider-ranges="#grundarealmin,#grundarealmax" />
139 <span>Ejerlejlighed</span>
140 </label>
141 </div>
142 <div class="checkbox">
143 <label>
144 <input type="checkbox" name="propertytype" value="helårsgrund" class="specialOption" data-disable-slider="#boligareal,#roomsslider" data-disable-slider-ranges="#boligarealmin,#boligarealmax,#roomsmin" />
145 <span>Helårsgrund</span>
146 </label>
147 </div>
148 <div class="checkbox">
149 <label>
150 <input type="checkbox" name="propertytype" value="fritidsgrund" class="specialOption" data-disable-slider="#boligareal,#roomsslider" data-disable-slider-ranges="#boligarealmin,#boligarealmax,#roomsmin" />
151 <span>Fritidsgrund</span>
152 </label>
153 </div>
154 </div>
155 <div class="col-6 col-md-4">
156 <div class="checkbox">
157 <label>
158 <input type="checkbox" name="propertytype" value="landejendom, lystejendom" class="specialOption" data-disable-checkbox="true" />
159 <span>Landejendom</span>
160 </label>
161 </div>
162 <div class="checkbox">
163 <label>
164 <input type="checkbox" name="propertytype" value="erhverv" class="specialOption" data-disable-checkbox="true" data-disable-slider="#roomsslider" data-disable-slider-ranges="#roomsmin" />
165 <span>Erhverv</span>
166 </label>
167 </div>
168 </div>
169 }
170
171 void RenderChecked(string queryString)
172 {
173 if (Dynamicweb.Context.Current.Request.QueryString["propertytype"] == queryString)
174 {
175 @("checked")
176 }
177 }
178
179 void RenderBoligtypeCheckboxesDropdown()
180 {
181 Dictionary<string, string> propertyTypes = new Dictionary<string, string>(){
182 { "Villa", "villa" }, { "Rækkehus", "rækkehus" }, { "Villalejlighed", "villalejlighed" },
183 { "Andelsbolig", "andelsbolig" }
184 };
185 foreach (KeyValuePair<string, string> type in propertyTypes)
186 {
187 bool ischecked = false;
188 string[] propertytypeSplit = new string[0];
189 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["propertytype"]))
190 {
191 propertytypeSplit = Dynamicweb.Context.Current.Request.QueryString["propertytype"].Split(',');
192 }
193 foreach (var propertytypeParams in propertytypeSplit)
194 {
195 if (propertytypeParams == type.Value)
196 {
197 ischecked = true;
198 }
199 }
200 <li>
201 <label class="checkbox-container d-flex">
202 @Translate("Smartpage:Search.DropDown." + type.Key + "", "" + type.Key + "")
203 <input type="checkbox" name="propertytype" value="@type.Value" class="js-input-check datavalue js-datavalue js-count" data-val="@type.Key" onchange="submitFilter()" checked="@ischecked" />
204 <span class="checkmark grey"></span>
205 </label>
206 </li>
207 }
208
209 <li>
210 <label class="checkbox-container d-flex">
211 @Translate("Smartpage:Search.DropDown.Blandet Bolig/Erhverv", "Blandet Bolig/Erhverv")
212 @{
213 bool blboligcheck = false;
214 }
215 @if (Dynamicweb.Context.Current.Request.QueryString["propertycategory"] == "Blandet Bolig/Erhverv")
216 {
217 blboligcheck = true;
218 }
219 <input type="checkbox" name="propertycategory" value="Blandet Bolig/Erhverv" class="specialOption js-input-check js-datavalue js-count" data-disable-checkbox="true" data-disable-slider="#roomsslider" data-disable-slider-ranges="#roomsmin" checked="@blboligcheck" />
220 <span class="checkmark grey"></span>
221 </label>
222 </li>
223
224 Dictionary<string, string> propertyTypes2 = new Dictionary<string, string>(){
225 { "Fritidsbolig", "fritidshus, fritidsbolig" }, { "Ejerlejlighed", "ejerlejlighed" }, { "Helårsgrund", "helårsgrund" },
226 { "Fritidsgrund", "fritidsgrund" }, { "Landejendom", "landejendom, lystejendom" }
227 };
228 foreach (KeyValuePair<string, string> type in propertyTypes2)
229 {
230 bool ischecked = false;
231 string[] propertytypeSplit2 = new string[0];
232 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["propertytype"]))
233 {
234 propertytypeSplit2 = Dynamicweb.Context.Current.Request.QueryString["propertytype"].Split(',');
235 }
236 foreach (var propertytypeParams in propertytypeSplit2)
237 {
238 if (propertytypeParams == type.Value)
239 {
240 ischecked = true;
241 }
242 }
243 <li>
244 <label class="checkbox-container d-flex">
245 @Translate("Smartpage:Search.DropDown." + type.Key + "", "" + type.Key + "")
246 @if (type.Value == "ejerlejlighed")
247 {
248 <input type="checkbox" name="propertytype" value="@type.Value" class="js-input-check datavalue" data-disable-slider="#grundareal" data-disable-slider-ranges="#grundarealmin,#grundarealmax" data-val="@type.Key" onchange="submitFilter()" checked="@ischecked" />
249 }
250 else if (type.Value == "helårsgrund")
251 {
252 <input type="checkbox" name="propertytype" value="@type.Value" class="js-input-check datavalue" data-disable-slider="#boligareal,#roomsslider" data-disable-slider-ranges="#boligarealmin,#boligarealmax,#roomsmin" data-val="@type.Key" onchange="submitFilter()" checked="@ischecked" />
253 }
254 else if (type.Value == "fritidsgrund")
255 {
256 <input type="checkbox" name="propertytype" value="@type.Value" class="js-input-check datavalue" data-disable-slider="#boligareal,#roomsslider" data-disable-slider-ranges="#boligarealmin,#boligarealmax,#roomsmin" data-val="@type.Key" onchange="submitFilter()" checked="@ischecked" />
257 }
258 else
259 {
260 <input type="checkbox" name="propertytype" value="@type.Value" class="js-input-check datavalue" data-val="@type.Key" onchange="submitFilter()" checked="@ischecked" />
261 }
262 <span class="checkmark grey"></span>
263 </label>
264 </li>
265 }
266 }
267
268 void RenderBoligTypeErhverv(bool submitOnChange = false, bool frontpage = false)
269 {
270 Dictionary<string, string> erhverType = new Dictionary<string, string>(){
271 { "Kontor", "OwnUseOffices" }, { "Lager + Produktion", "OwnUseStoresAndProductions" }, { "Detailhandel", "OwnUseRetailAndStores" },
272 { "Grunde", "OwnUseParcel" }, { "Andre typer", "OwnUseOtherTypes" }, { "Hotel + Restaurant", "OwnUseHotelsAndRestaurants" }
273 };
274 var submitonchange = "";
275 if (submitOnChange)
276 {
277 submitonchange = "onchange='submitFilter()'";
278 }
279
280 foreach (KeyValuePair<string, string> type in erhverType)
281 {
282 string ischecked = "";
283 string[] olineParamsSplit = new string[0];
284 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["olinecategory"]))
285 {
286 olineParamsSplit = Dynamicweb.Context.Current.Request.QueryString["olinecategory"].Split(',');
287 }
288 foreach (var olineParams in olineParamsSplit)
289 {
290 if (olineParams == type.Value)
291 {
292 ischecked = "checked";
293 }
294 }
295
296 <li>
297 <label class="checkbox-container d-flex">
298 @Translate("Smartpage:Search.DropDown." + type.Key + "", "" + type.Key + "")
299 <input type="checkbox" name="olinecategory" value="@type.Value" class="js-input-check datavalue" data-val="@type.Key" @submitonchange @ischecked />
300 <span class="checkmark grey"></span>
301 </label>
302 </li>
303 }
304
305
306 bool ischeckedpropertycat = false;
307 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["propertycategory"]))
308 {
309 if (Dynamicweb.Context.Current.Request.QueryString["propertycategory"] == "Blandet Bolig/Erhverv")
310 {
311 ischeckedpropertycat = true;
312 }
313 }
314 <li>
315 <label class="checkbox-container">
316 @Translate("Smartpage:Search.DropDown.Blandet Bolig/Erhverv", "Blandet Bolig/Erhverv")
317 <input type="checkbox" name="propertycategory" value="Blandet Bolig/Erhverv" class="js-input-check datavalue" data-val="Blandet Bolig/Erhverv" onchange="submitFilter()" checked="@ischeckedpropertycat" />
318 <span class="checkmark grey"></span>
319 </label>
320 </li>
321 }
322
323 void RenderBoligTypeErhvervInvest(bool submitOnChange = false)
324 {
325 Dictionary<string, string> erhverType = new Dictionary<string, string>(){
326 { "Kontor", "Kontor" }, { "Lager + Produktion", "InvestmentStoresAndProductions" }, { "Boligudlejning", "InvestmentHousingRental" },
327 { "Detailhandel", "InvestmentRetailAndStores" }, { "Grunde", "InvestmentParcel" }, { "Hotel + Restaurant", "InvestmentHotelsAndRestaurants" }, { "Andre typer", "InvestmentOtherTypes" }
328 };
329
330 foreach (KeyValuePair<string, string> type in erhverType)
331 {
332 bool ischecked = false;
333 string[] olineParamsSplit = new string[0];
334 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["olinecategory"]))
335 {
336 olineParamsSplit = Dynamicweb.Context.Current.Request.QueryString["olinecategory"].Split(',');
337 }
338 foreach (var olineParams in olineParamsSplit)
339 {
340 if (olineParams == type.Value)
341 {
342 ischecked = true;
343 }
344 }
345
346 <li>
347 <label class="checkbox-container">
348 @Translate("Smartpage:Search.DropDown." + type.Key + "", "" + type.Key + "")
349 <input type="checkbox" name="olinecategory" value="@type.Value" class="js-input-check datavalue" data-val="@type.Key" onchange="submitFilter()" checked="@ischecked" />
350 <span class="checkmark grey"></span>
351 </label>
352 </li>
353 }
354 }
355 int GetWebsiteSettingsPageId(string pageSysName)
356 {
357 int sideId = 0;
358
359 var pw = Dynamicweb.Frontend.PageView.Current();
360
361 string settingsItemId = "1";
362
363 if ((pw.Area.Item.ContainsKey("Type") && pw.Area.Item["Type"].ToString() == "bone") || Dynamicweb.Context.Current.Request.QueryString["bone"] == "true")
364 {
365 settingsItemId = "2";
366 }
367
368 var settingsItem = ItemManager.Storage.GetById("Delte_Egenskaber", settingsItemId);
369
370 if (settingsItem == null || !settingsItem.ContainsKey(pageSysName))
371 {
372 return sideId;
373 }
374
375 string boligsideLink = settingsItem[pageSysName] as String;
376 string linkPrefix = "Default.aspx?ID=";
377
378 if (!String.IsNullOrEmpty(boligsideLink) && boligsideLink.ToLower().StartsWith(linkPrefix.ToLower()))
379 {
380 Int32.TryParse(boligsideLink.Substring(linkPrefix.Length), out sideId);
381 }
382
383 return sideId;
384 }
385
386 int GetPageSettingsPageId(string pageSysName)
387 {
388 int sideId = 0;
389
390 var pw = Dynamicweb.Frontend.PageView.Current();
391
392 if (pw.Page == null || pw.Page.PropertyItem == null || !pw.Page.PropertyItem.ContainsKey(pageSysName))
393 {
394 return sideId;
395 }
396
397 string boligsideLink = pw.Page.PropertyItem[pageSysName] as String;
398 string linkPrefix = "Default.aspx?ID=";
399
400 if (!String.IsNullOrEmpty(boligsideLink) && boligsideLink.ToLower().StartsWith(linkPrefix.ToLower()))
401 {
402 Int32.TryParse(boligsideLink.Substring(linkPrefix.Length), out sideId);
403 }
404
405 return sideId;
406 }
407 void RenderMobileSelectBox(string name, int max, int step, string className, string inputname)
408 {
409 <select class="form-control d-block d-lg-none mb-10 @className" onchange="submitFilter()" name="@inputname">
410 <option selected="true" disabled="disabled">@Translate("Smartpage:Search.Placeholder." + name + "", "" + name + "")</option>
411
412 @for (var i = 0; i <= max; i += step)
413 {
414 var selected = string.Empty;
415 var current = string.Empty;
416 if (i == max)
417 {
418 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString[inputname]) && Dynamicweb.Context.Current.Request.QueryString[inputname] == Convert.ToString(i))
419 {
420 <option value="@i" data-value='@Convert.ToInt32(i).ToString("N0")' selected="selected">@Convert.ToInt32(i).ToString("N0")+</option>
421 }
422 else
423 {
424 <option value="@i" data-value='@Convert.ToInt32(i).ToString("N0")'>@Convert.ToInt32(i).ToString("N0")+</option>
425 }
426 }
427 else
428 {
429 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString[inputname]) && Dynamicweb.Context.Current.Request.QueryString[inputname] == Convert.ToString(i))
430 {
431 <option value="@i" data-value='@Convert.ToInt32(i).ToString("N0")' selected="selected">@Convert.ToInt32(i).ToString("N0")</option>
432 }
433 else
434 {
435 <option value="@i" data-value='@Convert.ToInt32(i).ToString("N0")'>@Convert.ToInt32(i).ToString("N0")</option>
436 }
437 }
438 }
439 </select>
440 }
441
442 void RenderTopFilter(string parameter)
443 {
444 if (parameter == "pricemin" || parameter == "pricemax")
445 {
446 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request["pricemin"]))
447 {
448 if (parameter == "pricemin")
449 {
450 @("<div class='search-terms' id='priceFilter'>")
451 @("Pris ") @Dynamicweb.Context.Current.Request[parameter]
452 }
453
454 else
455 {
456 @(" - ") @Dynamicweb.Context.Current.Request[parameter] @(" kr.") <i class="fa fa-times ml-2 pointer" onclick="removeParams(this)" data-tag="pricemin,pricemax"></i>
457 @("</div>")
458 }
459 }
460 }
461
462 else if (parameter == "subsidymin" || parameter == "subsidymax")
463 {
464 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request["subsidymin"]))
465 {
466 if (parameter == "subsidymin")
467 {
468 @("<div class='search-terms' id='subsidyFilter'>")
469 @("Årlig leje ") @Dynamicweb.Context.Current.Request[parameter]
470 }
471
472 else
473 {
474 @(" - ") @Dynamicweb.Context.Current.Request[parameter] @(" kr.") <i class="fa fa-times ml-2 pointer" onclick="removeParams(this)" data-tag="subsidymin,subsidymax"></i>
475 @("</div>")
476 }
477 }
478 }
479 else if (parameter == "etagearealmin" || parameter == "etagearealmax")
480 {
481 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request["etagearealmin"]))
482 {
483 if (parameter == "etagearealmin")
484 {
485 @("<div class='search-terms' id='etagearealFilter'>")
486 @("Etageareal ") @Dynamicweb.Context.Current.Request[parameter]
487 }
488
489 else
490 {
491 @(" - ") @Dynamicweb.Context.Current.Request[parameter] @(" kvm.") <i class="fa fa-times ml-2 pointer" onclick="removeParams(this)" data-tag="etagearealmin,etagearealmax"></i>
492 @("</div>")
493 }
494 }
495 }
496
497 else if (parameter == "grundarealmin" || parameter == "grundarealmax")
498 {
499 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request["grundarealmin"]))
500 {
501 if (parameter == "grundarealmin")
502 {
503 @("<div class='search-terms' id='grundarealFilter'>")
504 @("Grundareal ") @Dynamicweb.Context.Current.Request[parameter]
505 }
506
507 else
508 {
509 @(" - ") @Dynamicweb.Context.Current.Request[parameter] @(" kvm.") <i class="fa fa-times ml-2 pointer" onclick="removeParams(this)" data-tag="grundarealmin,grundarealmax"></i>
510 @("</div>")
511 }
512 }
513 }
514
515 else if (parameter == "subsidykvmmin" || parameter == "subsidykvmmax")
516 {
517 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request["subsidykvmmin"]))
518 {
519 if (parameter == "subsidykvmmin")
520 {
521 @("<div class='search-terms' id='subsidykvmFilter'>")
522 @("Årlig leje kvm ") @Dynamicweb.Context.Current.Request[parameter]
523 }
524
525 else
526 {
527 @(" - ") @Dynamicweb.Context.Current.Request[parameter] @(" kr.") <i class="fa fa-times ml-2 pointer" onclick="removeParams(this)" data-tag="subsidykvmmin,subsidykvmmax"></i>
528 @("</div>")
529 }
530 }
531 }
532
533 else if (parameter == "olinecategory")
534 {
535
536 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request["olinecategory"]))
537 {
538 Dictionary<string, string> erhverType = new Dictionary<string, string>(){
539 {"OwnUseOffices", "Kontor" }, { "OwnUseStoresAndProductions","Lager + Produktion" }, { "OwnUseRetailAndStores","Detailhandel" },
540 { "OwnUseParcel", "Grunde" }, { "OwnUseHotelsAndRestaurants", "Hotel + Restaurant" }, { "OwnUseOtherTypes", "Andre typer"},
541 { "Kontor", "Kontor" }, { "InvestmentStoresAndProductions", "Lager + Produktion" }, { "InvestmentHousingRental", "Boligudlejning" },
542 { "InvestmentRetailAndStores", "Detailhandel" }, { "InvestmentParcel", "Grunde" }, { "InvestmentHotelsAndRestaurants", "Hotel + Restaurant" }, { "InvestmentOtherTypes", "Andre typer" }
543 };
544
545
546 foreach (var er in erhverType)
547 {
548 if (Dynamicweb.Context.Current.Request[parameter].Contains(er.Key))
549 {
550 <div class="search-terms" id="@parameter">
551 @er.Value <i class="fa fa-times ml-2 pointer" onclick="removeParams(this)" data-tag="@parameter" data-val="@er.Key"></i>
552 </div>
553 }
554 }
555 }
556 }
557 else if (parameter == "propertycategory")
558 {
559
560 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request["propertycategory"]))
561 {
562 Dictionary<string, string> erhverType = new Dictionary<string, string>(){
563 { "propertycategory", "Blandet Bolig/Erhverv" }
564 };
565
566 foreach (var er in erhverType)
567 {
568 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request[parameter]) && Dynamicweb.Context.Current.Request[parameter] == er.Value)
569 {
570 <div class="search-terms" id="@parameter">
571 @er.Value <i class="fa fa-times ml-2 pointer" onclick="removeParams(this)" data-tag="@parameter" data-val="@er.Key"></i>
572 </div>
573 }
574 }
575 }
576 }
577 else if (parameter == "search")
578 {
579 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request["search"]))
580 {
581 <div class="search-terms" id="@parameter">
582 @Dynamicweb.Context.Current.Request[parameter] <i class="fa fa-times ml-2 pointer" onclick="removeParams(this)" data-tag="@parameter"></i>
583 </div>
584 }
585 }
586 else
587 {
588 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request[parameter]))
589 {
590 Dictionary<string, string>
591 ubudsform = new Dictionary<string, string>
592 (){
593 {"salg", "Salg" }, { "leje","Leje" }
594 };
595
596 foreach (var er in ubudsform)
597 {
598 if (Dynamicweb.Context.Current.Request[parameter].Contains(er.Key))
599 {
600 <div class="search-terms" id="@parameter">
601 @er.Value <i class="fa fa-times ml-2 pointer" onclick="removeParams(this)" data-tag="@parameter" data-val="@er.Key"></i>
602 </div>
603 }
604 }
605
606
607 }
608 }
609 }
610
611 void RenderSelectValue(string dropdownname, string dropdownvalue, string queryString)
612 {
613 var selected = "";
614 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString[queryString]) && Dynamicweb.Context.Current.Request.QueryString[queryString] == dropdownvalue)
615 {
616 selected = "selected";
617 }
618
619 var current = string.Format("<option value='" + dropdownvalue + "'>" + dropdownname + "</option>", selected);
620
621 @current
622 }
623
624 void RenderSearchForHousing(int searchPageId, string querySearch, string querySearchNameAttr, string queryZipCodeFrom, string queryZipCodeTo, string template, Item SettingsItem, string cssClasses = "")
625 {
626 <div class="main-search-form frontpage @cssClasses">
627 <div class="dropdown-overlay"></div>
628 <div class="row mb-3 align-items-center">
629 <div class="col-xs-12 col-md-3 border-right">
630 <h3>@Translate("Smartpage:Search.Søg bolig", "Søg bolig")</h3>
631 </div>
632 <div class="col-xs-12 col-md-9 home-count d-none d-md-block">
633 <span class="search-count" id="searchCounter">0</span> <span>@Translate("Smartpage:Search.BoligerTilSalg", "Boliger til salg")</span>
634 </div>
635 </div>
636
637 <form id="main-search-frontpage" class="searchbar-wrapper" action="/Default.aspx" method="GET">
638 <input type="hidden" name="ID" value='@searchPageId' id="searchPageId-frontpage" disabled="disabled" />
639 <div class="row form-wrapper no-gutters">
640
641 <div class="col-xs-12 col-md-5 col-searchbar">
642 <div class="searchbar">
643 <input type="text" name="@querySearchNameAttr" id="searchfield-frontpage" class="search-input" placeholder="Postnummer, by, vej eller sagsnummer" tabindex="1" value="@Dynamicweb.Core.Encoders.HtmlEncoder.HtmlAttributeEncode(querySearch)" />
644 <input type="hidden" id="zipcodefrom-frontpage" name="zipcodefrom" value="@Dynamicweb.Core.Encoders.HtmlEncoder.HtmlAttributeEncode(queryZipCodeFrom)" />
645 <input type="hidden" id="zipcodeto-frontpage" name="zipcodeto" value="@Dynamicweb.Core.Encoders.HtmlEncoder.HtmlAttributeEncode(queryZipCodeTo)" />
646 </div>
647 </div>
648 <div class="col-xs-12 col-md-5">
649 <div class="row no-gutters">
650 <div class="col-xs-12 col-md-6 input-col">
651 <div class="dropdown w-overlay">
652 <button class="btn btn-dropdown dropdown-toggle reverse position-absolute-md" type="button" id="Boligtype-frontpage" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
653 @Translate("Smartpage:Search.Boligtype", "Boligtype")
654 </button>
655 <div class="dropdown-menu box-shadow bolig-dropdown-container" aria-labelledby="Boligtype">
656 <ul class="bolig-dropdown list-unstyled">
657 @{
658 RenderBoligtypeCheckboxesDropdown();
659 }
660 </ul>
661 <span class="border-fat"></span>
662 <button class="btn btn-primary js-close-dropdown">@Translate("Smartpage:Search.Anvend", "Anvend")</button>
663 </div>
664
665 </div>
666
667 </div>
668 <div class="col-xs-12 col-md-6 input-col">
669 <div class="dropdown w-overlay">
670 <button class="btn btn-dropdown dropdown-toggle reverse position-absolute-md" type="button" id="Pris-frontpage" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
671 @Translate("Smartpage:Search.Pris", "Pris")
672 </button>
673 <div class="dropdown-menu box-shadow dropdown-price" aria-labelledby="Pris">
674 <input type="text" class="form-control mb-10 js-auto-thousand js-pricemin-frontpage-input" placeholder='@Translate("Smartpage:Search.Placeholder.MinPris","Min. pris")' />
675 <select class="form-control js-pricemin-frontpage-select js-input-min-select mb-10">
676 <option selected="true" disabled="disabled">@Translate("Smartpage:Search.Placeholder.MinPris", "Min. pris")</option>
677 @for (var i = 0; i <= 10000000; i += 100000)
678 {
679 if (i == 10000000)
680 {
681 <option value="@i" data-value='@Convert.ToInt32(i).ToString("N0")+'>@Convert.ToInt32(i).ToString("N0")+</option>
682 }
683 else
684 {
685 <option value="@i" data-value='@Convert.ToInt32(i).ToString("N0")'>@Convert.ToInt32(i).ToString("N0")</option>
686 }
687 }
688 </select>
689 <input type="hidden" id="pricemin-frontpage" name="pricemin" />
690
691 <input type="text" class="form-control js-auto-thousand js-pricemax-frontpage-input" placeholder='@Translate("Smartpage:Search.Placeholder.MaxPris","Max. pris")' />
692 <select class="form-control js-pricemax-frontpage-select js-input-max-select">
693 <option selected="true" disabled="disabled">@Translate("Smartpage:Search.Placeholder.MaxPris", "Max. pris")</option>
694 @for (var i = 0; i <= 10000000; i += 100000)
695 {
696 if (i == 10000000)
697 {
698 <option value="@i" data-value='@Convert.ToInt32(i).ToString("N0")+'>@Convert.ToInt32(i).ToString("N0")+</option>
699 }
700 else
701 {
702 <option value="@i" data-value='@Convert.ToInt32(i).ToString("N0")'>@Convert.ToInt32(i).ToString("N0")</option>
703 }
704 }
705 </select>
706 <input type="hidden" id="pricemax-frontpage" name="pricemax" />
707 <button class="btn btn-primary js-close-dropdown mt-3">@Translate("Smartpage:Search.Anvend", "Anvend")</button>
708 </div>
709 </div>
710 </div>
711 </div>
712 </div>
713 <div class="col-xs-12 col-md-2 d-none d-md-block">
714 <button type="submit" class="btn btn-block btn-search"><i class="fa fa-search"></i> @Translate("Smartpage:Search.Søg", "Søg")</button>
715 </div>
716 </div>
717
718 <div class="row moresearch-btn no-gutters">
719 <div class="col-sm-12">
720 <div class="row align-items-center no-gutters">
721 <div class="col-12 col-md-4">
722 <button class="btn-blank js-search-collapse" type="button" data-toggle="collapse" data-target="#moreSearch" aria-expanded="false" aria-controls="moreSearch">
723 <span class="moreSearch-text"><i class="fas fa-plus open-close"></i> <span class="not-open">@Translate("Smartpage:Search.Flere søgemuligheder", "Flere søgemuligheder")</span> <span class="open"><span class="js-filter-count">0</span> @Translate("Smartpage:Search.FiltreAnvendt", "filtre anvendt") </span></span>
724 </button>
725 </div>
726 <div class="col-6 col-md-2 mb-xs-4">
727 <a class="js-reset reset-btn">@Translate("Smartpage:Search.NulstilValg", "Nulstil valg")</a>
728 </div>
729 </div>
730
731 <div class="collapse" id="moreSearch">
732 <h4 class="mt-20"><b>@Translate("Smartpage:Search.Bolig", "Bolig")</b></h4>
733 <div class="row align-items-end mb-30">
734 <div class="col-12 col-sm-6 col-lg-3 mb-3 mb-lg-0">
735 <div class="filter-container row">
736 <label class="d-block col-12">@Translate("Smartpage:Search.Boligareal", "Boligareal")</label>
737 <div class="col-6 pr-sm-0 pr-2">
738 <input type="text" name="boligarealmin" id="boligarealmin-frontpage" class="form-control js-boligarealmin-frontpage-input js-count" placeholder='@Translate("Smartpage:Search.Placeholder.Minm2","Min. m2")' />
739 <select class="form-control js-boligarealmin-frontpage-select js-count">
740 <option selected="true" disabled="disabled">@Translate("Smartpage:Search.Placeholder.Minm2", "Min. m2")</option>
741 @for (var i = 0; i <= 300; i += 10)
742 {
743 if (i == 300)
744 {
745 <option value="@i">@i+</option>
746 }
747 else
748 {
749 <option value="@i">@i</option>
750 }
751 }
752 </select>
753 </div>
754 <div class="col-6 pl-sm-0 pl-2">
755 <input type="text" name="boligarealmax" id="boligarealmax-frontpage" class="form-control js-boligarealmax-frontpage-input js-count" placeholder='@Translate("Smartpage:Search.Placeholder.Maxm2","Max. m2")' />
756 <select class="form-control js-boligarealmax-frontpage-select js-count">
757 <option selected="true" disabled="disabled">@Translate("Smartpage:Search.Placeholder.Maxm2", "Max. m2")</option>
758 @for (var i = 0; i <= 300; i += 10)
759 {
760 if (i == 300)
761 {
762 <option value="@i">@i+</option>
763 }
764 else
765 {
766 <option value="@i">@i</option>
767 }
768 }
769 </select>
770 </div>
771 </div>
772 </div>
773 <div class="col-12 col-sm-6 col-lg-3 mb-3 mb-lg-0">
774 <div class="filter-container row">
775 <label class="d-block col-12">@Translate("Smartpage:Search.Grundareal", "Grundareal")</label>
776 <div class="col-6 pr-sm-0 pr-2">
777 <input type="text" name="grundarealmin" id="grundarealmin-frontpage" class="form-control js-grundarealmin-frontpage-input js-count" placeholder='@Translate("Smartpage:Search.Placeholder.Minm2","Min. m2")' />
778 <select class="form-control js-grundarealmin-frontpage-select js-count">
779 <option selected="true" disabled="disabled">@Translate("Smartpage:Search.Placeholder.Minm2", "Min. m2")</option>
780 @for (var i = 0; i <= 10000; i += 100)
781 {
782 if (i == 10000)
783 {
784 <option value="@i">@i+</option>
785 }
786 else
787 {
788 <option value="@i">@i</option>
789 }
790 }
791 </select>
792 </div>
793 <div class="col-6 pl-sm-0 pl-2">
794 <input type="text" name="grundarealmax" id="grundarealmax-frontpage" class="form-control js-grundarealmax-frontpage-input js-count" placeholder='@Translate("Smartpage:Search.Placeholder.Maxm2","Max. m2")' />
795 <select class="form-control js-grundarealmax-frontpage-select js-count">
796 <option selected="true" disabled="disabled">@Translate("Smartpage:Search.Placeholder.Maxm2", "Max. m2")</option>
797 @for (var i = 0; i <= 10000; i += 100)
798 {
799 if (i == 10000)
800 {
801 <option value="@i">@i+</option>
802 }
803 else
804 {
805 <option value="@i">@i</option>
806 }
807 }
808 </select>
809 </div>
810 </div>
811 </div>
812 <div class="col-12 col-sm-6 col-lg-3 mb-3 mb-lg-0">
813 <div class="filter-container row">
814 <label class="d-block col-12">Antal rum</label>
815
816 <div class="col-6 pr-sm-0 pr-2">
817 <select name="roomsmin" id="roomsmin-frontpage" class="form-control reverse js-count">
818 <option selected="true" disabled="disabled">@Translate("Smartpage:Search.Placeholder.Min", "Min")</option>
819 <option value="1">1</option>
820 <option value="2">2</option>
821 <option value="3">3</option>
822 <option value="4">4</option>
823 <option value="5+">5+</option>
824 </select>
825 </div>
826 <div class="col-6 pl-sm-0 pl-2">
827 <select name="roomsmax" id="roomsmax-frontpage" class="form-control reverse js-count">
828 <option selected="true" disabled="disabled">@Translate("Smartpage:Search.Placeholder.Max", "Max")</option>
829 <option value="1">1</option>
830 <option value="2">2</option>
831 <option value="3">3</option>
832 <option value="4">4</option>
833 <option value="5+">@Translate("Smartpage:Rooms.5", "5")</option>
834 </select>
835 </div>
836 </div>
837 </div>
838 <div class="col-12 col-sm-6 col-lg-3 mb-3 mb-lg-0">
839 <div class="row">
840 <div class="col-12">
841 <div class="filter-container">
842 <label class="d-block">Energimærke</label>
843 <select name="energylabel" id="energylabel-frontpage" class="form-control reverse js-count">
844 <option disabled selected="selected">@Translate("Smartpage:Search.Vælg", "Vælg")</option>
845 <option value="01">G</option>
846 <option value="02">F</option>
847 <option value="03">E</option>
848 <option value="04">D</option>
849 <option value="05">C</option>
850 <option value="06">B</option>
851 <option value="07">A</option>
852 <option value="08">A2010</option>
853 <option value="09">A2015</option>
854 <option value="10">A2020+</option>
855 </select>
856 </div>
857 </div>
858 </div>
859 </div>
860 <div class="col-12 col-sm-6 col-lg-3 mt-3">
861 <h4 class=""><b>@Translate("Smartpage:Search.Økonomi", "Økonomi")</b></h4>
862 <div class="filter-container row">
863 <label class="d-block col-12">@Translate("Smartpage:Search.Ejerudgift/boligydelse pr. måned", "Ejerudgift/boligydelse pr. måned")</label>
864 <div class="col-6 pr-sm-0 pr-2">
865 <input type="text" name="subsidymin" id="subsidymin-frontpage" class="form-control js-subsidymin-frontpage-input js-count" placeholder='@Translate("Smartpage:Search.Placeholder.MinDKK","Min. DKK")' />
866 <select class="form-control js-subsidymin-frontpage-select js-count">
867 <option selected="true" disabled="disabled">@Translate("Smartpage:Search.Placeholder.MinDKK", "Min. DKK")</option>
868 @for (var i = 0; i <= 25000; i += 1250)
869 {
870 if (i == 25000)
871 {
872 <option>@Convert.ToInt32(i).ToString("N0")+</option>
873 }
874 else
875 {
876 <option>@Convert.ToInt32(i).ToString("N0")</option>
877 }
878 }
879 </select>
880 </div>
881 <div class="col-6 pl-sm-0 pl-2">
882 <input type="text" name="subsidymax" id="subsidymax-frontpage" class="form-control js-subsidymax-frontpage-input js-count" placeholder='@Translate("Smartpage:Search.Placeholder.MaxDKK","Max. DKK")' />
883 <select class="form-control js-subsidymax-frontpage-select js-count">
884 <option selected="true" disabled="disabled">@Translate("Smartpage:Search.Placeholder.MaxDKK", "Max. DKK")</option>
885 @for (var i = 0; i <= 25000; i += 1250)
886 {
887 if (i == 25000)
888 {
889 <option value="@Convert.ToInt32(i)">@Convert.ToInt32(i).ToString("N0")+</option>
890 }
891 else
892 {
893 <option value="@Convert.ToInt32(i)">@Convert.ToInt32(i).ToString("N0")</option>
894 }
895 }
896 </select>
897 </div>
898 </div>
899 </div>
900 <div class="col-12 col-sm-6 col-lg-4 offset-lg-5 mt-3 mt-sm-0">
901 <button type="submit" class="btn btn-block btn-search"><i class="fa fa-search"></i> @Translate("Smartpage:Search.AnvendFiltre", "Anvend filtre")</button>
902 </div>
903 </div>
904 </div>
905 </div>
906 </div>
907
908 <div class="row d-block d-md-none form-wrapper no-gutters">
909 <div class="col-xs-12 col-md-2">
910 <button type="submit" class="btn btn-block btn-search btn-mobile-search">@Translate("Smartpage:Search.SøgBolig", "Søg Bolig")<i class="fa fa-search cta-icon"></i></button>
911 </div>
912 </div>
913 </form>
914 <div class="front-page-actions d-md-none">
915 <div>
916 <button class="btn btn-block btn-search btn-mobile-search js-search-mobile">@Translate("Smartpage:Search.SøgBolig", "Søg Bolig")<i class="fa fa-search cta-icon"></i></button>
917 </div>
918 <div>
919 @{
920 string brokerSearchId = SettingsItem != null ? Dynamicweb.Core.Converter.ToString(SettingsItem["Maeglersogning"]).Replace("Default.aspx?Id=", "") : "";
921 string ctaText = Translate("Smartpage.Frontpage.Mobile.FindBroker", "FIND EJENDOMSMÆGLER");
922 <form method="GET" action="/Default.aspx">
923 <input name="id" value="@brokerSearchId" type="hidden" />
924 <div class="icon-wrapper-wclick">
925 <i class="fas fa-search ta-submit-on-icon-click"></i>
926 <input class="box-cta-input ta-postnummer ta-submit-on-select ta-submit-on-enter" name="q" type="text" placeholder="@ctaText" onfocus="this.placeholder = ''" onblur="this.placeholder='@ctaText'" />
927 </div>
928 </form>
929 }
930 </div>
931 <div>
932 <a href="javascript:panelSalgsvurdering('Hovedmenu')" class="btn btn-orange btn-block">@Translate("Smartpage:Frontpage.Mobile.GetFreeAppraisal", "BESTIL GRATIS VURDERING")<i class="cta-icon fa fa-angle-right"></i></a>
933 </div>
934 </div>
935 </div>
936
937 }
938 Custom.Integration.Brokers.Models.BrokerEmployee GetBrokerFromCurrentProduct()
939 {
940 string productId = Dynamicweb.Context.Current.Request["ProductId"];
941
942 if (string.IsNullOrWhiteSpace(productId))
943 {
944 return null;
945 }
946
947 var propertyProduct = Dynamicweb.Ecommerce.Services.Products.GetProductById(productId, string.Empty, true);
948 if (propertyProduct == null)
949 {
950 return null;
951 }
952
953 string employee = Dynamicweb.Core.Converter.ToString(
954 Dynamicweb.Ecommerce.Services.Products.GetProductFieldValue(propertyProduct, "xAktoererMaeglerKontaktEmail")
955 );
956 string storeId = Dynamicweb.Core.Converter.ToString(
957 Dynamicweb.Ecommerce.Services.Products.GetProductFieldValue(propertyProduct, "xButikID")
958 );
959
960 if (string.IsNullOrWhiteSpace(employee) || string.IsNullOrWhiteSpace(storeId))
961 {
962 return null;
963 }
964
965 return Custom.Integration.Brokers.Search.GetEmployee(storeId, employee);
966 }
967
968 string GetAgentTitleFromCurrentProduct()
969 {
970 var propBroker = GetBrokerFromCurrentProduct();
971
972 if (propBroker?.Broker == null)
973 {
974 return string.Empty;
975 }
976
977 if (!string.IsNullOrEmpty(propBroker.Broker.CompanyName))
978 {
979 return propBroker.Broker.CompanyName;
980 }
981
982 return propBroker.Broker.Name ?? string.Empty;
983 }
984
985 string GetMasterBrokerUrlFromCurrentProduct()
986 {
987 var propBroker = GetBrokerFromCurrentProduct();
988
989 var itemId = propBroker?.Broker?.ItemId;
990 var itemType = propBroker?.Broker?.ItemType;
991
992 if (string.IsNullOrWhiteSpace(itemId) || string.IsNullOrWhiteSpace(itemType))
993 {
994 return string.Empty;
995 }
996 var brokerItem = Dynamicweb.Content.Items.ItemManager.Storage.GetById(itemType, itemId);
997
998 if (brokerItem == null)
999 {
1000 return string.Empty;
1001 }
1002
1003 var websiteId = Dynamicweb.Core.Converter.ToInt32(brokerItem["WebsiteId"]);
1004 var page = Dynamicweb.Content.Services.Pages.GetFirstPageForArea(websiteId);
1005 return Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl("Default.aspx?Id=" + page?.ID);
1006 }
1007 }
1008
1009 @{
1010
1011 var settingsItem = ItemManager.Storage.GetById("Delte_Egenskaber", "1");
1012 var settingsActivateGreenMobility = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetBoolean("Activate_Green_Mobility");
1013
1014 var iconPath = "/Files/Templates/Designs/rm/assets/images/svg/";
1015 var imagePath = "/Files/Images/RM billeder/";
1016 string fallbackImage = "/Files/Templates/Designs/rm/assets/images/na-real.png";
1017
1018 string productId = GetString("Ecom:Product.ID");
1019 var product = Dynamicweb.Ecommerce.Services.Products.GetProductById(productId, string.Empty, true);
1020 string propCategory = GetString("Ecom:Product:Field.xEjendomEjendomskategori");
1021 string propType = GetString("Ecom:Product:Field.xEjendomEjendomstype");
1022 string propTypeCategory = "";
1023 if (!string.IsNullOrEmpty(propType))
1024 {
1025 propTypeCategory = RealMaeglerne.Dynamicweb.PropertyClassification.GetCategoryByTypeName(propType).ToLower();
1026 }
1027
1028 string propTypeDisplay = !string.IsNullOrWhiteSpace(propCategory) ? propCategory : propTypeCategory;
1029 bool isRental = (propCategory != null && GetString("Ecom:Product:Field.xUdbudsForm").ToLower() == "leje" && !propCategory.Contains("erhverv")) || Converter.ToBoolean(Dynamicweb.Context.Current.Request["Udlejning"]);
1030
1031 string Employee = GetString("Ecom:Product:Field.xAktoererMaeglerKontaktEmail");
1032 Custom.Integration.Brokers.Models.BrokerEmployee propBroker = Custom.Integration.Brokers.Search.GetEmployee(GetString("Ecom:Product:Field.xButikID"), Employee);
1033 var employeeItem = Dynamicweb.Content.Items.ItemManager.Storage.GetById(propBroker?.Employee?.ItemType, propBroker?.Employee?.ItemId);
1034 var brokerItem = Dynamicweb.Content.Items.ItemManager.Storage.GetById(propBroker?.Broker?.ItemType, propBroker?.Broker?.ItemId);
1035
1036 var popularityMetrics = Custom.Tracking.Providers.TrackingProvider.GetPopularityMetrics(productId);
1037
1038 bool isValidForGreenMobility = false;
1039
1040 if (settingsActivateGreenMobility)
1041 {
1042 var settingsGreenMobilityPostalCodes = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItems("Green_Mobility_Postnumre");
1043 int postalCode = GetInteger("Ecom:Product:Field.xEjendomAdressePostnummer");
1044
1045 isValidForGreenMobility = settingsGreenMobilityPostalCodes.Any(range =>
1046 {
1047 int start = Convert.ToInt32(range.GetRawValue("Start"));
1048 int end = Convert.ToInt32(range.GetValue("Slut"));
1049
1050 return end > 0 ? postalCode >= start && postalCode <= end : postalCode == start;
1051 });
1052 }
1053
1054 Dictionary<string, string> edhFiles = RealMaeglerne.Library.BoligManager.GetEDHFilesCompact(product);
1055
1056 var origin = $"{Context.Current.Session["DP"]}Boligvisning (sektion: galleri)";
1057
1058 }
1059
1060 <script>
1061 // Set RMAPI (defined in master) values relevant for this page
1062 if(RMAPI) {
1063 RMAPI.ButikId = "@GetString("Ecom:Product:Field.xButikID")";
1064 RMAPI.Boligvisning = true;
1065 RMAPI.SagsNr = "@productId";
1066 RMAPI.MarkerColor = "#F06F18";
1067 }
1068 </script>
1069
1070 <div propertypage-top role="main" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.PropertyMain", "Ejendomsvisning hovedindhold"))">
1071 @*SECTION: Breadcrumbs*@
1072
1073 <nav class="container breadcrumbs" role="navigation" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.Breadcrumb", "Brødkrumme navigation"))">
1074 <div class="divider-blue d-none d-md-block" aria-hidden="true"></div>
1075 <div class="row py-md-3 py-2">
1076 <div class="col-6">
1077 @{
1078 int searchPageId = GetPageSettingsPageId("Boligside");
1079 if (searchPageId == 0)
1080 {
1081 searchPageId = GetWebsiteSettingsPageId("Boligside");
1082 }
1083 }
1084 <a href="/Default.aspx?ID=@searchPageId" class="breadcrumb-item" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.BackToSearch", "Tilbage til boligsøgning"))">
1085 @Translate("Custom:Propertypage.Breadcrumbs.Search", "Søg bolig")
1086 </a>
1087 @if (propBroker != null)
1088 {
1089 <a href="/Default.aspx?ID=@searchPageId&search=@propBroker.Broker.City" class="breadcrumb-item" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.SearchInCity", "Søg boliger i")) @propBroker.Broker.City">
1090 @propBroker.Broker.City
1091 </a>
1092 }
1093 </div>
1094 <div class="col-6 text-right">
1095 <a class="breadcrumb-link cursor-pointer" data-share-text="@Translate("Custom:Propertypage.Sharelink.ShareText", "Se denne bolig")" data-alert-text="@Translate("Custom:Propertypage.Sharelink.AlertText", "Link kopieret til udklipsholder!")" onclick="shareProperty(event, this)" role="button" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ShareProperty", "Del denne bolig"))" onkeypress="if(event.key === 'Enter' || event.key === ' ') shareProperty(event, this)">
1096 <img class="d-md-none d-inline mr-1" src="@(iconPath + "icon-share.svg")" alt="" aria-hidden="true" />
1097 <img class="d-none d-md-inline mr-1" src="@(iconPath + "icon-share-desktop.svg")" alt="" aria-hidden="true" />
1098 @Translate("Custom:Propertypage.Breadcrumbs.Share", "Del bolig")
1099 </a>
1100 </div>
1101 </div>
1102 <div class="divider-blue d-none d-md-block" aria-hidden="true"></div>
1103 </nav>
1104
1105 @*SECTION: Images*@
1106 @{
1107 var boligManager = new RealMaeglerne.Library.BoligManager(Pageview);
1108 RealMaeglerne.Library.Models.Bolig bolig = boligManager.CreateBolig(product, true);
1109
1110
1111 bool useEsoftImages = settingsItem != null ? Converter.ToBoolean(settingsItem["SpUseEsoftImages"]) : false;
1112 bool hasVideos = bolig.Videos != null && bolig.Videos.Any();
1113 bool hasSlideShow = bolig.EsoftAssets != null && bolig.EsoftAssets.HasSlideShows;
1114 bool hasBlueprints = bolig.Plantegninger != null && bolig.Plantegninger.Any();
1115 var panoramas = bolig.EsoftAssets?.PanoramasHtml5?
1116 .Where(x => Converter.ToInt32(x.ListOrder) > 0 && x.EmbedAssets?.Count > 0)
1117 .ToList() ?? new List<Custom.Esoft.Models.EsoftAssetContainer>();
1118 bool hasPanorama = panoramas.Any();
1119
1120 string mapLng = GetString("Ecom:Product:Field.xEjendomGeoinfoWGS84Y.Value.Raw").Replace(",", ".");
1121 string mapLat = GetString("Ecom:Product:Field.xEjendomGeoinfoWGS84X.Value.Raw").Replace(",", ".");
1122 bool hasMapCoordinates = !string.IsNullOrEmpty(mapLng) && !string.IsNullOrEmpty(mapLat);
1123
1124
1125 List<Bolig.CaseAsset> images = bolig.ImagesOfProperty;
1126
1127 var primaryImage = images.First();
1128 images = images.Skip(1).ToList();
1129
1130
1131 string primaryVideo = string.Empty;
1132
1133 if (hasVideos)
1134 {
1135 primaryVideo = bolig.Videos.First();
1136 }
1137 }
1138
1139 <section class="container image-section pt-3 pb-3" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ImageGallery", "Billedegalleri"))">
1140
1141 <div class="image-wrapper position-relative h-100 w-100">
1142 <div class="main-image position-relative">
1143 @if (!string.IsNullOrEmpty(primaryVideo))
1144 {
1145 <video width="100%" height="auto" autoplay="autoplay" muted loop preload="auto" poster="@primaryImage.ImageMd" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.PropertyVideo", "Ejendomsvideo for")) @GetString("Ecom:Product:Field.xEjendomAdresseAdresseLinie")">
1146 <source src="@primaryVideo" type="video/mp4" />
1147 @Translate("Custom:Accessibility.VideoNotSupported", "Din browser understøtter ikke HTML5 video.")
1148 </video>
1149 }
1150 else
1151 {
1152 <img class="img-fluid w-100" src="@primaryImage.ImageLg" alt="@Translate("Custom.Propertypage.PrimaryImage.AltTag", "Image of realestate")" />
1153 }
1154 </div>
1155
1156 @{
1157 var imageCount = 0;
1158 }
1159
1160 @foreach (var image in images.Take(2))
1161 {
1162 <div class="secondary-image position-relative" data-toggle="modal" data-target="#assets-modal" role="button" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.OpenImageGallery", "Åbn billedegalleri"))" onkeypress="if(event.key === 'Enter' || event.key === ' ') { $(this).click(); }">
1163 <img class="img-fluid w-100 h-100" src="@image.ImageLg" alt="@Translate("Custom:Accessibility.PropertyImage", "Ejendomsbillede") @(imageCount + 2) @Translate("Custom:Accessibility.Of", "af") @(images.Count() + 1)" />
1164 @if (imageCount == 1)
1165 {
1166 <button type="button" class="d-block d-lg-none btn btn-modal position-absolute" data-toggle="modal" data-target="#assets-modal" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ViewAllImages", "Vis alle billeder"))">
1167 @string.Format(Translate("Custom:Propertypage.AssetsModal.Button.Mobile.Open", "+ {0} billeder"), images.Count())
1168 </button>
1169
1170 <button type="button" class="d-none d-md-block btn btn-modal position-absolute" data-toggle="modal" data-target="#assets-modal" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ViewAllImages", "Vis alle billeder"))">
1171 <img src="@(iconPath + "icon-images.svg")" alt="" aria-hidden="true" />
1172 @string.Format(Translate("Custom:Propertypage.AssetsModal.Button.Desktop.Open", "Se alle {0} billeder"), images.Count())
1173 </button>
1174 }
1175 @if (bolig.AabentHus && imageCount == 0)
1176 {
1177 var upcomingOpenHouses = boligManager.KommendeAabnehuse(bolig);
1178
1179 <div class="open-house position-absolute d-none d-md-flex" onclick="stopPropagation(event)" role="region" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.OpenHouseInfo", "Åbent hus information"))">
1180 <div class="section-header semi-bold mb-0">
1181 @Translate("Custom.Propertypage.OpenHouseSection.Header", "Åbent hus")
1182 </div>
1183 <div class="open-house-dates d-flex align-items-center">
1184 @if (upcomingOpenHouses.Count() > 1)
1185 {
1186 <select id="openhouse-selector-desktop" class="open-house-selector js-aabenthus-liste-val" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.SelectOpenHouse", "Vælg åbent hus tidspunkt"))">
1187 @foreach (var openHouse in upcomingOpenHouses)
1188 {
1189 var json = System.Text.Json.JsonSerializer.Serialize(openHouse);
1190
1191 <option class="open-house-selector__option" data-aabent-hus="@Dynamicweb.Core.Encoders.HtmlEncoder.HtmlAttributeEncode(json)">
1192 @openHouse.Dato.ToString("d. MMM", Pageview.Area.CultureInfo) kl. @openHouse.FraKlokken.Substring(0, 5)
1193 </option>
1194 }
1195 </select>
1196 }
1197 else
1198 {
1199 var primaryOpenHouse = upcomingOpenHouses.First();
1200 var json = System.Text.Json.JsonSerializer.Serialize(primaryOpenHouse);
1201
1202 <div class="open-house-text">
1203 <span class="js-aabenthus-date-val">@primaryOpenHouse.Dato.ToString("d. MMM", Pageview.Area.CultureInfo)</span>
1204
1205 @if (!string.IsNullOrEmpty(primaryOpenHouse.TidspunktFormateret))
1206 {
1207 <div class="d-inline-block js-aabenthus-time-val js-primary-open-house" data-aabent-hus="@Dynamicweb.Core.Encoders.HtmlEncoder.HtmlAttributeEncode(json)">
1208 @Translate("Custom.Propertypage.OpenHouseSection.Kl", "kl.") @primaryOpenHouse.FraKlokken.Substring(0, 5)@(" - ")@primaryOpenHouse.TilKlokken.Substring(0, 5)
1209 </div>
1210 }
1211 </div>
1212 }
1213 @if (upcomingOpenHouses.Any(oh => oh.Tilmelding))
1214 {
1215 <a class="btn btn-orange" href="javascript:panelAabenthus('@origin');">
1216 @Translate("Custom.Propertypage.OpenHouseSection.SignupButton.Label", "Tilmeld")
1217 </a>
1218 }
1219 </div>
1220 </div>
1221 }
1222 @if (popularityMetrics.Any() && imageCount == 0)
1223 {
1224 <div class="popular position-absolute d-none d-md-flex" role="region" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.PopularityMetrics", "Popularitetsmålinger"))">
1225 <div class="popular-header">
1226 @Translate("Custom.Propertypage.PopularSection.Header", "Populær")
1227 </div>
1228 <div class="popular-metrics-wrapper js-popular-metrics-wrapper">
1229 @foreach (var metric in popularityMetrics)
1230 {
1231
1232 <div class="popular-metric d-inline-flex align-items-center">
1233 <div class="bold">@metric.Value</div>
1234 <div class="popular-metric-label">@Translate($"Custom.Propertypage.PopularSection.{metric.Key}.Label", "har interageret med denne bolig")</div>
1235 </div>
1236 }
1237 </div>
1238 </div>
1239 }
1240 </div>
1241 imageCount++;
1242 }
1243
1244 </div>
1245 <div class="image-wrapper__subtext d-md-block d-none">
1246 @if (propBroker != null)
1247 {
1248 <span>@Translate("Custom:Propertypage.Images.Subtext.Label", "Har du nogle spørgsmål?")</span>
1249 <span class="font-weight-normal">@Translate("Custom:Propertypage.Images.Subtext.Text", "Vi er klar til at hjælpe på telefon")</span>
1250 <span class="font-weight-normal">@(!string.IsNullOrEmpty(propBroker.Employee?.PhoneMobile) ? propBroker.Employee.PhoneMobile : propBroker.Broker.Telephone)</span>
1251 }
1252
1253 </div>
1254
1255
1256 <div class="modal fade images-modal" id="images-modal" tabindex="-1" aria-labelledby="images-modal-label" aria-hidden="true" aria-modal="true">
1257 <div class="modal-dialog">
1258 <div class="modal-content">
1259 <div class="position-absolute d-flex flex-column images-navigation">
1260 <button type="button" class="close-round mb-5" data-dismiss="modal" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.CloseModal", "Luk vindue"))">
1261 <img src="@(iconPath + "icon-minimize.svg")" alt="" aria-hidden="true" />
1262 </button>
1263 <div class="d-flex flex-column">
1264 <button id="image-prev-images-modal" type="button" class="close-round mb-2" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.PreviousImage", "Forrige billede"))">
1265 <img src="@(iconPath + "icon-arrow-narrow-up.svg")" alt="" aria-hidden="true" />
1266 </button>
1267 <button id="image-next-images-modal" type="button" class="close-round" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.NextImage", "Næste billede"))">
1268 <img src="@(iconPath + "icon-arrow-narrow-down.svg")" alt="" aria-hidden="true" />
1269 </button>
1270 </div>
1271 </div>
1272 <div class="image-gallery large-images">
1273 @{
1274 int largeImageCounter = 0;
1275 }
1276
1277 @foreach (var image in images)
1278 {
1279 var largeImageId = "image_large_" + largeImageCounter;
1280 <img id="@largeImageId" class="img-fluid" src="@fallbackImage" data-src="@image.ImageXl" />
1281 largeImageCounter++;
1282 }
1283 </div>
1284 </div>
1285 </div>
1286 </div>
1287
1288 <div class="modal fade" id="assets-modal" tabindex="-1" aria-labelledby="assets-modal-label" aria-hidden="true" aria-modal="true" role="dialog">
1289 <div class="modal-dialog">
1290 <div class="modal-content h-100 mh-100">
1291
1292 @if (hasVideos || hasSlideShow)
1293 {
1294 <input type="radio" id="video" name="category" class="category-radio" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.SelectVideoCategory", "Vælg video kategori"))">
1295 }
1296
1297 <input type="radio" id="images" name="category" class="category-radio" checked aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.SelectImagesCategory", "Vælg billeder kategori"))">
1298
1299 @if (hasBlueprints)
1300 {
1301 <input type="radio" id="blueprint" name="category" class="category-radio" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.SelectBlueprintCategory", "Vælg plantegning kategori"))">
1302 }
1303
1304 @if (hasMapCoordinates)
1305 {
1306 <input type="radio" id="mapradio" name="category" class="category-radio" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.SelectMapCategory", "Vælg kort kategori"))">
1307 }
1308
1309 @if (hasPanorama)
1310 {
1311 <input type="radio" id="view360" name="category" class="category-radio" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.Select360Category", "Vælg 360 graders visning kategori"))">
1312 }
1313
1314 <div class="modal-header">
1315
1316 <div class="nav-wrapper">
1317 <div class="category-scroll">
1318 <div class="category-buttons">
1319 @if (hasVideos || hasSlideShow)
1320 {
1321 <label for="video" class="category-btn" tabindex="0" role="button" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ShowVideoContent", "Vis video indhold"))" onkeypress="if(event.key === 'Enter' || event.key === ' ') { document.getElementById('video').click(); }">
1322 <span class="category-icon icon-video" aria-hidden="true"></span>
1323 <span>@Translate("Custom.Propertypage.AssetsModal.Category.Video", "Video")</span>
1324 </label>
1325 }
1326
1327 <label for="images" class="category-btn" tabindex="0" role="button" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ShowImagesContent", "Vis billeder"))" onkeypress="if(event.key === 'Enter' || event.key === ' ') { document.getElementById('images').click(); }">
1328 <span class="category-icon icon-image" aria-hidden="true"></span>
1329 <span>@Translate("Custom.Propertypage.AssetsModal.Category.Images", "Billeder")</span>
1330 </label>
1331
1332 @if (hasBlueprints)
1333 {
1334 <label for="blueprint" class="category-btn" tabindex="0" role="button" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ShowBlueprintContent", "Vis plantegning"))" onkeypress="if(event.key === 'Enter' || event.key === ' ') { document.getElementById('blueprint').click(); }">
1335 <span class="category-icon icon-plan" aria-hidden="true"></span>
1336 <span>@Translate("Custom.Propertypage.AssetsModal.Category.Plan", "Plantegning")</span>
1337 </label>
1338 }
1339
1340 @if (hasMapCoordinates)
1341 {
1342 <label for="mapradio" class="js-init-map category-btn" tabindex="0" role="button" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ShowMapContent", "Vis kort"))" onkeypress="if(event.key === 'Enter' || event.key === ' ') { document.getElementById('mapradio').click(); }">
1343 <span class="category-icon icon-map" aria-hidden="true"></span>
1344 <span>@Translate("Custom.Propertypage.AssetsModal.Category.Map", "Vis på kort")</span>
1345 </label>
1346 }
1347
1348 @if (hasPanorama)
1349 {
1350 <label for="view360" class="category-btn" tabindex="0" role="button" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.Show360Content", "Vis 360 graders visning"))" onkeypress="if(event.key === 'Enter' || event.key === ' ') { document.getElementById('view360').click(); }">
1351 <span class="category-icon icon-360" aria-hidden="true"></span>
1352 <span>@Translate("Custom.Propertypage.AssetsModal.Category.Panorama", "360°")</span>
1353 </label>
1354 }
1355 </div>
1356 <div class="d-none d-md-block">
1357 <a class="btn btn-orange" href="javascript:panelFremvisning('@origin');" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.BookViewing", "Bestil fremvisning"))">@Translate("Custom.Propertypage.AssetsModal.Header.Showing.ButtonLabel", "Bestil fremvisning")</a>
1358 </div>
1359 </div>
1360 </div>
1361 <button type="button" class="close" data-dismiss="modal" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.CloseAssetModal", "Luk medie vindue"))">
1362 @*Mobile*@
1363 <div class="d-md-none d-block" aria-hidden="true">
1364 <img src="@(iconPath + "icon-modal-close.svg")" alt="" aria-hidden="true" />
1365 </div>
1366 <div class="d-md-none d-block pb-2" aria-hidden="true">@Translate("Custom:Propertypage.AssetsModal.Button.Close.Mobile", "Luk")</div>
1367 @*Desktop*@
1368 <div class="d-none d-md-block pb-2" aria-hidden="true">@Translate("Custom:Propertypage.AssetsModal.Button.Close.Desktop", "Luk vindue")</div>
1369 <div class="d-none d-md-block" aria-hidden="true">
1370 <img src="@(iconPath + "icon-modal-close-small.svg")" alt="" aria-hidden="true" />
1371 </div>
1372 </button>
1373 </div>
1374 <div class="modal-body">
1375 <!-- Video Content -->
1376 @if (hasVideos || hasSlideShow)
1377 {
1378 <div class="content-section video-content">
1379 <div class="image-gallery">
1380 @foreach (var video in bolig.Videos)
1381 {
1382 <video width="100%" controls="controls" muted loop preload="auto">
1383 <source src="@video" type="video/mp4" />
1384 Your browser does not support HTML5 video.
1385 </video>
1386 }
1387 @foreach (var slide in bolig.EsoftAssets.ActiveSlideShows)
1388 {
1389 <div class="slide-show">@slide.EmbedAssets[0].EmbedCode.Replace("http://", "https://")</div>
1390 }
1391 </div>
1392 </div>
1393 }
1394
1395 <!-- Billeder (Images) Content -->
1396 <div class="content-section images-content">
1397 <div class="image-gallery">
1398 @{
1399 int imageCounter = 0;
1400 }
1401
1402 @foreach (var image in images)
1403 {
1404 var imageId = "image_" + imageCounter;
1405 <img id="@imageId" class="img-fluid" src="@fallbackImage" data-src="@image.ImageLg" />
1406 imageCounter++;
1407 }
1408 </div>
1409 <div class="d-md-flex d-none flex-column">
1410 <button type="button" class="btn btn-modal btn-modal__clean" data-toggle="modal" data-target="#images-modal" onclick="initImageNavigation('.images-modal', { imageSelector: '.large-images img', buttonIdPostFix: '-images-modal' })">
1411 <div class="pb-2" aria-hidden="true">@Translate("Custom:Propertypage.AssetsModal.Button.LargeImages", "Vis som store billeder")</div>
1412 <div aria-hidden="true">
1413 <img src="@(iconPath + "icon-expand.svg")" alt="" aria-hidden="true" />
1414 </div>
1415 </button>
1416 <div class="image-thumbnails">
1417 @{
1418 int imageThumbnailCounter = 0;
1419 }
1420
1421 @foreach (var image in images)
1422 {
1423 var imageId = "image_" + imageThumbnailCounter;
1424 <label class="thumbnail-radio" onclick="scrollToElementById('@imageId');">
1425 <input type="radio" id="@(imageId)_thumbnail" name="thumbnailradio" class="d-none" checked="@(imageThumbnailCounter == 0)" />
1426 <img class="img-fluid" src="@fallbackImage" data-src="@image.ImageSm" />
1427 </label>
1428
1429 imageThumbnailCounter++;
1430 }
1431 </div>
1432 </div>
1433 </div>
1434
1435 <!-- Plantegning (Floor Plan) Content -->
1436 @if (hasBlueprints)
1437 {
1438 <div class="content-section blueprint-content">
1439 <div class="image-gallery">
1440 @foreach (var plan in bolig.Plantegninger)
1441 {
1442 <img class="img-fluid" src="@fallbackImage" data-src="@plan.ImageXl" />
1443 }
1444 </div>
1445 </div>
1446 }
1447
1448 <!-- Kort (Map) Content -->
1449 @if (hasMapCoordinates)
1450 {
1451 var mapFeedPageId = Converter.ToString(GetPageIdByNavigationTag("MapFeed"));
1452 string mapMarkerUrl = "Files/Templates/Designs/rm/assets/images/map-pin-real-maeglerne.svg";
1453 int mapMarkerHeight = 32;
1454 int mapMarkerWidth = 32;
1455
1456 <div class="content-section map-content">
1457 <div class="image-gallery">
1458 <div class="map js-map" data-map-feed="@mapFeedPageId">
1459 <div class="renderMap" id="map"></div>
1460 </div>
1461 </div>
1462 </div>
1463
1464 <input type="hidden" class="js-hasmapcoordinates" value="true" />
1465 <input type="hidden" class="js-mapLng" value="@mapLng" />
1466 <input type="hidden" class="js-mapLat" value="@mapLat" />
1467 <input type="hidden" class="js-mapMarkerWidth" value="@mapMarkerWidth" />
1468 <input type="hidden" class="js-mapMarkerHeight" value="@mapMarkerHeight" />
1469 <input type="hidden" class="js-mapMarkerUrl" value="@mapMarkerUrl" />
1470
1471 <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.4/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==" crossorigin="" />
1472 <script src="https://unpkg.com/leaflet@1.3.4/dist/leaflet.js" integrity="sha512-nMMmRyTVoLYqjP9hrbed9S+FzjZHW5gY1TWCHA5ckwXZBadntCNs8kEqAWdrb9O7rxbCaA4lKTIWjDXZxflOcA==" crossorigin="">
1473 </script>
1474
1475 }
1476
1477 <!-- 360 View Content -->
1478 @if (hasPanorama)
1479 {
1480 <div class="content-section view360-content">
1481 <div class="image-gallery">
1482 @{
1483 string largeThumbnail = string.Empty;
1484
1485 foreach (var thumbnail in panoramas.First().Assets)
1486 {
1487 if (thumbnail.Width == "1920")
1488 {
1489 largeThumbnail = thumbnail.SecureUrl;
1490 }
1491 }
1492 <div class="panorama">
1493 <div class="renderMap position-relative">
1494 <img class="panorama-thumbnail" src="@largeThumbnail" />
1495 <div class="js-clickme clickme">
1496 <img src="@(iconPath + "icon-360.svg")" />
1497 <span>@Translate("Custom.Propertypage.AssetsModal.ShowPanorama", "Vis 360°")</span>
1498 </div>
1499 <span class="js-panorama-encoded" style="display:none">@Dynamicweb.Core.Encoders.HtmlEncoder.HtmlEncode(panoramas.First().EmbedAssets[0].EmbedCode.Replace("http://", "https://"))</span>
1500 </div>
1501 </div>
1502 }
1503 </div>
1504 </div>
1505 }
1506 </div>
1507 </div>
1508 </div>
1509 </div>
1510 </section>
1511 </div>
1512
1513 <div propertypage-anchor>
1514 @*SECTION: Subpage Navigation*@
1515 @{
1516 bool homePresentationOn = Converter.ToBoolean(GetString("Ecom:Product:Field.SpHomePresentationOn"));
1517 bool inspiireON = Converter.ToBoolean(GetString("Ecom:Product:Field.SPInspiireON"));
1518 }
1519 <section class="container subpage-navigation pb-0" role="navigation" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.PropertyNavigation", "Ejendomsnavigation"))">
1520 <div class="subpage-links">
1521 @if (hasVideos || hasSlideShow)
1522 {
1523 <label for="video" role="button" class="subpage-link cursor-pointer d-none d-md-flex order-md-0 order-8" data-toggle="modal" data-target="#assets-modal" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ViewVideo", "Se video"))" onkeypress="if(event.key === 'Enter' || event.key === ' ') { $(this).click(); }">
1524 <img src="@(iconPath + "icon-video.svg")" alt="" aria-hidden="true" />
1525 <span>@Translate("Custom.Propertypage.SubpageLink.Video", "Video")</span>
1526 </label>
1527 }
1528
1529 @if (images.Any())
1530 {
1531 <label for="images" role="button" class="subpage-link cursor-pointer d-none d-md-flex order-md-1 order-9" data-toggle="modal" data-target="#assets-modal" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ViewImages", "Se billeder"))" onkeypress="if(event.key === 'Enter' || event.key === ' ') { $(this).click(); }">
1532 <img src="@(iconPath + "icon-images.svg")" alt="" aria-hidden="true" />
1533 <span>@Translate("Custom.Propertypage.SubpageLink.Images", "Billeder")</span>
1534 </label>
1535 }
1536
1537 <a class="subpage-link d-flex d-md-none order-2 order-md-2" onclick="scrollToElementById('information-section')" role="button" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ViewPropertyFacts", "Se boligfakta"))" onkeypress="if(event.key === 'Enter' || event.key === ' ') scrollToElementById('information-section')">
1538 <img src="@(iconPath + "icon-house.svg")" alt="" aria-hidden="true" />
1539 <span>@Translate("Custom.Propertypage.SubpageLink.Information", "Boligfakta")</span>
1540 </a>
1541
1542 @if (hasBlueprints)
1543 {
1544 <label for="blueprint" role="button" class="subpage-link cursor-pointer order-md-3 order-0" data-toggle="modal" data-target="#assets-modal" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ViewBlueprint", "Se plantegning"))" onkeypress="if(event.key === 'Enter' || event.key === ' ') { $(this).click(); }">
1545 <img src="@(iconPath + "icon-blueprint.svg")" alt="" aria-hidden="true" />
1546 <span>@Translate("Custom.Propertypage.SubpageLink.Blueprint", "Plantegning")</span>
1547 </label>
1548 }
1549
1550 @if (hasMapCoordinates)
1551 {
1552 <label for="mapradio" role="button" class="subpage-link cursor-pointer js-init-map order-1 order-md-4" data-toggle="modal" data-target="#assets-modal" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ViewMap", "Se kort"))" onkeypress="if(event.key === 'Enter' || event.key === ' ') { $(this).click(); }">
1553 <img src="@(iconPath + "icon-map.svg")" alt="" aria-hidden="true" />
1554 <span>@Translate("Custom.Propertypage.SubpageLink.Map", "Kort")</span>
1555 </label>
1556 }
1557
1558 @if (hasPanorama)
1559 {
1560 <label for="view360" role="button" class="subpage-link cursor-pointer order-3 order-md-5" data-toggle="modal" data-target="#assets-modal" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.View360", "Se 360 graders visning"))" onkeypress="if(event.key === 'Enter' || event.key === ' ') { $(this).click(); }">
1561 <img src="@(iconPath + "icon-360.svg")" alt="" aria-hidden="true" />
1562 <span>@Translate("Custom.Propertypage.SubpageLink.360view", "360°")</span>
1563 </label>
1564 }
1565
1566 @if (homePresentationOn)
1567 {
1568 string homePresentationLink = GetString("Ecom:Product:Field.SpHomePresentationLink");
1569
1570 @if (!string.IsNullOrEmpty(homePresentationLink))
1571 {
1572 <a class="subpage-link order-4 order-md-6" href="@homePresentationLink" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ViewPresentation", "Se boligpræsentation"))">
1573 <img src="@(iconPath + "icon-presentation.svg")" alt="" aria-hidden="true" />
1574 <span>@Translate("Custom.Propertypage.SubpageLink.Presentation", "Boligpræsentation")</span>
1575 </a>
1576 }
1577 }
1578 else if (inspiireON)
1579 {
1580 string inspiireLink = GetString("Ecom:Product:Field.SPInspiireLink");
1581
1582 @if (!string.IsNullOrEmpty(inspiireLink))
1583 {
1584 <a class="subpage-link order-4 order-md-6" href="@inspiireLink" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ViewInspiire", "Se Inspiire præsentation"))">
1585 <img src="@(iconPath + "icon-presentation.svg")" alt="" aria-hidden="true" />
1586 <span>@Translate("Custom.Propertypage.SubpageLink.Inspiire", "Inspiire")</span>
1587 </a>
1588 }
1589 }
1590 </div>
1591 <div class="broker-card d-none d-md-flex align-items-center" role="complementary" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.BrokerInfo", "Mæglerinformation"))">
1592 @if (employeeItem != null)
1593 {
1594 string image = Converter.ToString(employeeItem["BilledeUrl"]);
1595 <img src="@image" alt="@Translate("Custom:Accessibility.BrokerImage", "Billede af mægler") @propBroker.Employee.Name" />
1596 }
1597 <div class="d-flex flex-column justify-content-around">
1598 @if (!string.IsNullOrEmpty(propBroker?.Employee?.Name))
1599 {
1600 <div class="bold">@propBroker.Employee.Name</div>
1601 }
1602 else if (!string.IsNullOrEmpty(propBroker?.Broker?.Name))
1603 {
1604 <div class="bold">@propBroker.Broker.Name</div>
1605 }
1606 @if (!string.IsNullOrEmpty(propBroker?.Employee?.JobTitle))
1607 {
1608 <div class="regular">@propBroker.Employee.JobTitle</div>
1609 }
1610 else if (!string.IsNullOrEmpty(propBroker?.Broker?.JobTitle))
1611 {
1612 <div class="regular">@propBroker.Broker.JobTitle</div>
1613 }
1614 @if (!string.IsNullOrEmpty(propBroker?.Employee?.PhoneMobile) && Converter.ToBoolean(employeeItem["VisMobilNrPaaSager"]))
1615 {
1616 <div class="regular">@Translate("Custom.Propertypage.BrokerCard.Call", "Ring på")<span class="pl-1">@RealMaeglerne.Library.Helper.FormatPhoneNumber(propBroker.Employee.PhoneMobile)</span></div>
1617 }
1618 else if (!string.IsNullOrEmpty(propBroker?.Broker?.Telephone))
1619 {
1620 <div class="regular">@Translate("Custom.Propertypage.BrokerCard.Call", "Ring på")<span class="pl-1">@RealMaeglerne.Library.Helper.FormatPhoneNumber(propBroker.Broker.Telephone)</span></div>
1621 }
1622 </div>
1623 <div class="divider-blue__vertical mx-4" aria-hidden="true"></div>
1624 <div class="broker-interactions" aria-hidden="true">
1625 <a class="btn btn-orange" aria-hidden="true" href="javascript:panelFremvisning('@origin');">@Translate("Custom.Propertypage.AssetsModal.Header.Showing.ButtonLabel", "Bestil fremvisning")</a>
1626 </div>
1627 </div>
1628 @*SECTION: Open house/Popular section*@
1629 @if (bolig.AabentHus || popularityMetrics.Any())
1630 {
1631 <section class="container open-house-popular-section p-0 pt-3 d-block d-md-none">
1632 <div class="open-house-popular-wrapper">
1633 @if (bolig.AabentHus)
1634 {
1635 var upcomingOpenHouses = boligManager.KommendeAabnehuse(bolig);
1636
1637 <div class="open-house w-50 @(!popularityMetrics.Any() ? "w-100" : "")">
1638 <h2 class="section-header section-header-md semi-bold mb-0">
1639 @Translate("Custom.Propertypage.OpenHouseSection.Header", "Åbent hus")
1640 </h2>
1641 <div class="open-house-dates">
1642 @if (upcomingOpenHouses.Count() > 1)
1643 {
1644 <select id="openhouse-selector-mobile" class="open-house-selector js-aabenthus-liste-val">
1645 @foreach (var openHouse in upcomingOpenHouses)
1646 {
1647 var json = System.Text.Json.JsonSerializer.Serialize(openHouse);
1648
1649 <option class="open-house-selector__option" data-aabent-hus="@Dynamicweb.Core.Encoders.HtmlEncoder.HtmlAttributeEncode(json)">
1650 @openHouse.Dato.ToString("d. MMM", Pageview.Area.CultureInfo) kl. @openHouse.FraKlokken.Substring(0, 5)
1651 </option>
1652 }
1653 </select>
1654 }
1655 else
1656 {
1657 var primaryOpenHouse = upcomingOpenHouses.First();
1658 var json = System.Text.Json.JsonSerializer.Serialize(primaryOpenHouse);
1659
1660 <div class="open-house-text">
1661 <span class="js-aabenthus-date-val">@primaryOpenHouse.Dato.ToString("d. MMM", Pageview.Area.CultureInfo)</span>
1662
1663 @if (!string.IsNullOrEmpty(primaryOpenHouse.TidspunktFormateret))
1664 {
1665 <div class="d-inline-block js-aabenthus-time-val js-primary-open-house" data-aabent-hus="@Dynamicweb.Core.Encoders.HtmlEncoder.HtmlAttributeEncode(json)">
1666 @Translate("Custom.Propertypage.OpenHouseSection.Kl", "kl.") @primaryOpenHouse.FraKlokken.Substring(0, 5)@(" - ")@primaryOpenHouse.TilKlokken.Substring(0, 5)
1667 </div>
1668 }
1669 </div>
1670 }
1671 </div>
1672 @if (upcomingOpenHouses.Any(oh => oh.Tilmelding))
1673 {
1674 <a class="btn btn-orange" href="javascript:panelAabenthus('@origin');" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.SignUpOpenHouse", "Tilmeld til åbent hus"))">
1675 @Translate("Custom.Propertypage.OpenHouseSection.SignupButton.Label", "Tilmeld")
1676 </a>
1677 }
1678 </div>
1679 }
1680 @if (popularityMetrics.Any())
1681 {
1682 <div class="popular w-50 @(!bolig.AabentHus ? "w-100" : "")">
1683 <div class="section-header section-header-md semi-bold mb-0">
1684 @Translate("Custom.Propertypage.PopularSection.Header", "Populær")
1685 </div>
1686 <div class="divider-orange ml-auto mr-auto"></div>
1687 <div class="popular-metrics-wrapper">
1688 @foreach (var metric in popularityMetrics)
1689 {
1690 <div class="popular-metric d-flex flex-column align-items-center justify-content-between">
1691 <div class="bold">@metric.Value</div>
1692 <div>@Translate($"Custom.Propertypage.PopularSection.{metric.Key}.Label", "har interageret med denne bolig")</div>
1693 </div>
1694 }
1695 </div>
1696 </div>
1697 }
1698 </div>
1699 </section>
1700 }
1701
1702 @*SECTION: ADDRESS SECTION*@
1703 <section class="container address-section p-0 pt-3 pb-3" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.AddressSection", "Adresse og pris information"))">
1704 <div class="address-wrapper">
1705 <h2 class="address-header d-flex align-items-center justify-content-between w-100 order-0">
1706 <div class="d-flex flex-column">
1707 <div class="js-aabenthus-address-val">@GetString("Ecom:Product:Field.xEjendomAdresseAdresseLinie")</div>
1708 <div class="js-aabenthus-zip-city-val">@GetString("Ecom:Product:Field.xEjendomAdressePostAdresseLinie")</div>
1709 </div>
1710 @{
1711 var (cssColor, translationKey, defaultText) = bolig switch
1712 {
1713 { Solgt: true, UdbudsForm: "Leje" } => ("red", "Custom.Propertypage.Leased", "Udlejet"),
1714 { Solgt: true } => ("red", "Custom.Propertypage.Sold", "Solgt"),
1715 { PurchaseAgreementSigned: true } => ("blue", "Custom.Propertypage.PurchaseAgreementSigned", "Købsaftale underskrevet"),
1716 { Nyhed: true } => ("orange", "Custom.Propertypage.New", "Nyhed"),
1717 { NyPris: true } => ("orange", "Custom.Propertypage.NewPrice", "Ny pris"),
1718 _ => (null, null, null)
1719 };
1720
1721 if (translationKey != null)
1722 {
1723 <div class="label" role="status" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.PropertyStatus", "Ejendomsstatus"))"><div class="label-icon @cssColor" aria-hidden="true"></div>@Translate(translationKey, defaultText)</div>
1724 }
1725 }
1726 </h2>
1727 <div class="divider-orange d-none d-md-block" aria-hidden="true"></div>
1728 <div class="address-price d-none d-md-flex flex-column w-100">
1729 @if (bolig.Solgt || bolig.PurchaseAgreementSigned)
1730 {
1731 //Do Nothing
1732 }
1733 else
1734 {
1735 @if (isRental)
1736 {
1737 <div class="d-flex align-items-center justify-content-between">
1738 <div>@Translate("Custom.Propertypage.Financing.RentPerMonth", "Leje pr. måned")</div>
1739 <div>@FormatPrice(GetInteger("Ecom:Product:Field.xEjendomBoligUdlejningLejeMaaned.Value.Clean"))</div>
1740 </div>
1741
1742 int usagePerMonth = GetInteger("Ecom:Product:Field.xEjendomBoligUdlejningAcVarmeMaaned.Value.Clean") + GetInteger("Ecom:Product:Field.xEjendomBoligUdlejningAcVandMaaned.Value.Clean") + GetInteger("Ecom:Product:Field.xEjendomBoligUdlejningAcontoForbrugFri01Beloeb.Value.Clean");
1743
1744 if (usagePerMonth > 0)
1745 {
1746 <div class="d-flex align-items-center justify-content-between address-price-small">
1747 <div>@Translate("Custom.Propertypage.Financing.UsagePerMonth", "Forbrugsudgift pr. md.")</div>
1748 <div>@FormatPrice(usagePerMonth)</div>
1749 </div>
1750 }
1751 }
1752 else
1753 {
1754 <div class="d-flex align-items-center justify-content-between">
1755 @if (propCategory == "Andelsbolig")
1756 {
1757 <div>@Translate("Custom.Propertypage.Financing.Table.Deposit", "Indskud")</div>
1758 }
1759 else
1760 {
1761 <div>@Translate("Custom.Propertypage.Financing.Table.Price", "Kontantpris")</div>
1762 }
1763 <div>@FormatPrice(GetInteger("Ecom:Product.DBPrice"))</div>
1764 </div>
1765 <div class="d-flex align-items-center justify-content-between address-price-small">
1766 <div>@Translate("Custom.Propertypage.Financing.Table.OwnerCost", "Ejerudgift")</div>
1767 <div>@FormatPrice(GetInteger("Ecom:Product:Field.xEjendomEjerudgifterMaanedSum"))</div>
1768 </div>
1769 }
1770 }
1771 </div>
1772 <div class="address-info d-flex flex-wrap d-md-none align-items-center order-1">
1773 @if (!string.IsNullOrEmpty(propTypeDisplay))
1774 {
1775 <div class="address-info-item">
1776 @propTypeDisplay
1777 </div>
1778 }
1779 @if (GetInteger("Ecom:Product:Field.xEjendomArealerBoligAreal") > 0)
1780 {
1781 <div class="address-info-item">
1782 @GetString("Ecom:Product:Field.xEjendomArealerBoligAreal") @Translate("Custom.Propertypage.Units.SquareMeters", "m²")
1783 </div>
1784 }
1785 @if (bolig.Solgt || bolig.PurchaseAgreementSigned)
1786 {
1787 //Do Nothing
1788 }
1789 else
1790 {
1791 <div class="address-info-item">
1792 @if (isRental)
1793 {
1794 @GetInteger("Ecom:Product:Field.xEjendomBoligUdlejningLejeMaaned.Value.Clean").ToString("#,##0") @Translate("Custom.Propertypage.RentPerMonth", "pr. md.")
1795 }
1796 else
1797 {
1798 @FormatPrice(GetInteger("Ecom:Product.DBPrice"), true)
1799 }
1800 </div>
1801 }
1802 @if (!string.IsNullOrEmpty(GetString("Ecom:Product:Field.xEjendomEnergiklassifikation")) || !isRental)
1803 {
1804 <div class="address-info-item d-flex align-items-center">
1805
1806 @{
1807 var scenarioNumber = GetString("Ecom:Product:Field.EnergyLabelScenarioNumber");
1808 var savings = GetInteger("Ecom:Product:Field.EnergyLabelSavings");
1809 var energyLink = GetString("Ecom:Product:Field.EnergyLabelLink");
1810 }
1811
1812 <div @(scenarioNumber == "3" ? "id='energi-kontrol-address-mobile'" : "")>
1813 @Translate("Custom.Propertypage.Information.Energy", "Energimærke")
1814 </div>
1815
1816 <div class="energylabel @(scenarioNumber == "2" ? "energy__hover" : "")"
1817 data-energylabel="@HtmlEncoder.HtmlAttributeEncode(GetString("Ecom:Product:Field.xEjendomEnergiklassifikation"))">
1818 @if (scenarioNumber == "2")
1819 {
1820 <span id="energi-testgruppe-address-mobile" class="tooltiptext">
1821 @if (savings > 0)
1822 {
1823 @string.Format(Translate("Smartpage:Boligvisning.Energimærketekst1-1", "OBS: du kan spare {0} årligt ved at renovere denne bolig - {1}"), savings.ToString("#,##0"), "")
1824 <a target="_blank" href="@(energyLink)&utm_source=realmaeglerne&utm_medium=energimaerke&utm_campaign=testgruppe1">@Translate("Custom.Propertypage.EnergyLabel.Tooltip.Linktext", "klik her")</a>
1825 }
1826 else
1827 {
1828 @string.Format(Translate("Smartpage:Boligvisning.Energimærketekst1-2", "OBS: du kan energi renovere denne bolig {0}"), "")
1829 <a target="_blank" href="@(energyLink)&utm_source=realmaeglerne&utm_medium=energimaerke&utm_campaign=testgruppe1">@Translate("Custom.Propertypage.EnergyLabel.Tooltip.Linktext", "klik her")</a>
1830 }
1831 </span>
1832 }
1833 </div>
1834 </div>
1835 }
1836 </div>
1837 @if (bolig.BudOenskes)
1838 {
1839 <div class="divider-blue order-2" aria-hidden="true"></div>
1840 <div class="address-offer d-flex align-items-center order-3">
1841 <div>
1842 @Translate("Custom.Propertypage.Address.Offerlink.label", "Har du et bud i tankerne?")
1843 </div>
1844 <a class="btn-link" onclick="scrollToElementById('offer-section', 'center')" role="button" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.MakeOffer", "Gå til bud sektion"))" onkeypress="if(event.key === 'Enter' || event.key === ' ') scrollToElementById('offer-section', 'center')">@Translate("Custom.Propertypage.Address.Offerlink.linktext", "Giv et bud")</a>
1845 <img height="12px" width="12px" src="@(iconPath + "icon-arrow-narrow-down-white.svg")" alt="" aria-hidden="true" />
1846 </div>
1847 <div class="divider-blue order-4" aria-hidden="true"></div>
1848 }
1849
1850 @if (bolig.Solgt || bolig.PurchaseAgreementSigned)
1851 {
1852 <div class="w-100 btn btn-light order-5 cursor-default">
1853 @Translate(translationKey, defaultText)
1854 </div>
1855 }
1856 else
1857 {
1858 <a class="btn btn-orange w-100 order-6" href="javascript:panelFremvisning('@origin');" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.BookViewing", "Bestil fremvisning"))">
1859 @Translate("Custom.Propertypage.AssetsModal.Header.Showing.ButtonLabel", "Bestil fremvisning")
1860 </a>
1861
1862 <div class="d-flex align-items-center justify-content-between flex-wrap order-7">
1863 @if (edhFiles.Any())
1864 {
1865 <a class="btn btn-link text-left d-flex align-items-center" href="javascript:panelSalgsopstilling('@origin');" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.DownloadDocuments", "Hent salgsdokumenter"))">@Translate("form-salgsopstilling-downloadbtn", "Hent salgsdokumenter") <img class="pl-1" src="@(iconPath + "icon-download-white.svg")" alt="" aria-hidden="true" /></a>
1866 }
1867
1868 <a class="btn btn-link text-left d-flex align-items-center" onclick="scrollToElementById('finance-section', 'center')" role="button" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ViewFinance", "Se økonomi og lån"))" onkeypress="if(event.key === 'Enter' || event.key === ' ') scrollToElementById('finance-section', 'center')">@Translate("Custom.Propertypage.Address.Financelink.linktext", "Økonomi & lån")<img height="12px" width="12px" src="@(iconPath + "icon-arrow-narrow-down-white.svg")" alt="" aria-hidden="true" /></a>
1869 </div>
1870 }
1871 </div>
1872 <div class="address-info d-none d-md-flex">
1873 @if (!string.IsNullOrEmpty(propTypeDisplay))
1874 {
1875 <div class="address-info-item d-flex align-items-center justify-content-between">
1876 <div>
1877 @Translate("Custom.Propertypage.Address.PropertyType", "Type")
1878 </div>
1879 <div>
1880 @propTypeDisplay
1881 </div>
1882 </div>
1883 }
1884 @if (GetInteger("Ecom:Product:Field.xEjendomArealerBoligAreal") > 0)
1885 {
1886 <div class="address-info-item d-flex align-items-center justify-content-between">
1887 <div>
1888 @Translate("Custom.Propertypage.Address.PropertyArea", "Boligareal")
1889 </div>
1890 <div>
1891 @GetString("Ecom:Product:Field.xEjendomArealerBoligAreal") @Translate("Custom.Propertypage.Units.SquareMeters", "m²")
1892 </div>
1893 </div>
1894 }
1895 @if (GetInteger("Ecom:Product:Field.xEjendomArealerVaerelser") != 0)
1896 {
1897 <div class="address-info-item d-md-flex justify-content-between">
1898 <div>@Translate("Custom.Propertypage.Address.Rooms", "Rum")</div>
1899 <div>@GetString("Ecom:Product:Field.xEjendomArealerVaerelser")</div>
1900 </div>
1901 }
1902 @if (!string.IsNullOrEmpty(GetString("Ecom:Product:Field.xEjendomEnergiklassifikation")) || !isRental)
1903 {
1904 <div class="address-info-item d-flex justify-content-between align-items-center">
1905 @{
1906 var scenarioNumber = GetString("Ecom:Product:Field.EnergyLabelScenarioNumber");
1907 var savings = GetInteger("Ecom:Product:Field.EnergyLabelSavings");
1908 var energyLink = GetString("Ecom:Product:Field.EnergyLabelLink");
1909 }
1910
1911 <div @(scenarioNumber == "3" ? "id='energi-kontrol-address-desktop'" : "")>
1912 @Translate("Custom.Propertypage.Information.Energy", "Energimærke")
1913 </div>
1914
1915 <div class="energylabel @(scenarioNumber == "2" ? "energy__hover" : "")"
1916 data-energylabel="@HtmlEncoder.HtmlAttributeEncode(GetString("Ecom:Product:Field.xEjendomEnergiklassifikation"))">
1917 @if (scenarioNumber == "2")
1918 {
1919 <span id="energi-testgruppe-address-desktop" class="tooltiptext">
1920 @if (savings > 0)
1921 {
1922 @string.Format(Translate("Smartpage:Boligvisning.Energimærketekst1-1", "OBS: du kan spare {0} årligt ved at renovere denne bolig - {1}"), savings.ToString("#,##0"), "")
1923 <a target="_blank" href="@(energyLink)&utm_source=realmaeglerne&utm_medium=energimaerke&utm_campaign=testgruppe1">@Translate("Custom.Propertypage.EnergyLabel.Tooltip.Linktext", "klik her")</a>
1924 }
1925 else
1926 {
1927 @string.Format(Translate("Smartpage:Boligvisning.Energimærketekst1-2", "OBS: du kan energi renovere denne bolig {0}"), "")
1928 <a target="_blank" href="@(energyLink)&utm_source=realmaeglerne&utm_medium=energimaerke&utm_campaign=testgruppe1">@Translate("Custom.Propertypage.EnergyLabel.Tooltip.Linktext", "klik her")</a>
1929 }
1930 </span>
1931 }
1932 </div>
1933 </div>
1934 }
1935 <div class="d-flex align-items-center">
1936 <a class="btn-link cursor-pointer" onclick="scrollToElementById('information-section', 'center')" role="button" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ViewAllFacts", "Vis alle fakta om boligen"))" onkeypress="if(event.key === 'Enter' || event.key === ' ') scrollToElementById('information-section', 'center')">@Translate("Custom.Propertypage.Address.InfoLink.linktext", "Vis alle fakta om boligen")</a>
1937 <img class="ml-1" height="12px" width="12px" src="@(iconPath + "icon-arrow-narrow-down.svg")" alt="" aria-hidden="true" />
1938 </div>
1939 </div>
1940 </section>
1941 </section>
1942 </div>
1943
1944 <div propertypage-light>
1945
1946 @*SECTION USPs TODO*@
1947 @{
1948 bool hasUSPs = false;
1949 }
1950 @if (hasUSPs)
1951 {
1952 <section class="container usp-section">
1953 <div class="usps d-flex position-relative">
1954 <button id="image-prev-usps" type="button" class="prev-button btn-round d-none d-md-flex" aria-label="@HtmlEncoder.HtmlAttributeEncode(@Translate("Custom:Accessiblity.UpsBtn.Previous","Forrige"))">
1955 </button>
1956 <button id="image-next-usps" type="button" class="next-button btn-round d-none d-md-flex" aria-label="@HtmlEncoder.HtmlAttributeEncode(@Translate("Custom:Accessiblity.UpsBtn.Next","Næste"))">
1957 </button>
1958 <h2 class="usps-header d-flex flex-column align-items-start justify-content-center">
1959 <div class="usps-header-number">
1960 6
1961 </div>
1962 <div class="usps-header-text d-block d-md-none">
1963 @Translate("Custom.Propertypage.USPSection.Header.Mobile", "gode grunde til at købe")
1964 </div>
1965 <div class="usps-header-text d-none d-md-block">
1966 @Translate("Custom.Propertypage.USPSection.Header.Desktop", "gode grunde til at købe denne bolig")
1967 </div>
1968 <div class="divider-orange d-none d-md-block"></div>
1969 </h2>
1970 <div class="usps-wrapper d-flex">
1971 <div class="usps-items d-flex">
1972 <div class="usp-item d-flex flex-column">
1973 <div class="circle-orange">
1974 <img src="@(iconPath + "icon-check-small.svg")" />
1975 </div>
1976 <div class="usp-text">
1977 Her får du et trygt fundament for familien med både god plads og et roligt nabolag.
1978 </div>
1979 </div>
1980 <div class="divider-blue__vertical"></div>
1981 <div class="usp-item d-flex flex-column">
1982 <div class="circle-orange">
1983 <img src="@(iconPath + "icon-check-small.svg")" />
1984 </div>
1985 <div class="usp-text">
1986 Du får en bolig med lavt energiforbrug, hvilket både gavner økonomien og miljøet. Lorem ipsum dolor est.
1987 </div>
1988 </div>
1989 <div class="divider-blue__vertical"></div>
1990 <div class="usp-item d-flex flex-column">
1991 <div class="circle-orange">
1992 <img src="@(iconPath + "icon-check-small.svg")" />
1993 </div>
1994 <div class="usp-text">
1995 Dette hjem har de detaljer, som mange købere efterspørger – lys og luft.
1996 </div>
1997 </div>
1998 <div class="divider-blue__vertical"></div>
1999 <div class="usp-item d-flex flex-column">
2000 <div class="circle-orange">
2001 <img src="@(iconPath + "icon-check-small.svg")" />
2002 </div>
2003 <div class="usp-text">
2004 Her får du et trygt fundament for familien med både god plads og et roligt nabolag.
2005 </div>
2006 </div>
2007 <div class="divider-blue__vertical"></div>
2008 <div class="usp-item d-flex flex-column">
2009 <div class="circle-orange">
2010 <img src="@(iconPath + "icon-check-small.svg")" />
2011 </div>
2012 <div class="usp-text">
2013 Du får en bolig med lavt energiforbrug, hvilket både gavner økonomien og miljøet. Lorem ipsum dolor est.
2014 </div>
2015 </div>
2016 <div class="divider-blue__vertical"></div>
2017 <div class="usp-item d-flex flex-column">
2018 <div class="circle-orange">
2019 <img src="@(iconPath + "icon-check-small.svg")" />
2020 </div>
2021 <div class="usp-text">
2022 Dette hjem har de detaljer, som mange købere efterspørger – lys og luft.
2023 </div>
2024 </div>
2025 </div>
2026 </div>
2027 </div>
2028 </section>
2029 }
2030 @*SECTION: Description*@
2031 <section id="description-section" class="container description-section" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.PropertyDescription", "Ejendomsbeskrivelse"))">
2032 <div class="description js-description">
2033 @{
2034 string shortDesc = GetString("Ecom:Product.ShortDescription.Raw");
2035 string longDesc = GetString("Ecom:Product.LongDescription");
2036
2037 // Replace uplifted numbers with markup (the characters doesn't exist in the current font)
2038 shortDesc = shortDesc.Replace("²", "<sup>2</sup>").Replace("³", "<sup>3</sup>");
2039 longDesc = longDesc.Replace("²", "<sup>2</sup>").Replace("³", "<sup>3</sup>");
2040 }
2041
2042 <h2 class="display-sm semi-bold m-0">@shortDesc</h2>
2043
2044 @if (longDesc.Length > 300)
2045 {
2046 <div class="text-wrapper">
2047 <div class="text-full @(hasUSPs ? "has-buying-reasons" : "")">
2048 @longDesc
2049 </div>
2050 <button class="read-more btn--clean" type="button" role="button" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ReadMoreText", "Læs hele beskrivelsen"))" aria-expanded="false">@Translate("product-read-more", "Læs hele teksten")<img src="@(iconPath + "plus.svg")" alt="" aria-hidden="true" /></button>
2051 <button class="read-less d-none" type="button" role="button" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ReadLessText", "Skjul noget af beskrivelsen"))" aria-expanded="true">@Translate("product-read-less", "Læs mindre")<img src="@(iconPath + "minus.svg")" alt="" aria-hidden="true" /></button>
2052 </div>
2053 }
2054 else
2055 {
2056 <div>@longDesc</div>
2057 }
2058 </div>
2059
2060 </section>
2061 @*SECTION: BLueprints*@
2062 @if (hasBlueprints)
2063 {
2064 <section class="container blueprint-section">
2065 <div class="blueprints position-relative">
2066 <h2 class="section-header semi-bold">@Translate("Custom.Propertypage.Blueprints.Header", "Plantegning")</h2>
2067 <div class="divider-orange mb-3 mb-md-5"></div>
2068 <div class="blueprints-wrapper">
2069 @foreach (var blueprint in bolig.Plantegninger)
2070 {
2071 <img class="blueprint img-fluid" src="@blueprint.ImageLg" />
2072 }
2073 </div>
2074 <button id="image-prev-blueprints" type="button" class="prev-button btn-round mb-2 d-none d-md-flex" aria-label="@HtmlEncoder.HtmlAttributeEncode(@Translate("Custom:Accessiblity.BlueprintsBtn.Previous","Forrige"))">
2075 </button>
2076 <button id="image-next-blueprints" type="button" class="next-button btn-round d-none d-md-flex" aria-label="@HtmlEncoder.HtmlAttributeEncode(@Translate("Custom:Accessiblity.BlueprintsBtn.Next","Næste"))">
2077 </button>
2078 </div>
2079 </section>
2080 }
2081
2082 @if (hasMapCoordinates)
2083 {
2084 <section class="container map-mobile-section d-md-none d-block js-init-map-onload" data-map-container="map-mobile" data-map-pois="false">
2085 <h2 class="section-header semi-bold">@Translate("Custom.Propertypage.MobileMap.Header", "Kort")</h2>
2086 <div class="divider-orange mb-3" aria-hidden="true"></div>
2087 <div id="map-mobile" class="map-mobile">
2088 <button type="button" class="btn btn-link" onclick="fullScreen('map-mobile')" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ToggleFullscreen", "Skift til fuldskærm"))" tabindex="0" onkeypress="if(event.key === 'Enter' || event.key === ' ') fullScreen('map-mobile')">
2089 <div class="pb-2">@Translate("Custom:Propertypage.MobileMap.Button.FullScreen", "Fuld skærm")</div>
2090 <div>
2091 <img src="@(iconPath + "icon-expand.svg")" alt="" aria-hidden="true" />
2092 </div>
2093 </button>
2094 <div class="map h-100 w-100 js-map" data-map-feed="@Converter.ToString(GetPageIdByNavigationTag("MapFeed"))" role="application" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.InteractiveMap", "Interaktivt kort"))">
2095 <div class="renderMap" id="map-mobile"></div>
2096 </div>
2097 </div>
2098 </section>
2099 }
2100
2101 @*SECTION: Broker mobile*@
2102 <section class="container broker-mobile d-block d-md-none">
2103 <div class="broker-card d-flex align-items-center">
2104 <div class="broker-info">
2105 @if (employeeItem != null)
2106 {
2107 string image = Converter.ToString(employeeItem["BilledeUrl"]);
2108 <img src="@image" />
2109 }
2110 <div class="d-flex flex-column justify-content-around">
2111 @if (!string.IsNullOrEmpty(propBroker?.Employee?.Name))
2112 {
2113 <div class="bold">@propBroker.Employee.Name</div>
2114 }
2115 else if (!string.IsNullOrEmpty(propBroker?.Broker?.Name))
2116 {
2117 <div class="bold">@propBroker.Broker.Name</div>
2118 }
2119 @if (!string.IsNullOrEmpty(propBroker?.Employee?.JobTitle))
2120 {
2121 <div class="regular">@propBroker.Employee.JobTitle</div>
2122 }
2123 else if (!string.IsNullOrEmpty(propBroker?.Broker?.JobTitle))
2124 {
2125 <div class="regular">@propBroker.Broker.JobTitle</div>
2126 }
2127 </div>
2128 </div>
2129 <div class="broker-interactions">
2130 <a class="btn btn-orange" href="javascript:panelFremvisning('@origin');">@Translate("Custom.Propertypage.AssetsModal.Header.Showing.ButtonLabel", "Bestil fremvisning")</a>
2131 @if (!string.IsNullOrEmpty(propBroker?.Employee?.PhoneMobile) && Converter.ToBoolean(employeeItem["VisMobilNrPaaSager"]))
2132 {
2133 <div class="regular">@Translate("Custom.Propertypage.BrokerCard.Call", "Ring på")<a href="tel:@RealMaeglerne.Library.Helper.FormatPhoneNumber(propBroker.Employee.PhoneMobile)" class="phone-link pl-1">@RealMaeglerne.Library.Helper.FormatPhoneNumber(propBroker.Employee.PhoneMobile)</a></div>
2134 }
2135 else if (!string.IsNullOrEmpty(propBroker?.Broker?.Telephone))
2136 {
2137 <div class="regular">@Translate("Custom.Propertypage.BrokerCard.Call", "Ring på")<a href="tel:@RealMaeglerne.Library.Helper.FormatPhoneNumber(propBroker.Broker.Telephone)" class="phone-link pl-1">@RealMaeglerne.Library.Helper.FormatPhoneNumber(propBroker.Broker.Telephone)</a></div>
2138 }
2139 </div>
2140 </div>
2141 </section>
2142
2143 @*SECTION: Information*@
2144 <section id="information-section" class="container information-section" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.PropertyFactsSection", "Fakta om boligen"))">
2145 @{
2146 int garageArea = GetInteger("Ecom:Product:Field.xEjendomArealerHovedbygningIntegreredeArealerGarage");
2147 int carportArea = GetInteger("Ecom:Product:Field.xEjendomArealerHovedbygningIntegreredeArealerCarport.Value");
2148 bool altan = GetBoolean("Ecom:Product:Field.xEjendomFaciliteterAltan");
2149 }
2150 <div class="information">
2151 <h2 class="information-header semi-bold">@Translate("Custom.Propertypage.Information.Header", "Fakta om boligen")</h2>
2152 <div class="d-none d-md-block divider-orange mb-4" aria-hidden="true"></div>
2153 <div class="table-wrapper" role="table" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.PropertyFactsTable", "Boligfakta tabel"))">
2154 <div class="table-item d-flex justify-content-between" role="row">
2155 <div role="cell">@Translate("Custom.Propertypage.Information.Case", "Sagsnummer")</div>
2156 <div role="cell" class="js-sagsnr-val" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.CaseNumber", "Sagsnummer")) @productId">@productId</div>
2157 </div>
2158 @if (!string.IsNullOrEmpty(propTypeDisplay))
2159 {
2160 <div class="table-item d-flex justify-content-between" role="row">
2161 <div role="cell">@Translate("Custom.Propertypage.Information.PropertyType", "Boligtype")</div>
2162 <div role="cell" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.PropertyType", "Boligtype")) @propTypeDisplay">@propTypeDisplay</div>
2163 </div>
2164 }
2165 @if (GetInteger("Ecom:Product:Field.xEjendomArealerBoligAreal") > 0)
2166 {
2167 <div class="table-item d-flex justify-content-between" role="row">
2168 <div role="cell">@Translate("Custom.Propertypage.Information.Residentialrea", "Boligareal")</div>
2169 <div role="cell" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ResidentialArea", "Boligareal")) @GetString("Ecom:Product:Field.xEjendomArealerBoligAreal") @HtmlEncoder.HtmlAttributeEncode(Translate("Custom.Propertypage.Units.SquareMeters", "kvadratmeter"))">@GetString("Ecom:Product:Field.xEjendomArealerBoligAreal") @Translate("Custom.Propertypage.Units.SquareMeters", "m²")</div>
2170 </div>
2171 }
2172 @if (GetInteger("Ecom:Product:Field.xEjendomArealerGrundAreal") > 0)
2173 {
2174 <div class="table-item d-flex justify-content-between" role="row">
2175 <div role="cell">@Translate("Custom.Propertypage.Information.Landarea", "Grundareal")</div>
2176 <div role="cell" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.LandArea", "Grundareal")) @GetString("Ecom:Product:Field.xEjendomArealerGrundAreal") @HtmlEncoder.HtmlAttributeEncode(Translate("Custom.Propertypage.Units.SquareMeters", "kvadratmeter"))">@GetString("Ecom:Product:Field.xEjendomArealerGrundAreal") @Translate("Custom.Propertypage.Units.SquareMeters", "m²")</div>
2177 </div>
2178 }
2179 else if (GetInteger("Ecom:Product:Field.xEjendomArealerGrundArealHA") > 0)
2180 {
2181 <div class="table-item d-flex justify-content-between" role="row">
2182 <div role="cell">@Translate("Custom.Propertypage.Information.Landarea", "Grundareal")</div>
2183 <div role="cell" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.LandArea", "Grundareal")) @GetString("Ecom:Product:Field.xEjendomArealerGrundArealHA") @HtmlEncoder.HtmlAttributeEncode(Translate("Custom.Propertypage.Units.Acres", "hektar"))">@GetString("Ecom:Product:Field.xEjendomArealerGrundArealHA") @Translate("Custom.Propertypage.Units.Acres", "hektar")</div>
2184 </div>
2185 }
2186
2187
2188 @if (garageArea > 0 || carportArea > 0)
2189 {
2190 if (garageArea > 0 && carportArea > 0)
2191 {
2192 <div class="table-item d-flex justify-content-between">
2193 <div>@Translate("Custom.Propertypage.Information.GarageCarport", "Garage/Carport")</div>
2194 <div>@garageArea/@carportArea @Translate("Custom.Propertypage.Units.SquareMeters", "m²")</div>
2195 </div>
2196 }
2197 else if (garageArea > 0 && carportArea <= 0)
2198 {
2199 <div class="table-item d-flex justify-content-between">
2200 <div>@Translate("Custom.Propertypage.Information.Garage", "Garage")</div>
2201 <div>@garageArea @Translate("Custom.Propertypage.Units.SquareMeters", "m²")</div>
2202 </div>
2203 }
2204 else
2205 {
2206 <div class="table-item d-flex justify-content-between">
2207 <div>@Translate("Custom.Propertypage.Information.Carport", "Carport")</div>
2208 <div>@carportArea @Translate("Custom.Propertypage.Units.SquareMeters", "m²")</div>
2209 </div>
2210 }
2211 }
2212 @if (altan)
2213 {
2214 <div class="table-item d-flex justify-content-between" role="row">
2215 <div role="cell">@Translate("Custom.Propertypage.Information.Balkony", "Altan")</div>
2216 <div role="cell" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.Balcony", "Altan")) @HtmlEncoder.HtmlAttributeEncode(Translate("Custom.Propertypage.Information.Yes", "Ja"))">@Translate("Custom.Propertypage.Information.Yes", "Ja")</div>
2217 </div>
2218 }
2219 @if (GetInteger("Ecom:Product:Field.xEjendomOpfoertAar") != 0)
2220 {
2221 <div class="table-item d-flex justify-content-between" role="row">
2222 <div role="cell">@Translate("Custom.Propertypage.Information.BuildRebuild", "Bygget/ombygget")</div>
2223 <div role="cell" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.BuildYear", "Byggeår")) @GetInteger("Ecom:Product:Field.xEjendomOpfoertAar") @(GetInteger("Ecom:Product:Field.xEjendomOmbyggetAar") != 0 ? HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.RebuildYear", "Ombygget")) + " " + GetString("Ecom:Product:Field.xEjendomOmbyggetAar") : "")">@GetInteger("Ecom:Product:Field.xEjendomOpfoertAar") @(GetInteger("Ecom:Product:Field.xEjendomOmbyggetAar") != 0 ? "/ " + GetString("Ecom:Product:Field.xEjendomOmbyggetAar") : "")</div>
2224 </div>
2225 }
2226 @if (GetInteger("Ecom:Product:Field.xEjendomArealerVaerelser") != 0)
2227 {
2228 <div class="table-item d-flex justify-content-between" role="row">
2229 <div role="cell">@Translate("Custom.Propertypage.Information.Rooms", "Antal rum")</div>
2230 <div role="cell" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.NumberOfRooms", "Antal rum")) @GetString("Ecom:Product:Field.xEjendomArealerVaerelser")">@GetString("Ecom:Product:Field.xEjendomArealerVaerelser")</div>
2231 </div>
2232 }
2233 @if (GetInteger("Ecom:Product:Field.xEjendomArealerEtager") != 0 && (propType != "Ejerlejlighed" && propType != "Andelsbolig"))
2234 {
2235 <div class="table-item d-flex justify-content-between" role="row">
2236 <div role="cell">@Translate("Custom.Propertypage.Information.Stories", "Etager")</div>
2237 <div role="cell" tabindex="0" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.NumberOfFloors", "Antal etager")) @GetString("Ecom:Product:Field.xEjendomArealerEtager")">@GetString("Ecom:Product:Field.xEjendomArealerEtager")</div>
2238 </div>
2239 }
2240 @if (!string.IsNullOrEmpty(GetString("Ecom:Product:Field.xEjendomEnergiklassifikation")))
2241 {
2242 <div class="table-item d-flex justify-content-between align-items-center">
2243 @{
2244 var scenarioNumber = GetString("Ecom:Product:Field.EnergyLabelScenarioNumber");
2245 var savings = GetInteger("Ecom:Product:Field.EnergyLabelSavings");
2246 var energyLink = GetString("Ecom:Product:Field.EnergyLabelLink");
2247 }
2248
2249 <div @(scenarioNumber == "3" ? "id='energi-kontrol-information'" : "")>
2250 @Translate("Custom.Propertypage.Information.Energy", "Energimærke")
2251 </div>
2252
2253 <div class="energylabel @(scenarioNumber == "2" ? "energy__hover" : "")"
2254 data-energylabel="@HtmlEncoder.HtmlAttributeEncode(GetString("Ecom:Product:Field.xEjendomEnergiklassifikation"))">
2255 @if (scenarioNumber == "2")
2256 {
2257 <span id="energi-testgruppe-information" class="tooltiptext">
2258 @if (savings > 0)
2259 {
2260 @string.Format(Translate("Smartpage:Boligvisning.Energimærketekst1-1", "OBS: du kan spare {0} årligt ved at renovere denne bolig - {1}"), savings.ToString("#,##0"), "")
2261 <a target="_blank" href="@(energyLink)&utm_source=realmaeglerne&utm_medium=energimaerke&utm_campaign=testgruppe1">@Translate("Custom.Propertypage.EnergyLabel.Tooltip.Linktext", "klik her")</a>
2262 }
2263 else
2264 {
2265 @string.Format(Translate("Smartpage:Boligvisning.Energimærketekst1-2", "OBS: du kan energi renovere denne bolig {0}"), "")
2266 <a target="_blank" href="@(energyLink)&utm_source=realmaeglerne&utm_medium=energimaerke&utm_campaign=testgruppe1">@Translate("Custom.Propertypage.EnergyLabel.Tooltip.Linktext", "klik her")</a>
2267 }
2268 </span>
2269 }
2270 </div>
2271 </div>
2272 }
2273 </div>
2274 @if (edhFiles.Any())
2275 {
2276 <div class="table-item">
2277 <a class="btn btn-link text-left d-flex align-items-center" href="javascript:panelSalgsopstilling('@origin');" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.DownloadSalesDocuments", "Hent salgsdokumenter"))" tabindex="0">@Translate("form-salgsopstilling-downloadbtn", "Hent salgsdokumenter") <img class="pl-1" src="@(iconPath + "icon-download.svg")" alt="" aria-hidden="true" /></a>
2278 </div>
2279 }
2280 </div>
2281 </section>
2282 @*SECTION: Finance*@
2283 @if (!bolig.Solgt)
2284 {
2285
2286 string status = GetString("Ecom:Product:Field.xStatus");
2287 string statusCode = !string.IsNullOrEmpty(status) ? status.Substring(0, 1).ToUpper() : "";
2288
2289 string brfQuery = $"price={GetInteger("Ecom:Product.DBPrice")}";
2290
2291 if (propCategory != null)
2292 {
2293 if (propCategory.Contains("Ejerlejlighed", StringComparison.InvariantCultureIgnoreCase))
2294 {
2295 brfQuery += "&housingType=ejerlejlighed";
2296 }
2297 else if (propCategory.Contains("Villa", StringComparison.InvariantCultureIgnoreCase) ||
2298 propCategory.Contains("Boliglandbrug", StringComparison.InvariantCultureIgnoreCase))
2299 {
2300 brfQuery += "&housingType=parcelhus";
2301 }
2302 }
2303
2304 brfQuery += "&partnerID=REM100";
2305
2306
2307 <section id="finance-section" class="container financing-section">
2308 <div class="financing d-flex flex-column flex-md-row">
2309 <div class="financing-bank d-flex flex-column justify-content-center">
2310 <img src="@(imagePath + "Jyske_Bank_logo1.png")" class="img-fluid logo" />
2311 <h2 class="section-header mb-0">
2312 @Translate("Custom.Propertypage.Financing.Bank.Header", "Find den finansiering, der passer dig. Få din drømmebolig til at blive virkelighed")
2313 </h2>
2314 <div class="d-none d-md-block divider-orange mb-4"></div>
2315 <div>
2316 @Translate("Custom.Propertypage.Financing.Bank.SubHeader", "Med en hurtig online vurdering kender du bedre dine muligheder")
2317 </div>
2318 @if (propCategory == "Andelsbolig")
2319 {
2320 <a href="https://www.jyskebank.dk/bolig/boliglaan/andelsbolig" target="_blank" id="gtm-brf" class="btn btn-light">@Translate("Smartpage:Boligvisning.CalculatorContact", "Kontakt Jyske Bank")</a>
2321 }
2322 else
2323 {
2324 <a href="https://www.jyskebank.dk/bolig/regn-paa-bolig/beregn-laan-til-ny-bolig?@(brfQuery)" target="_blank" id="gtm-brf" class="btn btn-light w-100">@Translate("Smartpage:Boligvisning.CalculatorLink", "Hvor meget kan jeg købe for?")<img src="@(iconPath + "icon-link-external.svg")" /></a>
2325 }
2326 </div>
2327 <div class="financing-table d-flex flex-column">
2328 <div class="section-header semi-bold mb-0">
2329 @Translate("Custom.Propertypage.Financing.Table.Header", "Økonomi og boliglån")
2330 </div>
2331 <div class="d-none d-md-block divider-orange mb-4"></div>
2332 <div class="table-wrapper w-100">
2333 @if (isRental)
2334 {
2335 <div class="table-item d-flex justify-content-between">
2336 <div>@Translate("Custom.Propertypage.Financing.RentPerMonth", "Leje pr. måned")</div>
2337 <div>@FormatPrice(GetInteger("Ecom:Product:Field.xEjendomBoligUdlejningLejeMaaned.Value.Clean"))</div>
2338 </div>
2339
2340 int usagePerMonth = GetInteger("Ecom:Product:Field.xEjendomBoligUdlejningAcVarmeMaaned.Value.Clean") + GetInteger("Ecom:Product:Field.xEjendomBoligUdlejningAcVandMaaned.Value.Clean") + GetInteger("Ecom:Product:Field.xEjendomBoligUdlejningAcontoForbrugFri01Beloeb.Value.Clean");
2341
2342 if (usagePerMonth > 0)
2343 {
2344 <div class="table-item d-flex justify-content-between">
2345 <div>@Translate("Custom.Propertypage.Financing.UsagePerMonth", "Forbrugsudgift pr. md.")</div>
2346 <div>@FormatPrice(usagePerMonth)</div>
2347 </div>
2348 }
2349
2350 if (GetInteger("Ecom:Product:Field.xEjendomBoligUdlejningAcVarmeMaaned.Value.Clean") > 0)
2351 {
2352 <div class="table-item d-flex justify-content-between">
2353 <div>@Translate("Custom.Propertypage.Financing.AcontoHeat", "Aconto varme pr. md.")</div>
2354 <div>@FormatPrice(GetInteger("Ecom:Product:Field.xEjendomBoligUdlejningAcVarmeMaaned.Value.Clean"))</div>
2355 </div>
2356 }
2357
2358 if (GetInteger("Ecom:Product:Field.xEjendomBoligUdlejningAcVandMaaned.Value.Clean") > 0)
2359 {
2360 <div class="table-item d-flex justify-content-between">
2361 <div>@Translate("Custom.Propertypage.Financing.AcontoWater", "Aconto vand pr. md.")</div>
2362 <div>@FormatPrice(GetInteger("Ecom:Product:Field.xEjendomBoligUdlejningAcVandMaaned.Value.Clean"))</div>
2363 </div>
2364 }
2365
2366 if (GetInteger("Ecom:Product:Field.xEjendomBoligUdlejningDepositum") > 0)
2367 {
2368 <div class="table-item d-flex justify-content-between">
2369 <div>@Translate("Custom.Propertypage.Financing.Deposit", "Depositum")</div>
2370 <div>@FormatPrice(GetInteger("Ecom:Product:Field.xEjendomBoligUdlejningDepositum"))</div>
2371 </div>
2372 }
2373
2374 if (GetInteger("Ecom:Product:Field.xEjendomBoligUdlejningForudbetaltLeje") > 0)
2375 {
2376 <div class="table-item d-flex justify-content-between">
2377 <div>@Translate("Custom.Propertypage.Financing.Prepayment", "Forudbetalt leje")</div>
2378 <div>@FormatPrice(GetInteger("Ecom:Product:Field.xEjendomBoligUdlejningForudbetaltLeje"))</div>
2379 </div>
2380 }
2381 }
2382 else
2383 {
2384 <div class="table-item d-flex justify-content-between">
2385 @if (propCategory == "Andelsbolig")
2386 {
2387 <div>@Translate("Custom.Propertypage.Financing.Table.Deposit", "Indskud")</div>
2388 }
2389 else
2390 {
2391 <div>@Translate("Custom.Propertypage.Financing.Table.Price", "Kontantpris")</div>
2392 }
2393 <div>@FormatPrice(GetInteger("Ecom:Product.DBPrice"))</div>
2394 </div>
2395 <div class="table-item d-flex justify-content-between">
2396 <div>@Translate("Custom.Propertypage.Financing.Table.OwnerCost", "Ejerudgift")</div>
2397 <div>@FormatPrice(GetInteger("Ecom:Product:Field.xEjendomEjerudgifterMaanedSum"))</div>
2398 </div>
2399 @if (propCategory != "Andelsbolig")
2400 {
2401 <div class="table-item d-flex justify-content-between">
2402 <div>@Translate("Custom.Propertypage.Financing.Table.Payout", "Udbetaling")</div>
2403 <div>@FormatPrice(GetInteger("Ecom:Product:Field.xFinansieringUdbetaling"))</div>
2404 </div>
2405 }
2406 <div class="table-item d-flex justify-content-between">
2407 <div>@Translate("Custom.Propertypage.Financing.Table.Brutto", "Brutto ekskl. ejerudgift")</div>
2408 <div>@FormatPrice(GetInteger("Ecom:Product:Field.xFinansieringBruttoMaaned"))</div>
2409 </div>
2410 <div class="table-item d-flex justify-content-between">
2411 <div>@Translate("Custom.Propertypage.Financing.Table.Netto", "Netto ekskl. ejerudgift")</div>
2412 <div>@FormatPrice(GetInteger("Ecom:Product:Field.xFinansieringNettoMaaned"))</div>
2413 </div>
2414 }
2415 </div>
2416 </div>
2417 </div>
2418 </section>
2419 }
2420
2421 @*SECTION: Offer*@
2422 @if (bolig.BudOenskes)
2423 {
2424 <section id="offer-section" class="container offer-section">
2425 <div class="offer">
2426 <div class="offer-wrapper d-flex flex-column text-center">
2427 <h2 class="section-header semi-bold">
2428 @Translate("Custom.Propertypage.OfferSection.Header", "Har du et bud i tankerne?")
2429 </h2>
2430 <div class="divider-orange d-none d-md-block mx-auto mb-4"></div>
2431 <div class="offer-text d-block d-md-none">
2432 @Translate("Custom.Propertypage.OfferSection.Text.Mobile", "Jeg vil gerne byde:")
2433 </div>
2434 <div class="offer-container">
2435 <div class="offer-text d-none d-md-block">
2436 @Translate("Custom.Propertypage.OfferSection.Text.Desktop", "Jeg byder")
2437 </div>
2438 <input class="form-control js-input-offer text-right" id="offer-input" type="text" />
2439 <a class="btn btn-orange js-send-offer-to-form" href="javascript:panelMakeAnOffer('@origin');">
2440 @Translate("Custom.Propertypage.OfferSection.Button.Send", "Send bud")
2441 <img height="20px" width="20px" src="@(iconPath + "icon-arrow-right.svg")" />
2442 </a>
2443 </div>
2444 <div class="offer-subtext">
2445 @Translate("Custom.Propertypage.OfferSection.Subtext", "Dit bud er helt uforpligtende")
2446 </div>
2447 </div>
2448 <img class="img-fluid d-none d-md-block" src="@(imagePath + "skriv_din_pris.jpg")" data-fallback="@fallbackImage" onerror="handleImageError(this)" />
2449 </div>
2450 </section>
2451 }
2452
2453 @*SECTION: Map with filter*@
2454 @if (hasMapCoordinates)
2455 {
2456 <section class="container map-filter-section js-init-map-onload" data-map-container="map-filter" data-map-pois="true">
2457 <div class="map-filter-wrapper">
2458 <h2 class="section-header semi-bold">@Translate("Custom.Propertypage.FilterMap.Header", "Hvor finder jeg?")</h2>
2459 <div class="divider-orange mb-3 d-none d-md-block"></div>
2460 <div class="map-filters d-flex flex-wrap">
2461 <label class="mapfilter-btn">
2462 <input type="checkbox" id="shopping" name="mapfilter" class="mapfilter-checkbox" onchange="toggleMapCategory(this.id, this)" checked>
2463 <span>@Translate("Custom.Propertypage.MapFilter.Filter.Shopping", "Indkøb")</span>
2464 </label>
2465 <label class="mapfilter-btn">
2466 <input type="checkbox" id="schools" name="mapfilter" class="mapfilter-checkbox" onchange="toggleMapCategory(this.id, this)" checked>
2467 <span>@Translate("Custom.Propertypage.MapFilter.Filter.Schools", "Dagtilbud")</span>
2468 </label>
2469 <label class="mapfilter-btn">
2470 <input type="checkbox" id="health" name="mapfilter" class="mapfilter-checkbox" onchange="toggleMapCategory(this.id, this)" checked>
2471 <span>@Translate("Custom.Propertypage.MapFilter.Filter.Health", "Helbred")</span>
2472 </label>
2473 <label class="mapfilter-btn">
2474 <input type="checkbox" id="nature" name="mapfilter" class="mapfilter-checkbox" onchange="toggleMapCategory(this.id, this)" checked>
2475 <span>@Translate("Custom.Propertypage.MapFilter.Filter.Nature", "Natur")</span>
2476 </label>
2477 <label class="mapfilter-btn">
2478 <input type="checkbox" id="transportation" name="mapfilter" class="mapfilter-checkbox" onchange="toggleMapCategory(this.id, this)" checked>
2479 <span>@Translate("Custom.Propertypage.MapFilter.Filter.Transportation", "Transport")</span>
2480 </label>
2481 </div>
2482 </div>
2483 <div id="map-filter-container" class="map-filter">
2484 <button type="button" class="btn btn-link" onclick="fullScreen('map-filter-container')">
2485 <div class="pb-2">@Translate("Custom:Propertypage.MobileMap.Button.FullScreen", "Fuld skærm")</div>
2486 <div>
2487 <img src="@(iconPath + "icon-expand.svg")" />
2488 </div>
2489 </button>
2490 <div class="map h-100 w-100 js-map" data-map-feed="@Converter.ToString(GetPageIdByNavigationTag("MapFeed"))">
2491 <div class="renderMap" id="map-filter"></div>
2492 </div>
2493 </div>
2494 </section>
2495 }
2496
2497 @*SECTION: Broker*@
2498 @{
2499 string brokerUrl = "/" + Converter.ToString(brokerItem["CBMedlemsnummer"]).Substring(1);
2500 string brokerAddress = GetFullAddress(propBroker.Broker);
2501 }
2502
2503 @if (employeeItem != null)
2504 {
2505 <input type="hidden" class="js-hasEmployee" value="true" />
2506 <section class="container broker-section">
2507 <div class="broker d-flex flex-column flex-md-row">
2508 <div class="broker-wrapper d-flex flex-column">
2509 <h2 class="section-header semi-bold mb-md-0">
2510 @string.Format(Translate("Custom.Propertypage.BrokerSection.Header", "Har du spørgsmål? Spørg {0}"), propBroker.Employee.FirstName)
2511 </h2>
2512 <div class="divider-orange d-none d-md-block"></div>
2513 <img class="img-fluid d-block d-md-none" src="@employeeItem["BilledeUrl"]" data-fallback="@fallbackImage" onerror="handleImageError(this)" />
2514 <div class="employee-info d-flex flex-column">
2515 @if (!string.IsNullOrEmpty(propBroker?.Employee?.Name))
2516 {
2517 <div class="bold js-maegler-employee-name-val">@propBroker.Employee.Name</div>
2518 }
2519 @if (!string.IsNullOrEmpty(propBroker?.Employee?.JobTitle))
2520 {
2521 <div class="regular js-maegler-employee-title-val">@propBroker.Employee.JobTitle</div>
2522 }
2523 @if (!string.IsNullOrEmpty(propBroker?.Employee?.Email))
2524 {
2525 <div class="regular js-maegler-mail-val">@Translate("Custom.Propertypage.BrokerSection.EmplyeeInfo.Emailprefix", "Mail:") <a class="btn-link regular" href="mailto:@propBroker.Employee.Email">@propBroker.Employee.Email</a></div>
2526 }
2527 @if (!string.IsNullOrEmpty(propBroker?.Employee?.PhoneMobile) && Converter.ToBoolean(employeeItem["VisMobilNrPaaSager"]))
2528 {
2529 <div class="regular">@Translate("Custom.Propertypage.BrokerSection.EmplyeeInfo.Phoneprefix", "Tlf:") <a class="btn-link regular js-maegler-mobile-val" href="tel:@propBroker.Employee.PhoneMobile">@RealMaeglerne.Library.Helper.FormatPhoneNumber(propBroker.Employee.PhoneMobile)</a></div>
2530 }
2531 else if (!string.IsNullOrEmpty(propBroker?.Broker?.Telephone))
2532 {
2533 <div class="regular">@Translate("Custom.Propertypage.BrokerSection.EmplyeeInfo.Phoneprefix", "Tlf:") <a class="btn-link regular" href="tel:@propBroker.Broker.Telephone">@RealMaeglerne.Library.Helper.FormatPhoneNumber(propBroker.Broker.Telephone)</a></div>
2534 }
2535 </div>
2536 <div class="divider-grey"></div>
2537
2538 @if (brokerItem != null)
2539 {
2540 var brokerEmail = Converter.ToString(brokerItem["Email"]);
2541
2542 <div class="broker-info">
2543 @if (!string.IsNullOrEmpty(propBroker?.Broker?.CompanyName))
2544 {
2545 <div class="bold js-maegler-name-val">@propBroker.Broker.CompanyName</div>
2546 }
2547 else if (!string.IsNullOrEmpty(propBroker?.Broker?.Name))
2548 {
2549 <div class="bold js-maegler-name-val">@propBroker.Broker.Name</div>
2550 }
2551 @if (!string.IsNullOrEmpty(brokerAddress))
2552 {
2553 <div class="regular">@brokerAddress</div>
2554 }
2555 @if (!string.IsNullOrEmpty(brokerEmail))
2556 {
2557 <div class="regular">@Translate("Custom.Propertypage.BrokerSection.EmployeeInfo.Emailprefix", "Mail:") <a class="btn-link regular" href="mailto:@brokerEmail">@brokerEmail</a></div>
2558 }
2559 @if (!string.IsNullOrEmpty(propBroker?.Broker?.Telephone))
2560 {
2561 <div class="regular">@Translate("Custom.Propertypage.BrokerSection.EmployeeInfo.Phoneprefix", "Tlf:") <a class="btn-link regular js-maegler-phone-val" href="tel:@propBroker.Broker.Telephone">@RealMaeglerne.Library.Helper.FormatPhoneNumber(propBroker.Broker.Telephone)</a></div>
2562 }
2563 </div>
2564 <span class="js-butikId d-none">@Converter.ToString(employeeItem["CBMedlemsnummer"])</span>
2565 <span class="js-maegler-address-val d-none">@propBroker.Broker.Address</span>
2566 <span class="js-maegler-zip-city-val d-none">@propBroker.Broker.ZipCode @propBroker.Broker.City</span>
2567 }
2568
2569 <div class="broker-buttons d-flex flex-column flex-md-row">
2570 <a href="@brokerUrl" class="btn btn-blue w-100">
2571 @Translate("Custom.Propertypage.BrokerSection.BrokerLink.Label", "Vis mæglerens side")
2572 <img height="20px" width="20px" src="@(iconPath + "icon-arrow-right.svg")" />
2573 </a>
2574 <a class="btn btn-orange w-100" href="javascript:panelFremvisning('@origin');">
2575 @Translate("Custom.Propertypage.AssetsModal.Header.Showing.ButtonLabel", "Bestil fremvisning")
2576 <img height="20px" width="20px" src="@(iconPath + "icon-arrow-right.svg")" />
2577 </a>
2578 </div>
2579 </div>
2580 <img class="img-fluid d-none d-md-block" src="@employeeItem["BilledeUrl"]" data-fallback="@fallbackImage" onerror="handleImageError(this)" />
2581 </div>
2582 </section>
2583 }
2584
2585 @*SECTION: Silmilar properties*@
2586 @{
2587 int sliderFeedPageId = GetPageIdByNavigationTag("PropertySlider");
2588 }
2589 @if (sliderFeedPageId > 0)
2590 {
2591 <section class="container property-slider-section">
2592 <div class="d-flex flex-column justify-content-center align-content-center">
2593 <h2 class="property-slider-header">@Translate("Custom.PropertySlider.Header", "Se lignende boliger")</h2>
2594 <div class="property-slider-subheader">@Translate("Custom.PropertySlider.Subheader", "- måske gemmer din drømmebolig sig her?")</div>
2595 </div>
2596 <div id="property-slider" class="property-slider" data-slider-feed="@Converter.ToString(sliderFeedPageId)" data-zip-code="@GetString("Ecom:Product:Field.xEjendomAdressePostnummer")" data-property-category="@propCategory">
2597 <div class="property-slider-skeleton">
2598 </div>
2599 </div>
2600 </section>
2601 }
2602 @*SECTION: Goldbuyer*@
2603 @{
2604 var becomeGoldBuyerLink = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetRawValueString("BecomeGoldBuyerLink", "");
2605 }
2606
2607 @if (!string.IsNullOrEmpty(becomeGoldBuyerLink))
2608 {
2609 <section class="container goldbuyer-section">
2610 <div class="goldbuyer">
2611 <div class="goldbuyer-wrapper d-flex flex-column">
2612 <h2 class="section-header semi-bold text-left mb-md-0">
2613 @Translate("Custom.Propertypage.GoldBuyerSection.Header", "Guldkøber®")
2614 </h2>
2615 <div class="divider-orange d-none d-md-block"></div>
2616 <div class="section-usps">
2617 <div class="d-flex">
2618 <img class="circle-gold mr-2" height="24px" width="24px" src="@(iconPath + "icon-check.svg")" />
2619 @Translate("Custom.Propertypage.GoldBuyerSection.Usp1", "Få besked, når en bolig matcher dine ønsker.")
2620 </div>
2621 <div class="d-flex">
2622 <img class="circle-gold mr-2" height="24px" width="24px" src="@(iconPath + "icon-check.svg")" />
2623 @Translate("Custom.Propertypage.GoldBuyerSection.Usp2", "Vi overvåger markedet for dig.")
2624 </div>
2625 <div class="d-flex">
2626 <img class="circle-gold mr-2" height="24px" width="24px" src="@(iconPath + "icon-check.svg")" />
2627 @Translate("Custom.Propertypage.GoldBuyerSection.Usp3", "Få et nemt køb.")
2628 </div>
2629 </div>
2630 <a class="btn btn-gold align-self-center align-self-md-start" href="/Default.aspx?ID=@becomeGoldBuyerLink">
2631 @Translate("Custom.Propertypage.GoldBuyerSection.ButtonLabel", "Bliv guldkøber")
2632 <img height="20px" width="20px" src="@(iconPath + "icon-arrow-right.svg")" />
2633 </a>
2634 </div>
2635 <img class="img-fluid d-none d-md-block" src="@(imagePath + "goldbuyer.jpg")" data-fallback="@fallbackImage" onerror="handleImageError(this)" />
2636 </div>
2637 </section>
2638 }
2639
2640 @*SECTION: Buyer Advice*@
2641 @{
2642 var rmBuyingAdvicePageId = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetRawValueString("RMBuyingAdviceMasterPageID", "");
2643 }
2644
2645 @if (!string.IsNullOrEmpty(rmBuyingAdvicePageId))
2646 {
2647 <section class="container buyeradvice-section">
2648 <div class="buyeradvice">
2649 <img class="img-fluid d-none d-md-block" src="@(imagePath + "buyeradvice.jpg")" data-fallback="@fallbackImage" onerror="handleImageError(this)" />
2650 <div class="buyeradvice-wrapper d-flex flex-column">
2651 <h2 class="section-header semi-bold text-left mb-md-0">
2652 @Translate("Custom.Propertypage.BuyerAdviceSection.Header", "Køber du hos anden mægler? Få ærlig køberrådgivning")
2653 </h2>
2654 <div class="divider-orange d-none d-md-block"></div>
2655 <div class="section-usps">
2656 <div class="d-flex">
2657 <img class="circle-blue mr-2" height="24px" width="24px" src="@(iconPath + "icon-check.svg")" />
2658 @Translate("Custom.Propertypage.BuyerAdviceSection.Usp1", "Vi gennemgår købsaftale, skøde og finansiering, så du undgår skjulte faldgruber og dyre fejl.")
2659 </div>
2660 <div class="d-flex">
2661 <img class="circle-blue mr-2" height="24px" width="24px" src="@(iconPath + "icon-check.svg")" />
2662 @Translate("Custom.Propertypage.BuyerAdviceSection.Usp2", "Du får en dedikeret køberrådgiver, som kun arbejder for dig – ikke sælger.")
2663 </div>
2664 <div class="d-flex">
2665 <img class="circle-blue mr-2" height="24px" width="24px" src="@(iconPath + "icon-check.svg")" />
2666 @Translate("Custom.Propertypage.BuyerAdviceSection.Usp3", "Vi kan forhandle på dine vegne og ofte skaffe bedre pris, vilkår eller overtagelsesdato.")
2667 </div>
2668 </div>
2669 <a class="btn btn-blue align-self-center align-self-md-start" href="/Default.aspx?ID=@rmBuyingAdvicePageId">
2670 @Translate("Custom.Propertypage.BuyerAdviceSection.ButtonLabel", "Sådan hjælper køberrådgivning dig")
2671 <img height="20px" width="20px" src="@(iconPath + "icon-arrow-right.svg")" />
2672 </a>
2673 </div>
2674 </div>
2675 </section>
2676 }
2677 <div id="sticky-sales-assessment-button" class="sales-assessment-mobile d-block d-md-none">
2678 <a class="btn btn-blue" href="javascript:panelSalgsvurdering('@origin');">@Translate("Custom.Propertypage.SalesAssessment.ButtonLabel", "Bestil salgsvurdering")</a>
2679 </div>
2680 </div>
2681 <!--PANELS-->
2682 @{
2683 var settingsPersondatapolitik = settingsItem != null ? settingsItem["Persondatapolitik"] : "";
2684 var termsMail = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetRawValueString("TermsEmail", "");
2685 var userId = Dynamicweb.Security.UserManagement.UserContext.Current.UserId;
2686 var user = Dynamicweb.Security.UserManagement.UserContext.Current.User;
2687 string brokerName = !string.IsNullOrEmpty(propBroker?.Broker?.CompanyName) ? propBroker.Broker.CompanyName : propBroker.Broker.Name;
2688 string butikId = brokerItem?["CBMedlemsNummer"] != null ? Converter.ToString(brokerItem["CBMedlemsnummer"]) : string.Empty;
2689
2690 }
2691
2692 <div id="panel-book-showing" class="panel panel-form" role="dialog" aria-modal="true" aria-labelledby="book-showing-title">
2693 <button type="button" class="close" data-dismiss="panel-form" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.CloseForm", "Luk formular"))">
2694 <b></b>
2695 </button>
2696 <h2 id="book-showing-title" class="js-showing-header">@Translate("form-fremvisning-titel", "Bestil fremvisning")</h2>
2697 <p>@Translate("form-fremvisning-beskrivelse", "")</p>
2698 <form id="book-showing" method="POST" action="/InboxHandler">
2699 <div class="form-group">
2700 <label><strong>@Translate("form-navn", "Navn")*</strong></label>
2701 <input class="form-control" type="text" name="navn" placeholder="@HtmlEncoder.HtmlAttributeEncode(Translate("Smartpage:Placeholder.Navn", "Indtast dit navn"))" value="@HtmlEncoder.HtmlAttributeEncode(user?.UserName)" required="required" aria-required="true" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.NameField", "Navn"))" />
2702 </div>
2703 <div class="form-group">
2704 <label><strong>@Translate("form-email", "E-mail")*</strong></label>
2705 <input class="form-control" type="email" pattern="[_a-z0-9.%+-]+@[a-z0-9.-]+.[a-z]{2,4}$" name="email" placeholder="@HtmlEncoder.HtmlAttributeEncode(Translate("Smartpage:Placeholder.Email", "Indtast din e-mail"))" value="@HtmlEncoder.HtmlAttributeEncode(user?.Email)" required="required" aria-required="true" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.EmailField", "E-mail adresse"))" />
2706 </div>
2707 <div class="form-group row">
2708 <div class="col-6">
2709 <label><strong>@Translate("form-mobile", "Mobil nr.")*</strong></label>
2710 <input class="form-control" type="tel" pattern="^[0-9]*$" maxlength="20" name="mobile" placeholder="@HtmlEncoder.HtmlAttributeEncode(Translate("Smartpage:Salgsopstilling.Placeholder.Mobile", "Indtast mobil nr."))" value="@HtmlEncoder.HtmlAttributeEncode(user?.Phone)" required="required" aria-required="true" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.MobileField", "Mobilnummer"))" />
2711 </div>
2712 <div class="col-6">
2713 <label><strong>@Translate("form-telephone", "Telefon nr.")</strong></label>
2714 <input class="form-control" type="tel" pattern="^[0-9]*$" maxlength="20" name="telefonnummer" placeholder="@HtmlEncoder.HtmlAttributeEncode(Translate("Smartpage:Salgsopstilling.Placeholder.Telefon", "Indtast tlf nr."))" value="@HtmlEncoder.HtmlAttributeEncode(user?.Phone)" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.PhoneField", "Telefonnummer"))" />
2715 </div>
2716 </div>
2717
2718 <div class="form-group">
2719 <label><strong>@Translate("form-tidspunkt", "Tidspunkt")*</strong></label>
2720 <input class="form-control" type="text" name="tidspunkt" placeholder="@HtmlEncoder.HtmlAttributeEncode(Translate("form-tidspunkt", "Tidspunkt"))" required="required" aria-required="true" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.TimeField", "Tidspunkt for fremvisning"))" />
2721 </div>
2722 <button class="form-control text-left js-collapse-focus" type="button" data-toggle="collapse" data-target="#bookshowing-collapse" aria-expanded="false" aria-controls="bookshowing-collapse" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.AddComment", "Tilføj kommentar"))">
2723 <strong class="f-12"><i class="fas fa-plus"></i> @Translate("Smartpage:.Skrivenkommentar", "Skriv en kommentar")</strong>
2724 </button>
2725 <div class="collapse" id="bookshowing-collapse">
2726 <div class="form-group">
2727 <textarea class="form-control" name="besked" placeholder="@HtmlEncoder.HtmlAttributeEncode(Translate("form-besked", "Besked"))" maxlength="150" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.MessageField", "Besked til mægler"))"></textarea>
2728 </div>
2729 </div>
2730
2731 <div class="form-group">
2732 <div class="row">
2733 <div class="col-12">
2734 <button type="submit" class="btn btn-green btn-block js-showing-btn">@Translate("form-fremvisning-submitbtn", "Bestil fremvisning")</button>
2735 </div>
2736 </div>
2737 </div>
2738 <div class="form-group form-group-terms">
2739 @string.Format(Translate("Custom.Propertypage.PanelBookShowing.Terms", "Ved at indsende formularen, giver du dit samtykke til, at dine data samles og behandles af RealMæglerne A/S for at kunne kontakte dig.\r\n Du kan til enhver tid tilbagekalde dit samtykke. For at gøre dette skal du blot sende en meddelelse til <a href=\"mailto:{0}\">{0}</a>.\r\n Læs mere på <a href=\"{1}\">privatlivspolitikkerne</a>."), termsMail, settingsPersondatapolitik)
2740 </div>
2741 <input type="hidden" name="kontaktmigok" value="true" />
2742 <input type="hidden" name="fn" value="bf" />
2743 <input type="hidden" name="origin" value="" />
2744 <input type="hidden" name="brugerId" value="@userId" />
2745 <input type="hidden" name="sagsnr" value="@productId" />
2746 <input type="hidden" name="productid" value="@productId" />
2747 <input type="hidden" name="eadresse" value="@HtmlEncoder.HtmlAttributeEncode(GetString("Ecom:Product:Field.xEjendomAdresseAdresseLinie"))" />
2748 <input type="hidden" name="epostnrby" value="@HtmlEncoder.HtmlAttributeEncode(GetString("Ecom:Product:Field.xEjendomAdressePostAdresseLinie"))" />
2749 <input type="hidden" name="areaid" value="@Pageview.AreaID" />
2750 <input type="hidden" name="bnavn" value="@HtmlEncoder.HtmlAttributeEncode(brokerName)" />
2751 <input type="hidden" name="greenmobility" value="@Converter.ToString(isValidForGreenMobility)" />
2752 <input class="js-online-showing" type="hidden" name="onlineShowing" value="" />
2753 <input type="hidden" name="butikId" value="@HtmlEncoder.HtmlAttributeEncode(butikId)" />
2754 @if (employeeItem != null)
2755 {
2756
2757 <input type="hidden" name="mnavn" value="@HtmlEncoder.HtmlAttributeEncode(propBroker.Employee.Name)" />
2758 if (!string.IsNullOrEmpty(propBroker.Employee.PhoneMobile) && Converter.ToBoolean(employeeItem["VisMobilNrPaaSager"]))
2759 {
2760 <input type="hidden" name="mtelefonnummer" value="@HtmlEncoder.HtmlAttributeEncode(propBroker.Employee.PhoneMobile)" />
2761 }
2762 else
2763 {
2764
2765 <input type="hidden" name="mtelefonnummer" value="@HtmlEncoder.HtmlAttributeEncode(propBroker.Broker.Telephone)" />
2766 }
2767
2768 <input type="hidden" name="memail" value="@RealMaeglerne.Library.Helper.ExtractMaskedEmail(propBroker.Employee.Email)" />
2769
2770 }
2771 </form>
2772 <div id="book-showing-thanks" style="display:none;" role="status" aria-live="polite" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.ThankYouMessage", "Tak besked"))">
2773 <p>@Translate("form-fremvisning-tak", "Tak for din bestilling af fremvisning. Du vil hurtigst muligt blive kontaktet af din mægler, for at bekræfte jeres aftale. Tak for din interesse.")</p>
2774 </div>
2775 </div>
2776
2777 <div id="panel-sales-documents" class="panel panel-form" role="dialog" aria-modal="true" aria-labelledby="sales-documents-title">
2778 <button type="button" class="close" data-dismiss="panel-form" aria-label="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Accessibility.CloseForm", "Luk formular"))">
2779 <b></b>
2780 </button>
2781
2782 <h2 id="sales-documents-title">@Translate("form-salgsopstilling-titel", "Bestil Salgsopstilling")</h2>
2783
2784 <p>@Translate("form-salgsopstilling-beskrivelse", "")</p>
2785 <form id="order-sales-documents" method="POST" action="/InboxHandler">
2786 <div class="form-group">
2787 <label><strong>@Translate("form-navn", "Navn")*</strong></label>
2788 <input class="form-control" type="text" name="navn" placeholder="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Salgsopstilling.Placeholder.Navn", "Indtast dit navn"))" value="@HtmlEncoder.HtmlAttributeEncode(user?.UserName)" required=required />
2789 </div>
2790 <div class="form-group">
2791 <label><strong>@Translate("form-email", "E-mail")*</strong></label>
2792 <input class="form-control" type="email" pattern="[_a-z0-9.%+-]+@[a-z0-9.-]+.[a-z]{2,4}$" name="email" placeholder="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:.Salgsopstilling.Placeholder.Email", "Indtast din e-mail"))" value="@HtmlEncoder.HtmlAttributeEncode(user?.Email)" required=required />
2793 </div>
2794 <div class="form-group row">
2795 <div class="col-6">
2796 <label><strong>@Translate("form-mobile", "Mobil nr.")*</strong></label>
2797 <input class="form-control" type="tel" pattern="^[0-9]*$" maxlength="20" name="mobile" placeholder="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Salgsopstilling.Placeholder.Mobile", "Indtast mobil nr."))" value="@HtmlEncoder.HtmlAttributeEncode(user?.Phone)" required=required />
2798 </div>
2799 <div class="col-6">
2800 <label><strong>@Translate("form-telephone", "Telefon nr.")</strong></label>
2801 <input class="form-control" type="tel" pattern="^[0-9]*$" maxlength="20" name="telefonnummer" placeholder="@HtmlEncoder.HtmlAttributeEncode(Translate("Custom:Salgsopstilling.Placeholder.Telefon", "Indtast tlf nr."))" value="@HtmlEncoder.HtmlAttributeEncode(user?.Phone)" />
2802 </div>
2803 </div>
2804 <div class="form-group">
2805 <div class="checkbox">
2806 <label>
2807 <input type="checkbox" name="kontaktmigok" />
2808 <span>@Translate("form-contactpermission-real", "Ja tak, RealMæglerne må gerne kontakte mig. *")</span>
2809 </label>
2810 </div>
2811 </div>
2812 <div class="form-group">
2813 <div class="row">
2814 <div class="col-12">
2815 <button type="submit" class="btn btn-green btn-block">@Translate("form-salgsopstilling-submitbtn", "Bestil salgsopstilling")</button>
2816 </div>
2817 </div>
2818 </div>
2819
2820
2821 <div class="form-group form-group-terms">
2822 @string.Format(Translate("Custom.Propertypage.PanelBookShowing.Terms", "Ved at indsende formularen, giver du dit samtykke til, at dine data samles og behandles af RealMæglerne A/S for at kunne kontakte dig.\r\n Du kan til enhver tid tilbagekalde dit samtykke. For at gøre dette skal du blot sende en meddelelse til <a href=\"mailto:{0}\">{0}</a>.\r\n Læs mere på <a href=\"{1}\">privatlivspolitikkerne</a>."), termsMail, settingsPersondatapolitik)
2823 </div>
2824 <input type="hidden" name="fn" value="bs" />
2825 <input type="hidden" name="origin" value="" />
2826 <input type="hidden" name="sagsnr" value="@productId" />
2827 <input type="hidden" name="brugerId" value="@userId" />
2828 <input type="hidden" name="areaid" value="@Pageview.AreaID" />
2829 <input type="hidden" Fname="butikId" value="@HtmlEncoder.HtmlAttributeEncode(butikId)" />
2830 <input type="hidden" name="productId" value="@productId" />
2831 </form>
2832 <div id="download-sales-documents" style="display:none;">
2833 <p>@Translate("form-salgsopstilling-downloadbeskrivelse", "Tak for din interesse")</p>
2834 <br />
2835 @foreach (var item in edhFiles)
2836 {
2837 if (item.Value.ToLower() == "salgsopstilling")
2838 {
2839 <a href="@item.Key" class="btn btn-primary link" target="_blank">@Translate("form-salgsopstilling-download", "Hent") @item.Value</a>
2840 <br /><br />
2841 }
2842 }
2843 </div>
2844 </div>
2845
2846 <div id="panel-makeanoffer" class="panel panel-form">
2847 <button type="button" class="close" data-dismiss="panel-form" aria-label="@HtmlEncoder.HtmlAttributeEncode(@Translate("Custom:Accessiblity.OfferPanel.Close","Luk"))">
2848 <b></b>
2849 </button>
2850
2851 <h2>@Translate("Smartpage:MakeAnOffer.Title", "Skriv din pris")</h2>
2852
2853 <form id="make-an-offer" method="POST" action="/InboxHandler">
2854 <p>@Translate("Smartpage:MakeAnOffer.Subtitle", "Giv et uforpligtende bud. Dit bud er ikke bindende for dig, ligesom sælger ikke er forpligtet til at acceptere dit bud.")</p>
2855 <div class="form-group">
2856 <label><strong>@Translate("Smartpage:MakeAnOffer.Price", "Prisforslag")*</strong></label>
2857 @*checkmark*@
2858 <input class="form-control js-input-offer" id="form-offer" type="text" name="price" placeholder="@Dynamicweb.Core.Encoders.HtmlEncoder.HtmlAttributeEncode(Translate("Smartpage:MakeAnOffer.Price", "Prisforslag") )" />
2859 </div>
2860 <div class="form-group">
2861 <label><strong>@Translate("form-navn", "Navn")*</strong></label>
2862 <input class="form-control" type="text" name="navn" placeholder="@Dynamicweb.Core.Encoders.HtmlEncoder.HtmlAttributeEncode(Translate("form-navn", "Navn") )" value="@HtmlEncoder.HtmlAttributeEncode(user?.UserName)" />
2863 </div>
2864 <div class="form-group">
2865 <label><strong>@Translate("form-email", "E-mail")*</strong></label>
2866 <input class="form-control" type="email" pattern="[_a-z0-9.%+-]+@[a-z0-9.-]+.[a-z]{2,4}$" name="email" placeholder="@Dynamicweb.Core.Encoders.HtmlEncoder.HtmlAttributeEncode(Translate("form-email", "E-mail") )" value="@HtmlEncoder.HtmlAttributeEncode(user?.Email)" />
2867 </div>
2868 <div class="form-group">
2869 <label><strong>@Translate("form-telephone", "Telefon nr.")*</strong></label>
2870 <input class="form-control" type="tel" pattern="^[0-9]*$" maxlength="20" name="telefonnummer" placeholder="@Dynamicweb.Core.Encoders.HtmlEncoder.HtmlAttributeEncode(Translate("Smartpage:Salgsopstilling.Placeholder.Telefon", "Indtast tlf nr.") )" value="@HtmlEncoder.HtmlAttributeEncode(user?.Phone)" />
2871 </div>
2872 <div class="form-group">
2873 <div class="checkbox">
2874 <label>
2875 <input type="checkbox" name="kontaktmigok" />
2876 <span>@Translate("form-contactpermission-real", "Ja tak, RealMæglerne må gerne kontakte mig. *")</span>
2877 </label>
2878 </div>
2879 </div>
2880 <div class="form-group">
2881 <div class="row">
2882 <div class="col-12">
2883 <button type="submit" class="btn btn-green btn-block">@Translate("Smartpage:MakeAnOffer.Button.Text", "Send mit bud")</button>
2884 </div>
2885 </div>
2886 </div>
2887
2888
2889 <div class="form-group form-group-terms">
2890 @Translate("Smartpage:MakeAnOffer.TermsAndConditions", "* Der samles ingen personlige oplysninger uden dit udtrykkelige samtykke. Ved at klikke på denne checkboks giver du dit samtykke til, at dine data samles og behandles af RealMæglerne A/S for at kunne kontakte dig. Du kan til enhver tid tilbagekalde dit samtykke. For at gøre dette skal du blot sende en meddelelse til ")
2891 <a href="mailto:@termsMail">@termsMail</a>.
2892 @Translate("Smartpage:MakeAnOffer.TermsAndConditions.ReadMoreOn", "Læs mere på") <a href="@settingsPersondatapolitik">@Translate("Smartpage:MakeAnOffer.TermsAndConditions.PrivacyPolicy", "privatlivspolitikkerne")</a>.
2893 </div>
2894 <input type="hidden" name="fn" value="skp" />
2895 <input type="hidden" name="origin" value="" />
2896 <input type="hidden" name="sagsnr" value="@productId" />
2897 <input type="hidden" name="brugerId" value="@userId" />
2898 <input type="hidden" name="areaid" value="@Pageview.AreaID" />
2899 <input type="hidden" name="butikId" value="@HtmlEncoder.HtmlAttributeEncode(butikId)" />
2900 </form>
2901 <div class="js-thank-you-message" style="display:none;">
2902 <p>@Translate("Smartpage:MakeAnOffer.ThankYouMessage", "Tak for dit bud. Du vil hurtigst muligt blive kontaktet af mægler. Tak for din interesse.")</p>
2903 </div>
2904 </div>
2905
2906 <script type="text/javascript" src="/Files/Templates/Designs/rm/assets/dist/bundle.boligside.min.js"></script>
2907 <script>
2908
2909
2910 document.addEventListener("DOMContentLoaded", () => {
2911 checkIfStuck("[propertypage-anchor]");
2912 initHiddenStickyElements("sticky-sales-assessment-button", "description-section");
2913 initImageNavigation('.blueprints', { imageSelector: '.blueprints-wrapper img', buttonIdPostFix: '-blueprints', threshold: 1, scrollDirection: 'horizontal' });
2914 initImageNavigation('.usps', { imageSelector: '.usp-item', buttonIdPostFix: '-usps', threshold: 1, scrollDirection: 'horizontal' });
2915 syncSelectors('openhouse-selector-desktop', 'openhouse-selector-mobile');
2916 initSliderObserver('property-slider');
2917 initMetricsSlider('.js-popular-metrics-wrapper', '.popular-metric');
2918 })
2919
2920 function initSliderObserver(sliderElementId) {
2921
2922 const sliderElement = document.getElementById(sliderElementId);
2923
2924 const observer = new IntersectionObserver((entries) => {
2925 entries.forEach(entry => {
2926 if (entry.isIntersecting) {
2927 addSlider(entry);
2928 observer.unobserve(entry.target);
2929 }
2930 });
2931 }, {
2932 root: null,
2933 threshold: 0.1
2934 });
2935
2936 // Observe elements
2937 observer.observe(sliderElement);
2938 }
2939
2940 async function addSlider(entry) {
2941 const sliderFeedId = entry.target.dataset.sliderFeed;
2942
2943 if (sliderFeedId != null) {
2944 const params = new URLSearchParams({ ID: sliderFeedId });
2945
2946 const zipCode = entry.target.dataset.zipCode;
2947 if (zipCode) {
2948 params.set('zipcodefrom', zipCode);
2949 params.set('zipcodeto', zipCode);
2950 }
2951
2952 const propertyCategory = entry.target.dataset.propertyCategory;
2953 if (propertyCategory) {
2954 params.set('propertycategory', propertyCategory);
2955 }
2956
2957 const url = `/Default.aspx?${params}`;
2958
2959 try {
2960 const result = await fetch(url);
2961 if (!result.ok) throw new Error('Network response was not ok');
2962 const response = await result.text();
2963 entry.target.innerHTML = response;
2964 } catch (error) {
2965 console.error('Error loading slider:', error);
2966 entry.target.innerHTML = '<p>@Dynamicweb.Core.Encoders.HtmlEncoder.JavaScriptStringEncode(Translate("Custom.Propertypage.PropertySlider.ErrorMessage", "Failed to load content"))</p>';
2967 }
2968 }
2969
2970 }
2971
2972 function initMetricsSlider(wrapperElement, children) {
2973 document.querySelectorAll(wrapperElement).forEach(wrapper => {
2974 const metrics = wrapper.querySelectorAll(children);
2975
2976 // Skip if only one metric
2977 if (metrics.length <= 1) return;
2978
2979 // Measure widths
2980 const widths = [];
2981 metrics.forEach(metric => {
2982 widths.push(metric.offsetWidth);
2983 });
2984
2985 // Setup wrapper
2986 wrapper.style.width = widths[0] + 'px';
2987 wrapper.style.transition = 'width 1s ease-in-out';
2988
2989 // Setup metrics
2990 metrics.forEach((metric, index) => {
2991 metric.style.position = 'absolute';
2992 metric.style.top = '0';
2993 metric.style.left = '0';
2994 metric.style.transition = 'opacity 1s ease-in-out';
2995 metric.style.opacity = index === 0 ? '1' : '0';
2996 });
2997
2998 // Animation loop
2999 let current = 0;
3000 setInterval(() => {
3001 const next = (current + 1) % metrics.length;
3002
3003 // Fade out current, fade in next
3004 metrics[current].style.opacity = '0';
3005 metrics[next].style.opacity = '1';
3006
3007 // Change width
3008 wrapper.style.width = widths[next] + 'px';
3009
3010 current = next;
3011 }, 4000);
3012 });
3013 }
3014
3015 function syncSelectors(firstSelectorId, secondSelectorId) {
3016 const select1 = document.getElementById(firstSelectorId);
3017 const select2 = document.getElementById(secondSelectorId);
3018
3019 if (select1 && select2) {
3020 select1.addEventListener('change', function () {
3021 select2.value = this.value;
3022 });
3023
3024 select2.addEventListener('change', function () {
3025 select1.value = this.value;
3026 });
3027 }
3028 }
3029
3030 function stopPropagation(event) {
3031 event.stopPropagation();
3032 }
3033
3034 function fullScreen(elementId) {
3035 const element = document.getElementById(elementId);
3036
3037 if (element) {
3038
3039 if (element.classList.contains('full-screen')) {
3040 element.classList.remove('full-screen');
3041 } else {
3042 element.classList.add('full-screen');
3043 }
3044 }
3045 }
3046
3047 function checkIfStuck(stickyElementSelector) {
3048 const stickyElement = document.querySelector(stickyElementSelector);
3049 const stickyTop = parseInt(getComputedStyle(stickyElement).top) || 0;
3050
3051 const observer = new IntersectionObserver(
3052 ([entry]) => {
3053 const targetTop = entry.boundingClientRect.top;
3054
3055 if (targetTop <= stickyTop) {
3056 stickyElement.classList.add('is-stuck');
3057 } else {
3058 stickyElement.classList.remove('is-stuck');
3059 }
3060 },
3061 {
3062 threshold: [1],
3063 rootMargin: `-${stickyTop + 1}px 0px 0px 0px`
3064 }
3065 );
3066
3067 observer.observe(stickyElement);
3068 }
3069
3070 function initHiddenStickyElements(stickyElementId, triggerElementId) {
3071 const stickyElement = document.getElementById(stickyElementId);
3072 const sentinel = document.getElementById(triggerElementId);
3073
3074 if (stickyElement && sentinel) {
3075 const observer = new IntersectionObserver((entries) => {
3076 entries.forEach(entry => {
3077 if (entry.boundingClientRect.top <= 0) {
3078 stickyElement.classList.add('visible');
3079 } else {
3080 stickyElement.classList.remove('visible');
3081 }
3082 });
3083 }, {
3084 threshold: 1,
3085 rootMargin: '0px'
3086 });
3087
3088 observer.observe(sentinel);
3089 }
3090 else {
3091 console.debug("Elements not found in initHiddenStickyElements using stickyElementId: ", stickyElementId, " and triggerElementId: ", triggerElementId);
3092 }
3093 }
3094
3095 function shareProperty(event, clickedButton) {
3096 event.preventDefault();
3097
3098 const shareData = {
3099 title: document.title,
3100 text: clickedButton.dataset.shareText,
3101 url: window.location.href
3102 };
3103
3104 if (navigator.share && navigator.canShare && navigator.canShare(shareData)) {
3105 navigator.share(shareData);
3106 } else {
3107 navigator.clipboard.writeText(window.location.href).then(() => {
3108 const alertText = clickedButton.dataset.alertText || 'Link copied to clipboard!';
3109 alert(alertText);
3110 });
3111 }
3112 }
3113
3114 function scrollToElementById(id, block = "start") {
3115 var element = document.getElementById(id);
3116 if (element) {
3117 element.scrollIntoView({ behavior: "smooth", block: block, container: "nearest" });
3118 }
3119 }
3120
3121 function initImageNavigation(parentSelector, options = {}) {
3122 // Default configuration
3123 const config = {
3124 imageSelector: 'img',
3125 nextButtonId: 'image-next',
3126 prevButtonId: 'image-prev',
3127 buttonIdPostFix: '',
3128 storageKey: 'currentImageIndex_' + parentSelector,
3129 threshold: 0.8,
3130 scrollBehavior: 'smooth',
3131 scrollDirection: 'vertical', // 'vertical' or 'horizontal'
3132 ...options
3133 };
3134
3135 // Get parent element
3136 const parent = document.querySelector(parentSelector);
3137
3138 if (!parent) {
3139 console.warn(`Parent element "${parentSelector}" not found`);
3140 return null;
3141 }
3142
3143 // Get images within parent
3144 const images = parent.querySelectorAll(config.imageSelector);
3145 if (images.length === 0) {
3146 console.warn(`No images found in "${parentSelector}"`);
3147 return null;
3148 }
3149
3150 let currentVisibleIndex = 0;
3151 let lastDirection = null; // Track navigation direction: 'forward' or 'backward'
3152 let visibleIndices = new Set(); // Persistent set of all visible image indices
3153
3154 // Set up Intersection Observer
3155 const observer = new IntersectionObserver((entries) => {
3156 // Update the set based on what changed
3157 entries.forEach(entry => {
3158 const index = Array.from(images).indexOf(entry.target);
3159
3160 if (entry.isIntersecting) {
3161 visibleIndices.add(index);
3162 } else {
3163 visibleIndices.delete(index);
3164 }
3165 });
3166
3167 if (visibleIndices.size > 0) {
3168 const visibleArray = Array.from(visibleIndices);
3169
3170 // Check for boundary cases first
3171 if (visibleIndices.has(images.length - 1)) {
3172 // Last image is visible - set to MIN (prepare for backward movement)
3173 currentVisibleIndex = Math.min(...visibleArray);
3174 lastDirection = 'backward';
3175 } else if (visibleIndices.has(0)) {
3176 // First image is visible - set to MAX (prepare for forward movement)
3177 currentVisibleIndex = Math.max(...visibleArray);
3178 lastDirection = 'forward';
3179 } else {
3180 // Middle of the list - use direction logic
3181 if (lastDirection === 'forward') {
3182 currentVisibleIndex = Math.max(...visibleArray);
3183 } else if (lastDirection === 'backward') {
3184 currentVisibleIndex = Math.min(...visibleArray);
3185 } else {
3186 // Default to min when no direction set (initial load)
3187 currentVisibleIndex = Math.min(...visibleArray);
3188 }
3189 }
3190
3191 if (config.storageKey) {
3192 localStorage.setItem(config.storageKey, currentVisibleIndex);
3193 }
3194
3195 updateButtonStates();
3196 }
3197 }, {
3198 root: null,
3199 threshold: config.threshold
3200 });
3201
3202 // Observe all images
3203 images.forEach(img => observer.observe(img));
3204
3205 function updateButtonStates() {
3206 const nextButton = parent.querySelector('#' + config.nextButtonId + config.buttonIdPostFix);
3207 const prevButton = parent.querySelector('#' + config.prevButtonId + config.buttonIdPostFix);
3208
3209 if (nextButton) {
3210 // Disable if last image is visible
3211 if (visibleIndices.has(images.length - 1)) {
3212 nextButton.classList.add('disabled');
3213 } else {
3214 nextButton.classList.remove('disabled');
3215 }
3216 }
3217
3218 if (prevButton) {
3219 // Disable if first image is visible
3220 if (visibleIndices.has(0)) {
3221 prevButton.classList.add('disabled');
3222 } else {
3223 prevButton.classList.remove('disabled');
3224 }
3225 }
3226 }
3227
3228 // Helper function to scroll to specific image
3229 function scrollToImage(index, direction) {
3230 if (index >= 0 && index < images.length) {
3231 lastDirection = direction;
3232
3233 const scrollOptions = {
3234 behavior: config.scrollBehavior
3235 };
3236
3237 // Set scroll alignment based on direction
3238 if (config.scrollDirection === 'horizontal') {
3239 scrollOptions.inline = 'start';
3240 scrollOptions.block = 'nearest';
3241 } else {
3242 scrollOptions.block = 'start';
3243 scrollOptions.inline = 'nearest';
3244 }
3245
3246 images[index].scrollIntoView(scrollOptions);
3247 currentVisibleIndex = index;
3248
3249 if (config.storageKey) {
3250 localStorage.setItem(config.storageKey, index);
3251 }
3252
3253 updateButtonStates();
3254 }
3255 }
3256
3257 // Set up navigation buttons
3258 const nextButton = parent.querySelector('#' + config.nextButtonId + config.buttonIdPostFix);
3259 const prevButton = parent.querySelector('#' + config.prevButtonId + config.buttonIdPostFix);
3260
3261 const handleNext = () => {
3262 const nextIndex = Math.min(currentVisibleIndex + 1, images.length - 1);
3263 scrollToImage(nextIndex, 'forward');
3264 };
3265
3266 const handlePrev = () => {
3267 const prevIndex = Math.max(currentVisibleIndex - 1, 0);
3268 scrollToImage(prevIndex, 'backward');
3269 };
3270
3271 if (nextButton) {
3272 nextButton.addEventListener('click', handleNext);
3273 } else {
3274 console.warn(`Next button "${config.nextButtonId}" not found`);
3275 }
3276
3277 if (prevButton) {
3278 prevButton.addEventListener('click', handlePrev);
3279 } else {
3280 console.warn(`Prev button "${config.prevButtonId}" not found`);
3281 }
3282
3283 // Initialize button states
3284 updateButtonStates();
3285 }
3286
3287 function handleError(img) {
3288 const fallback = img.dataset.fallback;
3289 if (fallback.length) {
3290 img.src = fallback;
3291 }
3292 }
3293 </script>
Denne hjemmeside bruger cookies til trafikmåling og optimering af indhold. Hvis du klikker videre, accepterer du vores brug af cookies. Læs mere