function academy_booking(price_category) { $('f_academy_booking_academy_price').selectedIndex = price_category; form_evaluate_conditions("academy_booking"); goto_section("academy_booking"); } // Connect to API async function backend_connect(connect_function, payload, complete_function) { const ru = window.location.href; let ref = document.referrer; const queryString = window.location.search; const urlParams = new URLSearchParams(queryString); if (urlParams.has('ref')) { ref = urlParams.get('ref'); } if (!ref && localStorage["si"]) { ref = "ret"; } let ua = 'unknown'; let vr = 'unknown'; let pl = 'unknown'; let mo = 'unknown'; try { const uad = navigator.userAgentData; for (var i=0;i'+JSON.stringify(debug)); return false; } if (json.error && !params.inhibit_error_messages) { console.log("API Error",json.error); const debug = { url:api_url, request:params, reply:json }; message_error("Error", json.error+'
'+JSON.stringify(debug)); return false; } if (global_hyperchat) { if (json.hyperchat) { global_hyperchat.read_messages(json.hyperchat); } if (global_hyperchat.show_online) { global_hyperchat.show_online(json.chat_online); } } if (complete_function) { complete_function(json); } } function booking_start(price_category) { global_booking.price_category = price_category; goto_section('booking'); booking_reset(); } function booking_reset() { global_booking.selected_first_day = false; global_booking.selected_last_day = false; global_booking.following_nights = 0; global_booking.progress = 0; booking_update(); } function booking_show_prices() { global_booking.progress = 1; booking_update(); backend_connect("booking_date_selected"); } function booking_show_form() { global_booking.progress = 2; booking_update(); backend_connect("booking_price_confirmed"); } function booking_update() { if (global_booking.progress == 0) { $('booking').style.display = 'block'; update_calendar(); } else { $('booking').style.display = 'none'; } if (global_booking.progress == 1) { $('booking_price').style.display = 'block'; booking_update_pricing(); } else { $('booking_price').style.display = 'none'; } if (global_booking.progress >= 2) { $('booking_form').style.display = 'block'; } else { $('booking_form').style.display = 'none'; } booking_nav_update(); } function booking_nav_update() { let s = ''; for (let i=0; i<3; i++) { let cls = []; const nav = global_booking_nav[i]; if (i > global_booking.progress) cls.push("disabled"); if (i == global_booking.progress) cls.push("active"); if (i <= global_booking.progress && nav.onclick) cls.push("selectable"); cls = cls.join(" "); let onclick = ''; let caption = nav.description[language]; if (i == 0 && nav.date_selected && global_booking.progress > 0) { caption = format_date_short(global_booking.selected_first_day)+' - '+format_date_short(global_booking.selected_last_day); } if (i < global_booking.progress) caption = ` ${caption}`; if (i == global_booking.progress) caption = ` ${caption}`; if (i <= global_booking.progress && nav.onclick) onclick = `onclick="${nav.onclick}";`; s += `
${caption}
`; } $('booking_nav').innerHTML = s; } var global_calendar = { stays: [], seasons_by_month: [-1, -1, -1, -1, -1, 0, 0, 0, 1, -1, -1, -1], temperatures_high: [ 6, 8, 12, 16, 22, 26, 31, 30, 24, 20, 13, 8 ], temperatures_low: [ 0, 0, 2, 6, 10, 15, 19, 19, 13, 9, 5, 0 ], day_width: 50, day_spacer: 10, day_height: 40, day_baseline: 27, month_spacer: 50, month_width: 0, width:0, height:390, main_svg:false, day_svg:[], months_shown:6, day_names:[], month_names:[], colors: { "past" : "#ccc", "text_past" : "#aaa", "text_weekday" : "#666", "text_weekend" : "#c00" }, current: { date:false, year:0, month:0, time:0, }, layout_written: false, hover_first_day: false, hover_first_last_day: false, hover_last_day: false, following_nights: 0, month_offset:0, scroll_offset:0, season_first_day:0 } // This is invoked once the booking data has loaded from the server function calendar_intialize(apps) { // TODO: Figure out blocked time spans if (apps.stays) { global_calendar.stays = apps.stays; } // Set Current calendar_get_current(); // Set Day Names and Month Names if (language == "de") { global_calendar.day_names = ["So","Mo","Di","Mi","Do","Fr","Sa",]; global_calendar.month_names = ["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"]; } else if (language == "bg") { global_calendar.day_names = ["So","Mo","Di","Mi","Do","Fr","Sa",]; global_calendar.month_names = ["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"]; } else { global_calendar.day_names = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]; global_calendar.month_names = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]; } // Calculate month width and total width global_calendar.month_width = global_calendar.day_width*7 + global_calendar.day_spacer*6; global_calendar.width = global_calendar.months_shown * global_calendar.month_width + (global_calendar.months_shown-1) * global_calendar.month_spacer; // Clear SVG if already exists if (global_calendar.main_svg) { dom_clear(global_calendar.main_svg); // Create SVG if not exists } else { global_calendar.main_svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); $('calendar').appendChild(global_calendar.main_svg); } // Set Width and Height of the main svg global_calendar.main_svg.setAttribute("width", global_calendar.width); global_calendar.main_svg.setAttribute("height", global_calendar.height); global_calendar.main_svg.onmouseleave = day_out; // Set left and right arrows $('calendar_left').innerHTML = arrow_left; $('calendar_right').innerHTML = arrow_right; booking_update(); // This will also update the calendar scroll_calendar(); // TODO: Needed? } function update_calendar() { var total_booked_count = 0; for (var mode=0; mode 0 && d == 0) { for (var j=0; j0) { x = base_x; y += global_calendar.day_height+global_calendar.day_spacer; } else if (d>0) { x += global_calendar.day_width+global_calendar.day_spacer; } // Past Is Unavailable by default if (day.getTime() < global_calendar.current.time ) { season = 4; } // If this is the last day of the month, and the next month is blocked, block day if (next_day.getMonth() != month) { const next_season = global_calendar.seasons_by_month[next_day.getMonth()]; if (next_season == -1) season = 4; } // Get blocked calendar datys if (global_calendar.stays && global_calendar.stays.length > 0) { for (var j=0;j= ce.first_day && day_date <= ce.last_day) { season = 4; } } } if (season == 4) { cbid++; } if (global_booking.selected_first_day && day_date < global_booking.selected_first_day) { season = 4; } if (global_booking.selected_first_day && cbid != global_booking.cbid) { season = 4; } let day_svg = global_calendar.day_svg[dac]; if (!day_svg) { day_svg = {}; var day_text = (d+1); var day_date = year+'-'+format_int(month+1,2)+'-'+format_int(d+1,2); var x1 = x+global_calendar.day_width; var y1 = y+global_calendar.day_height; // Background Rectangle day_svg.rect = svg_filled_rect(x,y,global_calendar.day_width,global_calendar.day_height,global_calendar.colors["past"], global_calendar.main_svg); // Bottom Right Triangle day_svg.trig = svg_path(`M ${x1} ${y1} L ${x} ${y1} L ${x1} ${y} Z`,global_calendar.colors["past"], global_calendar.main_svg); // Day of the Month as Text var text_color = global_calendar.colors["text_weekday"]; if (weekend) text_color = global_calendar.colors["text_weekend"]; day_svg.text = svg_text(x+global_calendar.day_width/2, y+global_calendar.day_baseline, day_text, text_color, "middle", "", global_calendar.main_svg); /* // Crossed out day_svg.cross1 = svg_line(x1, y1, x, y, "#ff0000", global_calendar.main_svg); day_svg.cross2 = svg_line(x1, y, x, y1, "#ff0000", global_calendar.main_svg); */ if (season == 4) { prev_rolos = []; } if (season != 4 || last_season != 4) { var rolo = svg_filled_rect(x-global_calendar.day_spacer/2, y-global_calendar.day_spacer/2, global_calendar.day_width+global_calendar.day_spacer, global_calendar.day_height+global_calendar.day_spacer, global_calendar.colors["past"], global_calendar.main_svg); day_svg.rolo = rolo; rolo.setAttribute('opacity', 0.01); rolo.onmouseover = day_over; rolo.date = day_date; rolo.onclick = day_click; rolo.style.cursor = 'pointer'; rolo.following_nights = 0; rolo.cbid = cbid; rolo.last_cbid = last_cbid; if (season != 4) { prev_rolos.push(rolo); for (var j=0; j= global_booking.selected_first_day && day_date < global_booking.selected_last_day) { booked = true; } // Rollover Last Day } else if (global_booking.selected_first_day && global_calendar.hover_last_day) { if (day_date >= global_booking.selected_first_day && day_date < global_calendar.hover_last_day) { booked = true; if (global_calendar.hover_last_day < global_booking.selected_first_last_day ) { error = true; } } // First Day Selected } else if (global_booking.selected_first_day) { if (day_date >= global_booking.selected_first_day && day_date < global_booking.selected_first_last_day) { // Highlight only the first day if (day_date == global_booking.selected_first_day ) { booked = true; global_calendar.season_first_day = season; } if (global_booking.following_nights < global_booking.minimum_nights) { booked = true; error = true; } } // Rollover First Day } else if (global_calendar.hover_first_day) { if (day_date >= global_calendar.hover_first_day && day_date < global_calendar.hover_first_last_day) { // Highlight only the first day if (day_date == global_calendar.hover_first_day ) { booked = true; global_calendar.season_first_day = season; } if (global_calendar.following_nights < global_booking.minimum_nights) { booked = true; error = true; } } } // if this day is blocked, change colors and do not allow start if (season == 4) { day_svg.color = global_calendar.colors["past"]; booked = false; } else if (booked) { day_svg.color = calendar_modes[season].color_booked; if (error) day_svg.color = calendar_modes[season].color_error; calendar_modes[season].booked_count++; total_booked_count++; } if (season == 4 && last_season == 4) { day_svg.text.setAttribute('opacity', 0.2); /* day_svg.cross1.setAttribute('opacity', 0.3); day_svg.cross2.setAttribute('opacity', 0.3); */ } else { day_svg.text.setAttribute('opacity', 1); /* day_svg.cross1.setAttribute('opacity', 0); day_svg.cross2.setAttribute('opacity', 0); */ } if (last_day_svg) { day_svg.rect.setAttribute('fill', last_day_svg.color); } else { day_svg.rect.setAttribute('fill', global_calendar.colors["past"]); } day_svg.trig.setAttribute('fill', day_svg.color); last_season = season; last_day_svg = day_svg; last_cbid = cbid; dac++; } base_x += global_calendar.month_width + global_calendar.month_spacer; } global_calendar.layout_written = true; calendar_scale(); let s = ``; const reset = ` ${loc["select_reset"][language]}`; // No Start Day, No Hover if (!global_booking.selected_first_day && !global_calendar.hover_first_day ) { s = `${loc["select_first"][language]}`; // Hover Start Day } else if (!global_booking.selected_first_day && global_calendar.hover_first_day ) { s = `${loc["select_next1"][language]} `+format_date(global_calendar.hover_first_day)+' ('+ calendar_modes[global_calendar.season_first_day]["name"][language]+')'; if (error) s += `
${loc["min_stay_warning"][language]} `+global_booking.minimum_nights+``; // Start Day selected, no hover, no end day selected } else if (global_booking.selected_first_day && !global_booking.selected_last_day && !global_calendar.hover_last_day) { s = `${reset} ${loc["select_next1"][language]} ${format_date(global_booking.selected_first_day)}`; if (error) { s += `
${loc["min_stay_warning"][language]} `+global_booking.minimum_nights+``; } else { s += `
${loc["select_next2"][language]}`; } // Start Day selected, hover, no end day selected } else if (global_booking.selected_first_day && !global_booking.selected_last_day && global_calendar.hover_last_day) { if (error) { s = `${reset} ${total_booked_count} ${loc["select_done1"][language]}
${loc["min_stay_warning"][language]} `+global_booking.minimum_nights+``; } else { s = `${reset} ${total_booked_count} ${loc["select_done1"][language]}
${loc["select_done2"][language]} ${format_date(global_booking.selected_first_day)} ${loc["select_done3"][language]} ${format_date(global_calendar.hover_last_day)}`; } } else if (global_booking.selected_first_day && !global_booking.selected_last_day) { s = `${reset} ${total_booked_count} ${loc["select_done1"][language]}
${loc["select_done2"][language]} ${format_date(global_booking.selected_first_day)} ${loc["select_done3"][language]} ${format_date(global_booking.selected_last_day)}`; } $('calendar_text').innerHTML = s; } // Page calendar back or forward function calendar_page(direction) { global_calendar.month_offset += parseInt(direction); global_calendar.month_offset = Math.max(0, global_calendar.month_offset); global_calendar.month_offset = Math.min(global_calendar.months_shown-1, global_calendar.month_offset); scroll_calendar(); } function day_over(event) { var t = event.target; // No starting day yet selected, start ok if (!global_booking.selected_first_day) { // Valid start date -> set hover, determine first last day (min stay) and check how many nights are possible to book if (t.start_ok) { global_calendar.hover_first_day = t.date; global_calendar.hover_first_last_day = dbdate_get(add_days_to_date(t.date, global_booking.minimum_nights)); global_calendar.following_nights = t.following_nights; // Invalid start date - reset hover } else { global_calendar.hover_first_day = false; global_calendar.hover_first_last_day = false; global_calendar.following_nights = 0; } // Startging day selected, end day not selected } else if (!global_booking.selected_last_day) { // Valid end day - at least one day after start, same continous block if (t.end_ok && t.date > global_booking.selected_first_day && t.last_cbid == global_booking.cbid) { global_calendar.hover_last_day = t.date; } else { global_calendar.hover_last_day = false; } } update_calendar(); } function day_out(event) { if (global_calendar.hover_last_day || global_calendar.hover_first_day) { global_calendar.hover_first_day = false; global_calendar.hover_first_last_day = false; global_calendar.hover_last_day = false; global_calendar.following_nights = 0; update_calendar(); } } function day_click(event) { var t = event.target; // No start day set or start and end day set (to reset) if (!global_booking.selected_first_day || ( global_booking.selected_first_day && global_booking.selected_last_day ) ) { // Valid start day if (t.start_ok) { global_booking.selected_first_day = t.date; global_booking.selected_last_day = false; global_booking.selected_first_last_day = dbdate_get(add_days_to_date(global_booking.selected_first_day, global_booking.minimum_nights)); global_booking.cbid = t.cbid; global_booking.last_cbid = t.last_cbid; global_booking.following_nights = t.following_nights; } } else { // Click on a date that is a valid end date and in the same continuous block if (t.end_ok && t.last_cbid == global_booking.last_cbid) { // Stay long enough -> continue booking process if (t.date >= global_booking.selected_first_last_day) { global_booking.selected_last_day = t.date; booking_show_prices(); // Stay too short -> go to hover mode (to show phone people stay is too short) } else { global_calendar.hover_first_day = false; global_calendar.hover_last_day = t.date; update_calendar(); return; } } } global_calendar.hover_first_day = false; global_calendar.hover_last_day = false; update_calendar(); } function is_weekend(weekday) { if (weekday == 0 || weekday == 6) return true; return false; } function weekday_shift(weekday) { if (language != "en") { weekday = (weekday+6)%7; } return weekday; } function weekday_unshift(weekday) { if (language != "en") { weekday = (weekday+1)%7; } return weekday; } function calendar_get_current() { global_calendar.current.date = new Date(); global_calendar.current.year = global_calendar.current.date.getFullYear(); global_calendar.current.month = global_calendar.current.date.getMonth(); global_calendar.current.time = global_calendar.current.date.getTime(); } // Scroll Calendar to selected month function scroll_calendar() { global_calendar.scroll_offset = global_calendar.month_offset * (global_calendar.month_width + global_calendar.month_spacer); $('calendar').scrollTo({ top: 0, left: global_calendar.scroll_offset, behavior: 'smooth' }); } // Resize Calendar for smol Displays function calendar_scale() { if (!$('calendar_container')) return; if (viewport_width >= 510) { $('calendar_container').style.transform = 'none'; } else { $('calendar_container').style.transform = `scale(${viewport_width/510})`; } } var legend_display_mode = "day"; function activate_extra(id) { optional_extras[id].active = true; update_legend(); } function deactivate_extra(id) { optional_extras[id].active = false; update_legend(); } function set_ng(number_guests) { if (number_guests >= 5) { if (!optional_extras[0].active) { optional_extras[0].active = true; update_legend(); } } else { if (optional_extras[0].active) { optional_extras[0].active = false; update_legend(); } } } function booking_toggle_extra(i) { if (optional_extras[i].active) { optional_extras[i].active = false; } else { optional_extras[i].active = true; } booking_update_pricing(); } function booking_update_pricing() { global_booking.user_timezone = user_timezone; let total = 0; let total_days = 0; const today = new Date(); const first_day = new Date(global_booking.selected_first_day); const last_day = new Date(global_booking.selected_last_day); const days_till_first = Math.round( ( first_day.getTime() - today.getTime() ) / (60*60*24*1000) ); const collateral_return = add_days_to_date(last_day, global_booking.collateral_return_window); let single_payment = false; let single_payment_enforce = false; let starts_soon = false; // If the first day is closer then X days, skip the whole pre-payment procedure if ( days_till_first < global_booking.single_payment_enforce ) { single_payment = true; single_payment_enforce = true; starts_soon = true; } let cancellation = []; if (starts_soon) { cancellation.push(loc.no_cancel[language]); } else { const collateral_cutoff = format_date(add_days_to_date(first_day, -global_booking.final_payment_latest)); cancellation.push(loc.cancel_until[language].replace('DATE', collateral_cutoff)); cancellation.push(loc.no_cancel_after[language].replace('DATE', collateral_cutoff)); } cancellation.push(loc.flex_ad[language]); // Count Total number of Booked Days for (let i=0; i${loc["your_planned_stay"][language]}`; for (let i=0; i`; const day_price = mo.prices[global_booking.price_category]; const item_count = mo.booked_count; const item_price = day_price*item_count; s += ` `; s += ` `; s += ` `; total += item_price; s += ``; } const price_base = total; for (var i=0; i= mo.min_days) { mo.active = true; } else { mo.active = false; } } // This auto-activates if booking duration greater or equal X days if (mo.max_days) { if (total_days <= mo.max_days) { mo.active = true; } else { mo.active = false; } } // This auto-activates if booking is more days ahead then X if (mo.days_ahead) { if (days_till_first >= mo.days_ahead) { mo.active = true; } else { mo.active = false; } } // If this is about single payment and single payment is enforced anyway, skip if (mo.single_payment && single_payment_enforce) { mo.active = false; } // This is not active, dont show, go to next if (!mo.active) continue; if (mo.single_payment) single_payment = true; let item_price = 0; if (mo.prices) { item_price = mo.prices[global_booking.price_category]; } if (mo.percentage) { item_price = Math.round(price_base * mo.percentage / 100); } s += ``; s += ``; s += ``; s += ``; if (mo.percentage) { s += ``; } else { s += ``; } s += ` `; s += ``; total += item_price; } s += ``; s += ``; s += ``; s += `
${loc["selection"][language]} ${loc["days"][language]} ${loc[legend_display_mode][language]} ${loc["price"][language]}
`; s += `
`; s += `
`+mo.name[language]+`${format_hidezero(item_count)}${format_money(day_price)}${format_money(item_price)}
`+mo.name[language]+`${mo.percentage}%${format_money(item_price)}
`; s += `${loc["total"][language]} ${format_money(total)}
`; var payments = []; var collateral = collaterals[global_booking.price_category]; global_booking.collateral = collateral; if (single_payment) { const payment_receivable_until = add_days_to_date(today, global_booking.prepayment_window_days); payments.push({ amount:total+collateral, description:loc.total_collateral[language], due_date:payment_receivable_until }); } else { const prepayment_receivable_until = add_days_to_date(today, global_booking.prepayment_window_days); const prepayment = Math.round(total*0.3); payments.push({ amount:prepayment, description:loc.prepayment[language], due_date:prepayment_receivable_until }); const final_payment_receivable_until = add_days_to_date(first_day, -global_booking.final_payment_latest); payments.push({ amount:total-prepayment+collateral, description:loc.remainder_collateral[language], due_date:final_payment_receivable_until }); } payments.push({ amount:collateral, description:loc.refund_collateral[language], due_date:collateral_return }); s += `

${loc.payment_plan[language]}

`; for (var i=0; i `; } s += `
${loc.due_date[language]} ${loc.amount[language]}
${pay.description} ${format_date(pay.due_date)} ${format_money(pay.amount)}
`; let pricing_html = s; s = `

${loc["your_price_category"][language]}

`; for (j=0; j `; } s += `
${icons["radio_buttons"][classname]} ${price_categories[j].name[language]} ${price_categories[j].description[language].join(", ")}
`; s += `

Extras

`; for (var i=0; i`; s += ``; s += ``; s += ``; s += ``; s += ``; } s += `
${icons["checkboxes"][classname]}`+mo.name[language]+`${mo.percentage}%${mo.description[language]}
`; s += `
${loc.book_now[language]}
`; $('booking_price_categories').innerHTML = s; pricing_html += `

${loc.cancellation_information[language]}

`; for (var i=0; i `; } pricing_html += `
• ${can}
`; $('booking_pricelist').innerHTML = pricing_html; } let global_floorplan = false; function floorplan() { this.level_width = 1920; this.level_height = 1200; this.level_x_offset = 0; this.level_y_offset = 0; this.level_scale = 0; this.levels = 4; this.level_current = 1; this.padding_width = 0; this.png_width = 2400; this.png_height = 2000; this.div = false; this.zoom_container = false; this.main_containers = []; this.transition_containers = []; this.current_container = false; this.camera_angle = 0; this.camera_animation = 0; this.camera_animation_direction = 0; this.camera_animation_angle = 0; this.auto_direction = 0; this.bobbels = floorplan_legend; this.seed = 1; this.animation_fps = 60; this.edit = false; this.preload_invoked = false; this.preload_image_buffer = []; this.preload_images = function() { if (this.preload_invoked) return; this.preload_invoked = true; for (let angle = 0; angle < 4; angle++) { for (let level = this.levels-1; level>=0; level--) { this.preload_image(`https://www.villa-musica.art/images/${level}_${angle}.webp`); } if (angle < 3) { for (let level = this.levels-1; level>=0; level--) { this.preload_image(`https://www.villa-musica.art/images/${level}_${angle}_t.webp`); } } } } this.preload_image = function(url) { var img=new Image(); img.src=url; this.preload_image_buffer.push(img); } this.init= function() { this.div = $('floorplan'); if (!this.div) return; const owner = this; this.zoom_container = div_create('floorplan_zoom_container', this.div); for (let angle = 0; angle < 4; angle++) { this.main_containers[angle] = { levels:[] }; this.main_containers[angle].div = div_create(".floorplan_container", this.zoom_container); for (let level = this.levels-1; level>=0; level--) { this.main_containers[angle].levels[level] = div_create(".floorplan_level", this.main_containers[angle].div); this.main_containers[angle].levels[level].style.backgroundImage = `url('https://www.villa-musica.art/images/${level}_${angle}.webp')`; } if (angle < 3) { this.transition_containers[angle] = { levels:[] }; this.transition_containers[angle].div = div_create(".floorplan_container", this.zoom_container); for (let level = this.levels-1; level>=0; level--) { this.transition_containers[angle].levels[level] = div_create(".floorplan_level", this.transition_containers[angle].div); this.transition_containers[angle].levels[level].style.backgroundImage = `url('https://www.villa-musica.art/images/${level}_${angle}_t.webp')`; } } } let navigator_html = ''; for (let level=0; level < this.levels; level++) { let level_name = floorplan_levels[level][language]; navigator_html += `
${level_name}
`; } navigator_html += `
` this.nav = div_create('floorplan_navigator', this.div, navigator_html); this.fpleft = div_create('fpleft', $('rotcont'), ` `); this.fpleft.onmousedown = function() { owner.rotate(-1)}; this.fpright = div_create('fpright', $('rotcont'), ` `); this.fpright.onmousedown = function() { owner.rotate(1)}; this.legend = div_create('floorplan_legend', this.div); for (var i=0; i${number} ${this.bobbels[i].name[language]}`); bob.div.onmouseenter=function() { owner.bobble_mouseover(j); }; bob.div.onmouseleave=function() { owner.bobble_mouseout(j); }; bob.div.onclick=function() { owner.bobble_click(j); }; bob.legend.onmouseenter=function() { owner.bobble_mouseover(j); }; bob.legend.onmouseleave=function() { owner.bobble_mouseout(j); }; bob.legend.onclick=function() { owner.bobble_click(j); }; if (bob.video) { const url = `${base_video_path}${bob.video}`; bob.video_div = div_create('.flv', this.zoom_container); bob.video_div.innerHTML = ``; } else if (bob.img) { const url = `${base_image_path}${bob.img}`; bob.img_div = div_create('.fli', this.zoom_container); bob.img_div.style.backgroundImage = `url('${url}')`; } } if (this.edit) { this.div.onmousemove = function(event) {owner.bobble_mousemove(event); }; } else { if (matchMedia('(hover:hover)').matches && false) { this.div.onmousemove = function(event) {owner.mousemove(event); }; this.div.onmouseleave = function(event) {owner.mouseleave(event); }; } } this.update(); } this.bobble_startmove = function(i, event) { this.bobmove = true; this.bobmove_i = i; this.bobmove_mx = event.clientX; this.bobmove_my = event.clientY; const bob = this.bobbels[i]; this.bobmove_x = bob.position[this.camera_angle][0]; this.bobmove_y = bob.position[this.camera_angle][1]; } this.bobble_stopmove = function(i, event) { this.bobmove = false; this.update_bobbels(); const s = `const floorplan_legend = `+JSON.stringify(this.bobbels, null, '\t')+';'; console.log(s); navigator.clipboard.writeText(s); } this.bobble_mousemove = function(event) { if (this.bobmove) { let mx = event.clientX; let my = event.clientY; const i = this.bobmove_i; const x_diff = mx-this.bobmove_mx; const y_diff = my-this.bobmove_my; const bob = this.bobbels[i]; bob.position[this.camera_angle][0] = this.bobmove_x + x_diff/this.level_width; bob.position[this.camera_angle][1] = this.bobmove_y + y_diff/this.level_height; const x = this.level_x_offset + this.level_width * (0.5+bob.position[this.camera_angle][0]); const y = this.level_y_offset + this.level_height * (0.5+bob.position[this.camera_angle][1]); bob.div.style.left = `${x}px`; bob.div.style.top = `${y}px`; } } this.update = function() { if (!this.div) return; if (this.camera_angle == 0) { this.fpleft.style.display = 'none'; } else { this.fpleft.style.display = ''; } if (this.camera_angle == 3) { this.fpright.style.display = 'none'; } else { this.fpright.style.display = ''; } this.padding_width = Math.min(150,viewport_width/30); this.level_width = Math.min(viewport_width-this.padding_width,(viewport_height)*this.png_width/(this.png_height-800)); this.level_scale = this.level_width/this.png_width; this.level_height = this.png_height*this.level_scale; this.level_x_offset = (viewport_width - this.level_width)/2; this.level_y_offset = (viewport_height - this.level_height)/2; for (let angle = 0; angle < 4; angle++) { const c = this.main_containers[angle].div; if (this.camera_angle == angle) { c.style.display = 'block'; this.current_container = c; } else { c.style.display = 'none' } c.style.left = `${this.level_x_offset}px`; c.style.top = `${this.level_y_offset}px`; c.style.width = `${this.level_width}px`; c.style.height = `${this.level_height}px`; c.style.backgroundSize = ''; for (let level = this.levels-1; level>=0; level--) { this.main_containers[angle].levels[level].style.opacity = (level >= this.level_current ? 1 : 0); } if (angle < 3) { const c = this.transition_containers[angle].div; c.style.display = 'none'; c.style.left = `${this.level_x_offset}px`; c.style.top = `${this.level_y_offset}px`; c.style.width = `${this.level_width}px`; c.style.height = `${this.level_height}px`; c.style.backgroundSize = ''; for (let level = this.levels-1; level>=0; level--) { this.transition_containers[angle].levels[level].style.opacity = (level == this.level_current ? 1 : 0); } } } for (var level=0; level${number} ${bob.name[language]}`; let x2 = x-140; let y2 = y+40; if ( bob.position[this.camera_angle][1] > 0) { y2 = y-200; } if (bob.video) { bob.video_div.style.left = `${x2}px`; bob.video_div.style.top = `${y2}px`; } if (bob.img) { bob.img_div.style.left = `${x2}px`; bob.img_div.style.top = `${y2}px`; } bob.active = true; bob.div.style.zIndex = 10; number++; } else { bob.active = false; bob.div.style.zIndex = -10; this.bobbels[i].div.style.opacity = 0; this.bobbels[i].legend.style.display = 'none'; } } } this.rotate = function(a) { if (this.camera_angle <= 0 && a < 0 ) return; if (this.camera_angle >= 3 && a > 0 ) return; if (this.camera_animation != 0) return; this.camera_angle = (this.camera_angle+a+4)%4; this.camera_animation_direction = a; if (a == 1) { this.camera_animation = 1; this.camera_animation_angle = (this.camera_angle+2)%3; } else { this.camera_animation = 19; this.camera_animation_angle = (this.camera_angle)%3; } this.hide_all_bobbels(); const owner = this; window.setTimeout(function() { owner.rotation_animate(); }, 1); } this.rotation_animate = function() { if (this.camera_animation > 0) { const ca = this.camera_animation-1; let x = (ca%5)*100/4; let y = Math.floor(ca/5)*100/3; for (let angle = 0; angle < 4; angle++) { const c = this.main_containers[angle].div; c.style.display = 'none' if (angle < 3 && angle == this.camera_animation_angle) { const c = this.transition_containers[angle].div; c.style.display = 'block'; const d = this.transition_containers[angle].levels[this.level_current]; d.style.backgroundSize = '500% 400%'; d.style.backgroundPosition = `${x}% ${y}%`; } } this.camera_animation += this.camera_animation_direction; if (this.camera_animation > 19) this.camera_animation = 0; const owner = this; window.setTimeout(function() {owner.rotation_animate(); }, 1000/this.animation_fps); } else { this.update(); } } this.mousemove = function(event) { let x = event.clientX; let y = event.clientY; const rect = this.current_container.getBoundingClientRect(); const container = $('floorplan').getBoundingClientRect(); if (x < rect.left|| y < rect.top || x > rect.left+rect.width || y > rect.top+rect.height || x < container.left + 200 || x > container.left+container.width - 200) { this.zoom_container.style.transform = 'scale(1)'; } else { this.zoom_container.style.transform = 'scale(1.5)'; this.zoom_container.style.transformOrigin = `${x}px ${y}px`; } } this.mouseleave = function(event) { this.zoom_container.style.transform = 'none'; } this.bobble_mouseover = function(i) { const bob = this.bobbels[i]; if (!bob.active) return; bob.legend.className = 'fll_selected'; bob.div.className = 'flp_selected'; if (bob.img_div) { bob.img_div.className = 'fli_selected'; } if (bob.video_div) { bob.video_div.className = 'flv_selected'; const video_id = `flv_${i}`; const video_object = $(video_id); if (video_object) video_object.play(); } } this.bobble_mouseout = function(i) { const bob = this.bobbels[i]; bob.legend.className = 'fll'; bob.div.className = 'flp'; if (bob.img_div) { bob.img_div.className = 'fli'; } if (bob.video_div) { bob.video_div.className = 'flv'; const video_id = `flv_${i}`; const video_object = $(video_id); if (video_object) video_object.pause(); } } this.bobble_click = function(i) { const bob = this.bobbels[i]; if (!bob.active) return; if (!bob.video_div) return; const video_id = `flv_${i}`; const video_object = $(video_id); if (video_object) { if (video_object.paused) { video_object.play(); } else { video_object.pause(); } } } this.goto_level = function(level) { this.level_current = level; this.update(); goto_section("floorplan"); hamburger_hide(); } this.init(); } function populate_forms() { for (var form_name in global_forms) { populate_form(form_name); } } function populate_form(form_name) { const form_div_id = `f_${form_name}`; const form = global_forms[form_name]; if (!$(form_div_id)) return; s = `

${form.title[language]}

${form.description[language]}

`; for (var i=0;i
${field.label[language]}${req}
`; for (var j=1;j${label}`; } s += `
`; } else if (type == "pulldown") { let selected_index = 0; // Preset language and country if (field.field == "language_id" && language == "de") selected_index = 1; if (field.field == "language_id" && language == "en") selected_index = 2; if (field.field == "language_id" && language == "ro") selected_index = 4; if (field.field == "country_id" && language == "ro") selected_index = 37; s += `
`; s += `
`; } else if (type == "div") { continue; } else if (type == "var") { continue; } else if (type == "bigtext") { s += `
`; s += `
`; } else if (type == "mediumtext") { s += `
`; s += `
`; } else if (type == "checkbox") { s += `
`; s += ``; s += `
`; } else if (type == "error") { s += `
`; s += ``; s += `
`; field.required = true; // This will block form sending if the error is displayed } else { s += `
`; s += ``; s += `
`; } } s += `
${form.send_button[language]}
`; $(form_div_id).innerHTML = s; form_evaluate_conditions(form_name); } function form_keydown(event, form_name) { if (event.key == "Enter") send_form(form_name); } function form_evaluate_conditions(form_name) { const form = global_forms[form_name]; form.fields_by_field = []; for (var i=0;i${form.title[language]}
`; $(form_div_id).innerHTML = s; if (global_backend_data.turbotest) { result["turbotest"] = "test" }; await backend_connect("submit_form",{ form_data: result }); s = `

${form.title[language]}

${form.success[language]}

`; $(form_div_id).innerHTML = s; if (global_backend_data.turbotest) { turbotest_ok(); } if (typeof gtag_report_conversion === "function") gtag_report_conversion(); } else { if (global_backend_data.turbotest) { turbotest_fail(); } } } function get_value(name, type, vl_name) { if (type == "error") return ""; if (type == "text") return $(name).value; if (type == "bigtext" || type == "mediumtext") return $(name).value; if (type == "div") return $(name).innerHTML; if (type == "pulldown") { const i = $(name).selectedIndex; if (i == 0) return ""; return vl[vl_name][language][i]; } if (type == "email") { if (!$(name).checkValidity()) return ""; return $(name).value; } if (type == "checkbox") { if ($(name).checked) { return "on"; } else { return ""; } } if (type == "radio") { let a = document.querySelector('input[name="'+name+'"]:checked'); if (!a) return ""; return a.value; } } var gallery_image_path = ""; var gallery_image_count = 0; var gallery_selected_image = 0; var gallery_thumb_width = 160; var gallery_mini_spacer = 5; function build_gallery(count, target, image_path, thumb_path) { var thumb_width = gallery_thumb_width; var thumb_height = 100; var spacer = 120; var smol_spacer = 20; var mini_spacer = gallery_mini_spacer; var main_bottom = spacer + thumb_height + smol_spacer; var s = ``; s += ``; var scroller_width = thumb_width * count + mini_spacer * (count+1); var scroller_height = thumb_height + mini_spacer * 2; gallery_image_path = image_path; gallery_image_count = count; var scroller = ``; s += scroller; $(target).innerHTML += s; gallery_show_selected(); } function gallery_next() { gallery_selected_image = (gallery_selected_image+1)%gallery_image_count; gallery_show_selected(); } function gallery_select(i) { gallery_selected_image = i; gallery_show_selected(); } function gallery_show_selected() { var image_url = gallery_image_path + format_int(gallery_selected_image,5) + ".jpg"; $('gallery_main_show').style.backgroundImage = `url('${image_url}')`; for (var i=0;i current_x + viewport_width - 400 - gallery_thumb_width) { $('gallery_scroll_container').scrollLeft = x - viewport_width + 400 + gallery_thumb_width; } var next_image = gallery_selected_image+1; if (next_image >= gallery_image_count) return; var image_url = gallery_image_path + format_int(next_image,5) + ".jpg"; $('gallery_preloader').style.backgroundImage = `url('${image_url}')`; } global_hyperchat = false; function hyperchat_controller() { /* this.last_date = 0; this.last_sender = 0; this.typing = false; this.u2r = []; this.last_seen_balls = []; */ this.last_added_div = false; this.messages = []; this.last_message_id = 0; this.last_added_message_id = 0; this.last_seen_message_id = 0; if (!$('chat_launcher')) return; $('chat_launcher').innerHTML = icons.chat; $('closebutton').innerHTML = icons.close; $('chat_send_text').innerHTML= icons.send; this.canary_check_interval = 3000; this.canary_timestamp = false; this.canary_url = false; // Canary Check this.canary_check = async function() { if (!this.canary_url) return; const url = this.canary_url + `?a=${Math.random()}`; // Get and decode Result try { const result = await fetch(url); const timestamp = parseInt(await result.text()); if (this.canary_timestamp != timestamp) { if (this.canary_timestamp) { backend_connect('chat_check_status'); } this.canary_timestamp = timestamp; } } catch (e) { } } this.keypress = function(event) { if(event.key == "Enter") { this.submit_form(); stop_bubble(event); this.typing = false; } else { this.set_typing(); } } this.submit_form = function() { const form_id = `chat_input_text`; let message = $(form_id).value; message = message.trim(); $(form_id).value = ''; this.send_message(message); } this.send_message = function(message) { backend_connect('send_chat_message', {message:message }); } this.set_typing = async function() { if (this.typing) return; this.typing = true; backend_connect('chat_set_typing'); } this.close = function() { $('chat_room').style.display = 'none'; } this.show = function() { $('chat_room').style.display = ''; } this.u2r_update = async function() { for (var j=0;j 0 && last_seen <= this.last_added_message_id) { if (!this.last_seen_balls[user_id]) { const div = document.createElement("div"); div.innerHTML = `
${vl.hyperchat_users[user_id]}
`; div.className = 'last_seen_ball_container'; this.last_seen_balls[user_id] = div; } const div_id = `hpcm${last_seen}`; const msg = $(div_id); if (msg) { if (msg.nextSibling) { msg.parentNode.insertBefore(this.last_seen_balls[user_id], msg.nextSibling); } else { msg.parentNode.appendChild( this.last_seen_balls[user_id] ); } } } } } this.room_click = async function() { if (this.last_added_message_id > this.last_seen_message_id) { this.last_seen_message_id = this.last_added_message_id; backend_connect('set_chat_last_seen', { last_seen_message_id:this.last_seen_message_id} ); this.check_unseen(); } } this.check_unseen = function() { if ( this.last_added_message_id > this.last_seen_message_id ) { this.show(); // $(this.target_id).className = 'hyperchat_room_unseen'; this.last_added_div.scrollIntoView(); } else { // $(this.target_id).className = 'hyperchat_room'; } } this.read_messages = function(hyperchat) { if (hyperchat.canary_url) { this.canary_url = hyperchat.canary_url; } for (var i=0; i this.last_message_id) { this.last_message_id = parseInt(hyperchat.last_message_id); } this.check_unseen(); } this.show_online = function(online) { if (online == true) { $('chat_online').innerHTML = 'Online'; $('online_explainer').style.display = ''; $('offline_explainer').style.display = 'none'; } else { $('chat_online').innerHTML = 'Offline'; $('online_explainer').style.display = 'none'; $('offline_explainer').style.display = ''; } } this.add_message = function(message) { if (parseInt(message.id) <= this.last_added_message_id) return; this.last_added_message_id = parseInt(message.id); const div = document.createElement("div"); div.id = `hpcm${message.id}`; let s = ''; const new_date = new Date(message.sent_date); const new_date_formatted = format_datetime(message.sent_date); const sender_me = message.sender_me; const time_difference_minutes = (new_date.getTime() - this.last_date) / (1000*60); this.last_date = new_date.getTime(); if (time_difference_minutes > 5) { s = `
${new_date_formatted}
`; } const msg = format_chat_message(message.message) if (sender_me) { s += `
${msg}
`; } else { s += `
${msg}
`; } div.innerHTML = s; $('chat_content').appendChild(div); this.last_added_div = div; div.scrollIntoView(); } this.init = function() { const owner = this; window.setInterval(function() { owner.canary_check() }, owner.canary_check_interval); } this.init(); } function format_chat_message(s) { const orig_s = s; if (s.substring(0,9) == "image:://") { const url = s.substring(9); return ``; } s = s.replaceAll(':D','😀'); s = s.replaceAll(':-D','😀'); s = s.replaceAll(':)','🙂'); s = s.replaceAll(':-)','🙂'); s = s.replaceAll(':|','😐'); s = s.replaceAll(':-|','😐'); s = s.replaceAll(':(','😟'); s = s.replaceAll(':-(','😟'); s = s.replaceAll('<3','❤️'); s = s.replaceAll(':p','😜'); s = s.replaceAll(':-p','😜'); s = s.replaceAll(':-*','😘'); s = s.replaceAll(':*','😘'); s = s.replaceAll('8)','😎'); s = s.replaceAll('8-)','😎'); s = s.replaceAll(':-B','😁'); s = s.replaceAll(':B','😁'); s = s.replaceAll(':cow:','🐮'); s = s.replaceAll('<','<'); s = s.replaceAll('>','>'); s = s.replaceAll('\n','
'); s = s.replace( /(http:\/\/[^\s]+)/gi , '$1' ); s = s.replace( /(https:\/\/[^\s]+)/gi , '$1' ); if (s.length <= 2) { s = `${s}`; } return s; }; const icons = { "close":``, "left":``, "right":``, "bell":``, "key":``, "toggle_text":``, "chat":``, "send":``, radio_buttons:{ selectable:``, selected:`` }, checkboxes: { selectable:``, selected:`` }, checkmark: ``, arrow_right:``, } const country_flags = { "en":` `, "de":` `, "bg":` `, "ro":` ` } const arrow_left = icons.left; const arrow_right = icons.right; const icon_close = icons.close; function key_visual_enhance() { var x = document.querySelectorAll('.key_visual'); for (var i = 0; i < x.length; i++) { const k = x[i]; const images = k.dataset.images; const parent = k.parentNode; // Typically a pic_box if (images) { const image_list = images.split(';'); const iml = image_list.length; const kvb = document.createElement("div"); kvb.className = "key_visual_placeholder"; k.appendChild(kvb); const kv = document.createElement("div"); kv.className = "key_visual_main"; k.appendChild(kv); if (k.dataset.features == 'playbutton') { let playbutton = document.createElement("div"); playbutton.innerHTML = ``; playbutton.onclick = video_play; playbutton.className = "playbutton"; k.appendChild(playbutton); } let nav = document.createElement("div"); nav.className = 'key_visual_navigator'; const back = document.createElement("a"); back.innerHTML = arrow_left; back.className = 'arrow'; nav.appendChild(back); nav.buttons = []; nav.selected_index = 0; for (var j=0; j 0) { nav.buttons[nav.selected_index-1].onclick(); } else { picbox_nav_back_click(e); } } nav.forward = function(e) { const pic_box_class = kv.parentNode.parentNode.className; if (pic_box_class != "pic_box_enlarged") return; if (nav.selected_index < nav.button_count-1) { nav.buttons[nav.selected_index+1].onclick(); } else { picbox_nav_forward_click(e); } } const fwd = document.createElement("a"); fwd.innerHTML = arrow_right; fwd.className = 'arrow'; back.onclick = nav.backward; fwd.onclick = nav.forward; nav.appendChild(fwd); kv.onclick = nav.forward; // Add Nav (only if more than 1 pic) /* if (iml > 1) { */ k.appendChild(nav); if (parent.className == "pic_box") { parent.nav = nav; } /* } */ } } } var hamburger_shown = false; var position_informer_trigger = false; var position_informer_section = ''; function nav_update() { var children = document.querySelectorAll("#nav > a, #info_menu > a, #bottom_nav > a"); var nav_mode = -1; var hide_chat = false; for(i=0;i -200) nav_mode = 0; } else { nav_mode = 1; } if (nav_mode == 0) { c.classList.add("selected"); position_informer_set(c.dataset.section); if (c.dataset.nochat) hide_chat= true; if (c.dataset.preloadfloorplan && global_floorplan) global_floorplan.preload_images(); } else { c.classList.remove("selected"); } } } } if ($('chat_launcher')) { if (hide_chat) { $('chat_launcher').style.opacity = 0; } else { $('chat_launcher').style.opacity = 1; } } } function position_informer_set(section) { if (section != position_informer_section) { position_informer_section = section; if (position_informer_trigger) { clearTimeout(position_informer_trigger); position_informer_trigger = false; } position_informer_trigger = setTimeout(position_informer, 1000); } } function position_informer() { backend_connect("view_"+position_informer_section); } function hamburger_click() { hamburger_toggle(); } function hamburger_toggle() { if (hamburger_shown) { hamburger_hide(); } else { hamburger_show(); } } function hamburger_hide() { $('nav').style.setProperty('--menu-flip', "none"); hamburger_shown = false; } function hamburger_show() { $('nav').style.setProperty('--menu-flip', ""); hamburger_shown = true; } var info_menu_shown = false; function info_menu_over() { if (matchMedia('(hover:hover)').matches) { info_menu_show(); } } function info_menu_click() { info_menu_toggle(); } function info_menu_toggle() { if (info_menu_shown) { info_menu_hide(); } else { info_menu_show(); } } function info_menu_hide() { if (!$('info_menu')) return; $('info_menu').style.setProperty('--info-menu-flip', "none"); info_menu_shown = false; } function info_menu_show() { if (!$('info_menu')) return; $('info_menu').style.setProperty('--info-menu-flip', "block"); info_menu_shown = true; } // User clicked on nav button function nav_click(event) { let target = event.target; while (!target.dataset.section) target = target.parentElement; // Determine target section var section = target.dataset.section; // And go there goto_section(section); // Hide Hamburger Nav hamburger_hide(); } // Go to a specific section function goto_section(section) { current_section = section; if (content == "villa" || content == "academy") { history.pushState( {}, "", language+".html#"+section); } else if (content == "terms") { history.pushState( {}, "", "termsandconditions_"+language+".html"); } // Close all Pic Boxes picbox_close_all(); var target = $(section); var parent_group_element = target.parentElement; var content_group = parent_group_element.id; display_content_group(content_group); var rect = target.getBoundingClientRect(); var target_top = rect.top; window.scrollTo( { left:0, top:window.scrollY+target_top-nav_height, behavior:"smooth"} ); info_menu_hide(); video_reset(); } function display_content_group(content_group) { var children = document.querySelectorAll("div.main_container > div.content_group"); for(i=0;i

${parts[0]}

${parts[1]}
${loc.book_now[language]}

${pex[i]}

`; } s += `
${academy_snippets.special_offer[language]}
`; $('academy_pricelist').innerHTML = s; } function update_writing_pricelist() { if (!$('writing_pricelist')) return; $('special_offer_1').innerHTML = writing_snippets.special_offer[language]; $('writing_duration_1').innerHTML = writing_snippets.writing_duration[language]; $('writing_duration_2').innerHTML = writing_snippets.writing_duration[language]; $('cancellation_deadline').innerHTML = writing_snippets.cancellation_deadline[language]; const p = vl.writing_prices[language]; const pex = vl.writing_prices_explanation[language]; let s = ''; for (var i=1; i

${parts[0]}

${parts[1]}
${loc.book_now[language]}

${pex[i]}

`; } s += `
${writing_snippets.special_offer[language]}
`; $('writing_pricelist').innerHTML = s; } function update_pricelist() { if (!$('pricelist')) return; // OUR PRICES - header s = `

${loc["our_prices"][language]}

`; s += ``; // Headers s += ` `; for (j=0; j${price_categories[j].name[language]}`; } s += ` `; // OUR PRICES - calendar modes for (let i=0; i`; s += ``; for (j=0; j${format_money(week_price)}`; } else { s += ``; } } s += ``; } // Other priced items (currently only cleaning) for (var i=0; i`; s += ``; s += ``; for (j=0; j${format_money(mo.prices[j])} `; } s += ``; } s += `
`; s += `
`; s += `
`+mo.name[language]+``+mo.months_text[language]+`${format_money(day_price)}
`+mo.name[language]+`
`; // Day/Week mode for (var i=0; i<2; i++) { var classname = "selectable"; if (i == global_booking.week_mode) { classname = "selected"; } s += ` ${icons["radio_buttons"][classname]} ${loc["price_display"][i][language]} `; } $('pricelist').innerHTML = s; // Price Categories s = `

${loc["our_price_categories"][language]}

`; for (j=0; j${price_categories[j].name[language]}`; } s += ``; s += ``; for (j=0; j• ${price_categories[j].description[language].join('
• ')}`; } s += `
`; s += ``; for (j=0; j ${loc.book_now[language]} `; } s += ``; s += `
`; $('price_categories').innerHTML = s; s = `

${loc["discounts_and_extra_features"][language]}

`; for (var i=0; i`; s += ``; s += ``; s += ``; s += ``; } s += `
`+mo.name[language]+`${mo.percentage}%${mo.description[language]}
`; $('price_extras').innerHTML = s; s = `

${loc["amenities"][language]}

`; for (var i=0; i`; s += ``; s += ``; } s += `
• `+mo[language]+`
`; if ($('price_included')) $('price_included').innerHTML = s; } // Globals for language and current section var language = "en"; var user_timezone = "Europe/Vienna"; var current_section = "welcome"; var content = "villa"; // Globals for Viewport var viewport_width = 1920; var viewport_height = 1200; var nav_height = 50; const global_backend_data = { api_url: 'https://61p6t9eun9.execute-api.eu-central-1.amazonaws.com/', service: 'open/api/index', site_id: 1, shard_id: 200 } // Weather API URL var weather_api_url = 'https://api.openweathermap.org/data/2.5/weather?q=Baltschik&APPID=224f460f46cb34626aafe347e0ed29af&units=metric&lang='; var weather_api_icon_base_url = 'https://openweathermap.org/img/wn/'; async function get_current_weather() { const url = weather_api_url+language; const weather = await fetch(url); const json = await weather.json(); const icon_url = weather_api_icon_base_url + json.weather[0].icon + '@2x.png'; if (json.main.temp >= 15) { const text = `${json.weather[0].description}` + Math.round(json.main.temp)+'° '+json.weather[0].description; $('nav_spacer').innerHTML = text; } } const base_image_path = 'https://www.villa-musica.art/images/'; const base_thumb_path = 'https://www.villa-musica.art/images/thumbs/'; const base_video_path = 'https://www.villa-musica.art/videos/'; // Init size after loading function init(l, c) { // Get content ("villa" or "academy") if (c) content = c; // Get current URL const current_url = document.URL; const url_parts = current_url.split('#'); const search_params = new URL(document.URL).searchParams; global_hyperchat = new hyperchat_controller(); // Determine Language language = l; // Determine Time Zone if (Intl && Intl.DateTimeFormat) { const tz = Intl.DateTimeFormat().resolvedOptions().timeZone; user_timezone = tz; } // Create Floor PLan global_floorplan = new floorplan(); // Set Scroll and Resize Behaviours document.onscroll = on_scroll; window.onresize = on_resize; if (content == "villa") { global_backend_data.site_id = 1; // Build Calendar backend_connect("get_stays", false, calendar_intialize); } else if (content == "terms") { global_backend_data.site_id = 1; } else if (content == "academy") { global_backend_data.site_id = 2; } else if (content == "writing") { global_backend_data.site_id = 6; } rental_condition_replacer(); // Keep in touch with server while on site // setInterval(backend_connect, 30000); // Start Loading Key Visuals and Build Navigation key_visual_enhance(); // Enhance the pic boxes picbox_enhance(); // Set the language buttons if ($('flag_de')) $('flag_de').innerHTML = country_flags.de; if ($('flag_en')) $('flag_en').innerHTML = country_flags.en; if ($('flag_ro')) $('flag_ro').innerHTML = country_flags.ro; // Get Viewport Size && Build Floor Plan on_resize(); // Get Weather Report get_current_weather(); // If current URL contains anchor, go to anchor if (url_parts.length > 1) { var section = url_parts[1]; goto_section(section); } // Update pricelist update_pricelist(); update_academy_pricelist(); update_writing_pricelist(); // Populate forms populate_forms(); // TurboTest if (search_params.get('turbotest')) { window.addEventListener("message", turbotest, false); global_backend_data.turbotest = true; turbotest_ok(); } } // Get Viewport Size && Build Floor Plan function on_resize() { // Update Viewport Size viewport_width = window.innerWidth; viewport_height = window.innerHeight-100; // Resize Floorplan (if exists) global_floorplan.update(); // Scale calendar(if exists) calendar_scale(); // Scrolling Position may have changed on_scroll(); video_resize(); } // Scroll-Based Activities function on_scroll() { // Check if navigation highlights are current nav_update(); } // Condition replacer function rental_condition_replacer() { var rc = document.querySelectorAll(".rental_condition"); rc.forEach(function(item) { item.innerHTML = rental_conditions[item.innerHTML]; }); } function $(s) { return document.getElementById(s); } function format_int(n,l) { var s = n.toString(); while (s.length < l) s = "0"+s; return s; } function format_hidezero(n) { if (n == 0) return ""; return n.toString(); } function format_date(date_string) { const d = new Date(date_string); const options = { year: 'numeric', month: 'long', day: 'numeric' }; let locale = 'de-DE'; if (language == 'en') { locale = 'en-UK'; } return d.toLocaleDateString(locale, options); } function format_datetime(date_string) { const d = new Date(date_string); var options = { year: '2-digit', month: '2-digit', day: '2-digit', hour:'2-digit', minute:'2-digit', second:undefined }; let locale = 'de-DE'; if (language == 'en') { locale = 'en-UK'; } return d.toLocaleString(locale, options); } function format_date_short(date_string) { const d = new Date(date_string); const options = { year: '2-digit', month: '2-digit', day: '2-digit' }; let locale = 'de-DE'; if (language == 'en') { locale = 'en-UK'; } return d.toLocaleDateString(locale, options); } function add_days_to_date(date, days) { var result = new Date(date); result.setDate(result.getDate() + days); return result; } function dbdate_get(d) { return d.toISOString().substring(0,10); } function format_money(n) { if (n==0) return ""; let s = ''; let separator = ','; if (language == "de") separator = "."; while (n>=1000) { s = separator + format_int(n%1000,3) + s; n = Math.floor(n/1000); } s = n.toString() + s + "€"; return s; } function dom_clear(element) { while (element.firstChild) { element.removeChild(element.firstChild); } } function svg_text(x,y,text,color,anchor,style,parent) { var ob = document.createElementNS("http://www.w3.org/2000/svg", "text"); parent.appendChild(ob); ob.setAttribute('x', x); ob.setAttribute('y', y); ob.setAttribute('fill', color); ob.setAttribute('text-anchor', anchor); ob.setAttribute('style', style) ob.textContent = text; return ob; } function svg_filled_rect(x,y,width,height,color,parent) { var ob = document.createElementNS("http://www.w3.org/2000/svg", "rect"); parent.appendChild(ob); ob.setAttribute('x', x); ob.setAttribute('y', y); ob.setAttribute('width', width); ob.setAttribute('height', height); ob.setAttribute('fill', color); return ob; } function svg_path(path,color,parent) { var ob = document.createElementNS("http://www.w3.org/2000/svg", "path"); parent.appendChild(ob); ob.setAttribute('d', path); ob.setAttribute('fill', color); return ob; } function svg_line(x1,y1,x2,y2,color,parent) { var ob = document.createElementNS("http://www.w3.org/2000/svg", "line"); parent.appendChild(ob); ob.setAttribute('x1', x1); ob.setAttribute('y1', y1); ob.setAttribute('x2', x2); ob.setAttribute('y2', y2); ob.setAttribute('stroke', color); return ob; } function div_create(id, parent, innerHTML) { const div = document.createElement("div"); if (id) { if (id.substr(0, 1) == ".") { div.className = id.substr(1); } else { div.id = id; } } parent.appendChild(div); if (innerHTML) { div.innerHTML = innerHTML; } return div; } function stop_bubble(e) { if (!e) e = window.event; //IE9 & Other Browsers if (e.stopPropagation) { e.stopPropagation(); } //IE8 and Lower else { e.cancelBubble = true; } } function random_alphanum(length) { var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; var result = ''; for (var i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)]; return result; } function getDistanceFromLatLonInKm(lat1, lon1, lat2, lon2) { var R = 6371; // Radius of the earth in km var dLat = deg2rad(lat2-lat1); // deg2rad below var dLon = deg2rad(lon2-lon1); var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.sin(dLon/2) * Math.sin(dLon/2) ; var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); var d = R * c; // Distance in km return d; } function deg2rad(deg) { return deg * (Math.PI/180) } function turbotest_ok() { if (global_backend_data.turbotest) { window.parent.postMessage({ ok:true}, '*'); } } function turbotest_fail() { if (global_backend_data.turbotest) { window.parent.postMessage({ ok:false}, '*'); } } function turbotest(message) { const a = message.data; if (a.show_form) { $(a.show_form).scrollIntoView(); global_backend_data.turbotest_form = $(a.show_form); turbotest_ok(); } if (a.nav_click_section) { const anchors = document.querySelectorAll('a'); anchors.forEach((c) => { if (c.dataset && c.dataset.section == a.nav_click_section) { c.click(); turbotest_ok(); } }); } if (a.form_fill) { const inputElements = global_backend_data.turbotest_form.querySelectorAll('input,textarea'); inputElements.forEach((input) => { let id = input.id; let value = input.getAttribute('autocomplete'); if (value == "email") value = "ich@janstudt.de"; if (value == "tel") value = "+1-212-555-2368"; if (value == "given-name") value = "Lönäpüßte"; if (value == "family-name") value = "Könügälößen"; if (value == "comment") value = a.comment; if (value == "street-address") value = "Example Street 1\n12345 Zipcodeburg\nTestcountry"; if (!value) value = id; if (id) { input.value = value; } if (input.type == "checkbox") input.checked = true; }); const selects = global_backend_data.turbotest_form.querySelectorAll('select'); selects.forEach((input) => { input.selectedIndex = 1; }); const buttons = global_backend_data.turbotest_form.querySelectorAll('span.booking_button'); buttons.forEach((input) => { input.click(); }); } } function video_resize() { if (viewport_width < 800) return; // Resize and position the Video const video_aspect = 1920/800; const video_width = Math.min(viewport_width, viewport_height * video_aspect ); const video_height = video_width / video_aspect; const video_margin_w = (viewport_width - video_width)/2; const video_margin_h = (viewport_height - video_height)/2; const v = $('key_video'); if (v) { v.style.left = video_margin_w+'px'; v.style.top = video_margin_h+'px'; v.style.width = video_width+'px'; v.style.height = video_height+'px'; v.onplay = video_onplay; } const s = $('key_video_smol'); if (s) { s.onplay = video_count_view; } } function video_play() { const v = $('key_video'); if (v) { v.play(); } } function video_onplay() { // Make sure Video Dimensions are correct video_resize(); // Push Video in Front of static Picture and Text $('key_video_container').style.zIndex = 99; // Make sure container is scrolled all the way to the top window.scroll(0,0); video_count_view(); } function video_count_view() { backend_connect("key_video_play"); } function video_pause() { const v = $('key_video'); if (v) { v.pause(); } } // On nav interaction, stop the video and hide the video function video_reset() { if (!$('key_video_container')) return; video_pause(); $('key_video_container').style.zIndex = ''; } function writing_booking(price_category) { $('f_writing_booking_writing_price').selectedIndex = price_category; goto_section("writing_booking"); } var global_booking = { "progress":0, "price_category":0, "week_mode":0, "prepayment_window_days":5, "final_payment_latest":90, "single_payment_enforce":100, "collateral_return_window":10, collateral:0, "minimum_nights":4, "selected_first_day":false, "selected_last_day":false, "selected_first_last_day":false, following_nights:0 } const academy_snippets = { "academy_duration": { "de":"03.08. - 10.08. 2025", "en":"03 August - 10 August 2025" }, "cancellation_deadline": { "de":"30.03.2025", "en":"30 March 2025" }, "special_offer": { "de":"Music und Spass!", "en":"Music and Fun!" }, "outside_eu" : { "de":"Teilnahme an der Summer Academy ist leider nur für EU-Bürger möglich.", "en":"Participation in the Summer Academy is only possible for EU citizens." } }; const writing_snippets = { "writing_duration": { "de":"12.10. - 19.10. 2024", "en":"12. October - 19. October" }, "cancellation_deadline": { "de":"30.03.2024", "en":"30 March 2024" }, "special_offer": { "de":"Schreiben und Urlaub!", "en":"Writing and Fun!" } }; const calendar_modes = [ { "name": { "de": "Hauptsaison", "en": "High season", "ro": "Sezon de vârf" }, "bookable": true, "prices": [295, 325, 395, 495], "months_text": { "de": "Juni - August", "en": "June - August", "ro": "Iunie - August" }, "months": [7, 8], "color": "#feb", "color_booked": "#dea300", "color_error": "#dd3300", "booked_count": 0 }, { "name": { "de": "Nebensaison", "en": "Mid season", "ro": "Sezon mediu" }, "bookable": true, "prices": [195, 275, 355, 455], "months_text": { "de": "Andere Monate", "en": "Other months", "ro": "Alte luni" }, "months": [6, 9], "color": "#efc", "color_booked": "#96e600", "color_error": "#dd3300", "booked_count": 0 }, { "name": { "de": "Zwischensaison", "en": "Low season", "ro": "Sezon scăzut" }, "bookable": false, "prices": [250, 330, 410], "months_text": { "de": "Mai, Okt.", "en": "May, Oct.", "ro": "Mai, oct." }, "months": [5, 10], "color": "#ced", "color_booked": "#00dd75", "color_error": "#dd3300", "booked_count": 0 }, { "name": { "de": "Wintersaison", "en": "Winter season", "ro": "Sezon de iarnă" }, "bookable": false, "prices": [170, 250, 330], "months_text": { "de": "Nov. - April", "en": "Nov. - April", "ro": "Nov. - aprilie" }, "months": [1, 2, 3, 4, 11, 12], "color": "#cef", "color_booked": "#0096e6", "color_error": "#dd3300", "booked_count": 0 }, { "name": { "de": "Nicht buchbar", "en": "Unavailable", "ro": "Indisponibil" }, "bookable": false, "color": "#ccc", "booked_count": 0 } ] const price_categories = [ { "name": { "de": "Villa für vier", "en": "Villa for Four", "ro": "Vila pentru patru" }, "description": { "de": ["2 Schlafzimmer", "Bis zu 4 Gäste", "3 Badezimmer", "1 Küche"], "en": ["2 Guest Rooms", "Up to 4 Guests", "3 Bathrooms", "1 Kitchen"], "ro": ["2 dormitoare", "Până la 4 oaspeți", "3 băi", "1 bucătărie"] } }, { "name": { "de": "Villa", "en": "Villa", "ro": "Vilă" }, "description": { "de": ["4 Schlafzimmer", "Bis zu 8 Gäste", "3 Badezimmer", "1 Küche"], "en": ["4 Guest Rooms", "Up to 8 Guests", "3 Bathrooms", "1 Kitchen"], "ro": ["4 dormitoare", "Până la 8 oaspeți", "3 băi", "1 bucătărie"] } }, { "name": { "de": "Villa Plus", "en": "Villa Plus", "ro": "Vilă Plus" }, "description": { "de": ["6 Schlafzimmer", "Bis zu 12 Gäste", "4 Badezimmer", "2 Küchen"], "en": ["6 Guest Rooms", "Up to 12 Guests", "4 Bathrooms", "2 Kitchens"], "ro": ["6 dormitoare", "Până la 12 oaspeți", "4 băi", "2 bucătării"] } } ] const collaterals = [ 200,300,400,500 ] // This is now handled by the "Amenities" Section const included_services = [ { "de": "Gratis WLAN / 200MBit Glasfaser", "en": "Free Wi-Fi (200MBit connection)", "ro": "Wi-Fi gratuit (conexiune de 200MBit)" }, { "de": "Villa zur Alleinnutzung - nur für Sie!", "en": "Villa only for you - complete privacy", "ro": "Vilă doar pentru tine - intimitate completă" }, { "de": "Nutzung Poolbereich mit Whirlpool", "en": "Pool area with whirlpool", "ro": "Zonă de piscină cu jacuzzi" }, { "de": "Schlaf- und Wohnbereiche voll klimatisiert", "en": "All guestrooms and living rooms climatized", "ro": "Toate camerele și livingurile climatizate" }, { "de": "Smart TVs", "en": "Smart TVs", "ro": "Televizoare inteligente" }, { "de": "Spülmaschine", "en": "Dishwasher", "ro": "Mașină de spălat vase" }, { "de": "Waschmaschine & Trockner", "en": "Washer & Dryer", "ro": "Mașină de spălat & uscător" }, { "de": "Alle Nebenkosten wie Strom und Wasser inklusive", "en": "All utilities (power, water etc.) included", "ro": "Toate utilitățile (electricitate, apă etc.) incluse" } ] const optional_extras = [ { "name": { "de": "Endreinigung", "en": "Cleaning", "ro": "Curățenie" }, "prices": [54, 155, 195, 235], "active": true }, { "name": { "de": "Villa FLEX", "en": "Villa FLEX", "ro": "Vilă FLEX" }, "description": { "de": "Stornierung bis 48 Stunden vor Anreisetag möglich mit voller Erstattung", "en": "Cancellation possible until 48 hours before arrival with full refund", "ro": "Anulare posibilă până la 48 de ore înainte de sosire cu rambursare completă" }, "percentage": 12, "active": false, "checkable": true, "cancellation": true }, { "name": { "de": "Frühbucher-Rabatt", "en": "Early bird discount", "ro": "Reducere early bird" }, "description": { "de": "Wenn Sie mehr als 150 Tage im Voraus buchen", "en": "If you book more than 150 days in advance", "ro": "Dacă rezervați cu mai mult de 150 de zile în avans" }, "percentage": -10, "days_ahead": 150, "active": false, "checkable": false }, { "name": { "de": "Langzeitbucher-Rabatt", "en": "Long stay discount", "ro": "Reducere pentru ședere lungă" }, "description": { "de": "Wenn Sie mehr als 20 Tage Aufenthalt buchen", "en": "If you book more than 20 consecutive nights", "ro": "Dacă rezervați mai mult de 20 de nopți consecutive" }, "percentage": -10, "min_days": 21, "active": false, "checkable": false }, { "name": { "de": "Sofortzahler-Rabatt", "en": "Prepayment discount", "ro": "Reducere pentru plată anticipată" }, "description": { "de": "Wenn Sie den Gesamtpreis sofort überweisen
(sonst 30% Anzahlung, Rest 90 Tage vor Anreisetag)
(gilt nicht für kurzfristige Buchungen)", "en": "If you transfer the complete price on booking
(otherwise 30% prepayment, rest due 90 days before start of vacation)
(not applicable for short-term bookings)", "ro": "Dacă transferați prețul complet la rezervare
(în caz contrar, 30% plată în avans, restul datorat cu 90 de zile înainte de începutul vacanței)
(nu se aplică pentru rezervările pe termen scurt)" }, "percentage": -8, "active": false, "checkable": true, "single_payment": true } ] const floorplan_legend = [ { "level": [ 0, 1, 2, 3 ], "name": { "en": "Large Pool", "de": "Großer Pool", "ro": "Piscină mare" }, "video": "room_pool.mp4", "position": [ [ -0.3207210984173567, 0.032700974740593226 ], [ -0.23058379624777278, 0.25280368934074 ], [ -0.055549732732417985, 0.3068860706424903 ], [ 0.16140865737344093, 0.2289068231841526 ] ], "div": {}, "legend": {}, "className": "fll" }, { "level": [ 3 ], "name": { "en": "Jacuzzi", "de": "Whirlpool", "ro": "Jacuzzi" }, "video" : "room_whirlpool.mp4", "position": [ [ -0.09432973482863431, -0.2188449848024316 ], [ -0.2064773084582329, -0.08552562624462845 ], [ -0.22324703909443455, 0.03773189393145372 ], [ -0.12158054711246201, 0.1094224924012158 ] ], "div": {}, "legend": {}, "className": "fll" }, { "level": [ 0, 1, 2, 3 ], "name": { "en": "Sun Terrace", "de": "Sonnenterasse", "ro": "Terasa de soare" }, "img":"terrace.jpg", "position": [ [ -0.22848757991824756, 0.20626768682528035 ], [ -0.06603081438004402, 0.2993396918561995 ], [ 0.14359081857247669, 0.23771093176815847 ], [ 0.2599308248611257, 0.10061838381720993 ] ], "div": {}, "legend": {}, "className": "fll" }, { "level": [ 0, 1, 2, 3 ], "name": { "en": "Summer kitchen", "de": "Grillbereich", "ro": "Bucătărie de vară" }, "img" : "bbq.jpg", "position": [ [ -0.19494811864584424, 0.334556126192223 ], [ 0.04611675924955455, 0.36725710093281627 ], [ 0.2767005554973273, 0.1987213080389896 ], [ 0.35111623519547214, 0.03898962372916885 ] ], "div": {}, "legend": {}, "className": "fll" }, { "level": [ 0, 1, 2 ], "name": { "en": "Playground", "de": "Schaukel und Rutsche", "ro": "Loc de joacă" }, "img" : "swingset.jpg", "position": [ [ 0.1562651636019208, -0.33881552131735554 ], [ -0.06084364943499207, -0.34730228604036384 ], [ -0.2708728800071427, -0.21028252337863493 ], [ -0.37924774947885737, -0.043385855198034215 ] ], "div": {}, "legend": {}, "className": "fll" }, { "level": [ 0, 1, 2 ], "name": { "en": "Garage", "de": "Garage", "ro": "Garaj" }, "position": [ [ 0.26482199629668446, -0.24494578951658924 ], [ 0.07006311940281126, -0.37029079178749025 ], [ -0.1583249872868362, -0.3118150904284434 ], [ -0.31139972904463004, -0.1516234030907545 ] ], "div": {}, "legend": {}, "className": "fll" }, { "level": [ 1, 2 ], "name": { "en": "Living Room ❄", "de": "Wohnzimmer ❄", "ro": "Living ❄" }, "video": "room_main.mp4", "position": [ [ -0.0901373021695839, -0.05282465150403522 ], [ -0.08175243685148308, -0.00880410858400587 ], [ -0.04821297557907976, 0 ], [ -0.03878000209621633, -0.023413571836169045 ] ], "div": {}, "legend": {}, "className": "fll" }, { "level": [ 2 ], "name": { "en": "Room Verdi ❄", "de": "Zimmer Verdi ❄", "ro": "Camera Verdi ❄" }, "video": "room_verdi.mp4", "position": [ [ 0.1943512792742433, -0.05545656756221687 ], [ 0.1278691961010376, -0.17356671208468713 ], [ 0.02410648778953988, -0.2238759039932921 ], [ -0.10271460014673514, -0.17482444188240226 ] ], "div": {}, "legend": {}, "className": "fll" }, { "level": [ 2 ], "name": { "en": "Kitchen", "de": "Küche", "ro": "Bucătărie" }, "img" : "kitchen11.jpg", "position": [ [ 0.0035786100532982207, 0.0633173787979364 ], [ 0.04565335957485626, 0.009383479486194106 ], [ 0.11510265637191536, -0.04571498445306221 ], [ 0.08167237303334149, -0.12022674073297697 ] ], "div": {}, "legend": {}, "className": "fll" }, { "level": [ 2 ], "name": { "en": "Bathroom", "de": "Badezimmer", "ro": "Baie" }, "img" : "main_bathroom.jpg", "position": [ [ 0.08260159855904535, 0.04607599948759156 ], [ 0.1023264119375638, -0.06053989216131549 ], [ 0.0735956321062704, -0.12904831778639556 ], [ 0.0074386565582457015, -0.1403416832617126 ] ], "div": {}, "legend": {}, "className": "fll" }, { "level": [ 1 ], "name": { "en": "Room Beethoven ❄", "de": "Zimmer Beethoven ❄", "ro": "Camera Beethoven ❄" }, "video": "room_beethoven.mp4", "position": [ [ 0.18477273521294063, -0.1924297476388452 ], [ 0.06640687170767873, -0.29234065844484036 ], [ -0.08684498092054951, -0.273684333112066 ], [ -0.19770182875465342, -0.19877080203565897 ] ], "div": {}, "legend": {}, "className": "fll" }, { "level": [ 1 ], "name": { "en": "Room Bach ❄", "de": "Zimmer Bach ❄", "ro": "Camera Bach ❄" }, "video": "room_bach.mp4", "position": [ [ 0.0035786100532982368, 0.0748116316714996 ], [ 0.09514250389158678, -0.011689317448671799 ], [ 0.12148835241278383, -0.112764792882181 ], [ 0.09524197712018695, -0.17578229628853254 ] ], "div": {}, "legend": {}, "className": "fll" }, { "level": [ 1 ], "name": { "en": "Room Mozart ❄", "de": "Zimmer Mozart ❄", "ro": "Camera Mozart ❄" }, "video": "room_mozart.mp4", "position": [ [ 0.20153518732022033, -0.06311940281125901 ], [ 0.15820125229516277, -0.2166701603605492 ], [ 0.03448324385595112, -0.28326287717336873 ], [ -0.1091002961876036, -0.2284642886256973 ] ], "div": {}, "legend": {}, "className": "fll" }, { "level": [ 3 ], "name": { "en": "Room Wagner ❄", "de": "Zimmer Wagner ❄", "ro": "Camera Wagner ❄" }, "video": "room_wagner.mp4", "position": [ [ -0.1017853746210313, -0.03438377062735097 ], [ -0.09243731730892407, 0.025667004390408643 ], [ -0.061302196757075704, 0.06731183547030944 ], [ -0.004534523518382641, 0.06368130524403451 ] ], "div": {}, "legend": {}, "className": "fll" }, { "level": [ 3 ], "name": { "en": "Room Haydn ❄", "de": "Zimmer Haydn ❄", "ro": "Camera Haydn ❄" }, "video": "room_haydn.mp4", "position": [ [ -0.09380325456994573, 0.09109515657571415 ], [ -0.011019692787851282, 0.11953673619117491 ], [ 0.054438543983665044, 0.07305896190709105 ], [ 0.11040800521724953, 0.016746439343651387 ] ], "div": {}, "legend": {}, "className": "fll" }, { "level": [ 3 ], "name": { "en": "TV Lounge ❄", "de": "TV-Lounge ❄", "ro": "Salon TV ❄" }, "video": "room_tvlounge.mp4", "position": [ [ 0.1847727352129406, -0.008521701661833733 ], [ 0.1502191322440772, -0.1352525358394764 ], [ 0.023308275784431325, -0.15969965878256412 ], [ -0.11947705225401484, -0.10873248785941375 ] ], "div": {}, "legend": {}, "className": "fll" }, { "level": [ 3 ], "name": { "en": "Jazz Club ❄", "de": "Jazz-Club ❄", "ro": "Club de jazz ❄" }, "video": "room_jazzclub.mp4", "position": [ [ 0.019542850155469346, 0.12174649757188273 ], [ 0.08636217183539266, 0.06398118063561936 ], [ 0.11350623236169825, 0.00026202704119066 ], [ 0.060120648895410446, -0.050303369085467384 ] ], "div": {}, "legend": {}, "className": "fll" }, { "level": [ 3 ], "name": { "en": "Bathroom", "de": "Badezimmer", "ro": "Baie" }, "position": [ [ 0.19355306726913477, -0.1368741920832897 ], [ 0.07039793173322152, -0.22816441323411243 ], [ -0.09881816099717788, -0.18843529096647216 ], [ -0.20967500883128176, -0.09053325414293865 ] ], "div": {}, "legend": {}, "className": "fll" }, { "level": [ 3 ], "name": { "en": "Kitchen", "de": "Küche", "ro": "Bucătărie" }, "img": "kitchen.jpg", "position": [ [ 0.1352835908962101, -0.09760216143194869 ], [ 0.04804799559018193, -0.15440962396208177 ], [ -0.06449504477750992, -0.13479544422317713 ], [ -0.1482126844379229, -0.07041831161420302 ] ], "div": {}, "legend": {}, "className": "fll" } ]; vl = { genders: { "de": ["", "Herr", "Frau", "Andere"], "en": ["", "Male", "Female", "Other"], "ro": ["", "Domn", "Doamnă", "Altul"] }, countries: { "de": [ "Albanien", "Andorra", "Armenien", "Aserbaidschan", "Belarus", "Belgien", "Bosnien und Herzegowina", "Bulgarien", "Dänemark", "Deutschland", "Estland", "Finnland", "Frankreich", "Georgien", "Griechenland", "Irland", "Island", "Italien", "Kasachstan", "Kosovo", "Kroatien", "Lettland", "Liechtenstein", "Litauen", "Luxemburg", "Malta", "Moldawien", "Monaco", "Montenegro", "Niederlande", "Nordmazedonien", "Norwegen", "Österreich", "Polen", "Portugal", "Rumänien", "Russland", "San Marino", "Schweden", "Schweiz", "Serbien", "Slowakei", "Slowenien", "Spanien", "Tschechien", "Türkei", "Ukraine", "Ungarn", "Vatikanstadt", "Vereinigtes Königreich", "Weißrussland", "Andere / Nicht-EU" ], "en": [ "Albania", "Andorra", "Armenia", "Austria", "Azerbaijan", "Belarus", "Belgium", "Bosnia and Herzegovina", "Bulgaria", "Croatia", "Cyprus", "Czechia", "Denmark", "Estonia", "Finland", "France", "Georgia", "Germany", "Greece", "Hungary", "Iceland", "Ireland", "Italy", "Kazakhstan", "Kosovo", "Latvia", "Liechtenstein", "Lithuania", "Luxembourg", "Malta", "Moldova", "Monaco", "Montenegro", "Netherlands", "North Macedonia", "Norway", "Poland", "Portugal", "Romania", "Russia", "San Marino", "Serbia", "Slovakia", "Slovenia", "Spain", "Sweden", "Switzerland", "Turkey", "Ukraine", "United Kingdom", "Other / Outside EU" ], "ro": [ "Albania", "Andorra", "Armenia", "Austria", "Azerbaidjan", "Belarus", "Belgia", "Bosnia și Herțegovina", "Bulgaria", "Cehia", "Cipru", "Croația", "Danemarca", "Estonia", "Finlanda", "Franța", "Germania", "Georgia", "Grecia", "Irlanda", "Islanda", "Italia", "Kazahstan", "Kosovo", "Letonia", "Liechtenstein", "Lituania", "Luxemburg", "Malta", "Moldova", "Monaco", "Muntenegru", "Norvegia", "Olanda", "Polonia", "Portugalia", "Regatul Unit", "România", "Rusia", "San Marino", "Serbia", "Slovacia", "Slovenia", "Spania", "Suedia", "Elveția", "Turcia", "Ucraina", "Ungaria", "Vatican", "Altele / În afara UE" ] }, "languages": { "de": ["", "Deutsch", "Englisch", "Bulgarisch", "Rumänisch"], "en": ["", "German", "English", "Bulgarian", "Romanian"], "ro": ["", "Germană", "Engleză", "Bulgară", "Română"] }, academy_prices: { "de":["", "Unklar / Ich habe eine Frage", "Einzelzimmer: 850€ p.P.", "Einzelzimmer (Stammgäste): 750€ p.P.", "Academy for two: 1200€ (600€ p.P.)", "Externe Teilnehmer: 350€ p.P.", ], "en":["", "Don't know / I have a question", "Single room: 850€ p.p.", "Single room (returning visitors): 750€ p.P.", "Academy for two: 1200€ (600€ p.p.)", "External participants: €350 p.p.", ], } , academy_prices_explanation: { "de":[ "hidden", "hidden", "", "", "Zwei Personen im Doppelzimmer", "Nur Unterricht, keine Übernachtung - wenn Sie bereits eine andere Unterkunft in der Umgebung gefunden haben.", ], "en":[ "hidden", "hidden", "", "", "Two people in a double room", "Lessons only, no accommodation - if you have already found other accommodation in the area.", ] }, writing_prices: { "de":["", "Einzelzimmer: 850€ p.P.", "Einzelzimmer (Studentenrabatt): 750€ p.P.", "Zwei Teilnehmer im Doppelzimmer: 1200€ (600€ p.P.)", ], "en":["", "Single room: 850€ p.p.", "Single room (discounted): 750€ p.P.", "Two participants sharing a double room: 1200€ (600€ p.p.)", ], } , writing_prices_explanation: { "de":[ "", "", "", "Zwei Personen im Doppelzimmer", ], "en":[ "", "", "", "Two people in a double room", ] } }; global_booking_nav = [ { "description": { "de": "Termin auswählen", "en": "Pick Dates", "ro": "Alegeți datele" }, "date_selected": { "de": "Zeitraum: ", "en": "Interval: ", "ro": "Interval: " }, "onclick": "booking_reset();" }, { "description": { "de": "Preise und Extras", "en": "Prices and Extras", "ro": "Prețuri și extraopțiuni" }, "onclick": "booking_show_prices();" }, { "description": { "de": "Buchung abschließen", "en": "Confirm Booking", "ro": "Confirmă rezervarea" }, "onclick": "booking_show_form();" } ]; global_forms = { "subscribe": { "title": { "de": "Newsletter abonnieren", "en": "Subscribe to Our Newsletter", "ro": "Abonați-vă la newsletter" }, "description": { "de": "Subscribe to our newsletter for updates about our Villa and the Villa Musica Summer Academy. If you want more day-to-day updates you can also follow us on Facebook.", "en": "Subscribe to our newsletter for updates about our Villa and the Villa Musica Summer Academy. If you want more day-to-day updates you can also follow us on Facebook.", "ro": "Abonați-vă la newsletter-ul nostru pentru actualizări despre Vila noastră și Academia de vară Villa Musica. Dacă doriți mai multe actualizări zilnice, ne puteți urmări și pe Facebook." }, "fields": [ { "field": "sex", "type": "radio", "label": { "de": "Anrede", "en": "Gender", "ro": "Gen" }, "vl": "genders" }, { "field": "firstname", "required": true, "label": { "de": "Vorname", "en": "First Name", "ro": "Prenume" }, "autocomplete": "given-name" }, { "field": "lastname", "required": true, "label": { "de": "Nachname", "en": "Last Name", "ro": "Nume" }, "autocomplete": "family-name" }, { "field": "language", "required": true, "type": "pulldown", "label": { "de": "Sprache", "en": "Language", "ro": "Limbă" }, "vl": "languages" }, { "field": "email", "type": "email", "required": true, "label": { "de": "Email", "en": "Email", "ro": "Email" }, "autocomplete": "email" } ], "send_button": { "de": "Abonnieren", "en": "Subscribe", "ro": "Abonează-te" }, "email_subject": "Villa Musica Form Submission - Subscribe Newsletter", "success": { "de": "Abonnement erfolgreich! Sie bekommen jetzt unseren Newsletter.", "en": "You have been successfully subscribed.", "ro": "V-ați abonat cu succes." } }, "contact": { "title": { "de": "Kontakt", "en": "Contact", "ro": "Contact" }, "description": { "de": "Schreiben Sie uns gerne, wenn Sie Fragen oder Anregungen haben.", "en": "If you have any questions or suggestions, drop us a line!", "ro": "Dacă aveți întrebări sau sugestii, scrieți-ne!" }, "fields": [ { "field": "sex", "type": "radio", "label": { "de": "Anrede", "en": "Gender", "ro": "Gen" }, "vl": "genders" }, { "field": "firstname", "required": true, "label": { "de": "Vorname", "en": "First Name", "ro": "Prenume" }, "autocomplete": "given-name" }, { "field": "lastname", "required": true, "label": { "de": "Nachname", "en": "Last Name", "ro": "Nume" }, "autocomplete": "family-name" }, { "field": "language_id", "required": true, "type": "pulldown", "label": { "de": "Sprache", "en": "Language", "ro": "Limbă" }, "vl": "languages" }, { "field": "email", "type": "email", "required": true, "label": { "de": "Email", "en": "Email", "ro": "Email" }, "autocomplete": "email" }, { "field": "phone", "label": { "de": "Telefon", "en": "Phone", "ro": "Telefon" }, "autocomplete": "tel" }, { "field": "comment", "type": "bigtext", "required": true, "label": { "de": "Kommentar/Anfrage", "en": "Your Comment or Question", "ro": "Comentariul sau întrebarea dvs." }, "autocomplete": "comment" }, { "field": "subscribe", "type": "checkbox", "label": { "de": "Newsletter abonnieren", "en": "Subscribe to our Newsletter", "ro": "Abonați-vă la newsletter" } } ], "send_button": { "de": "Nachricht versenden", "en": "Send Message", "ro": "Trimite mesajul" }, "email_subject": "VM - Contact Form", "success": { "de": "Danke für Ihre Nachricht, wir werden uns schnell wie möglich bei Ihnen melden.", "en": "Thank you for contacting us, we will get back to you as soon as possible.", "ro": "Mulțumim pentru mesaj, vă vom răspunde cât mai curând posibil." } }, "booking": { "title": { "de": "Buchung abschließen", "en": "Booking", "ro": "Finalizați rezervarea" }, "description": { "de": "Geben Sie für die Buchung noch Ihre Kontaktdaten an.", "en": "Please supply the personal data required to complete the booking process.", "ro": "Vă rugăm să furnizați datele personale necesare pentru a finaliza procesul de rezervare." }, "fields": [ { "field": "sex", "type": "radio", "label": { "de": "Anrede", "en": "Gender", "ro": "Gen" }, "vl": "genders" }, { "field": "firstname", "required": true, "label": { "de": "Vorname", "en": "First Name", "ro": "Prenume" }, "autocomplete": "given-name" }, { "field": "lastname", "required": true, "label": { "de": "Nachname", "en": "Last Name", "ro": "Nume" }, "autocomplete": "family-name" }, /* { "field": "address", "type": "mediumtext", "required": true, "label": { "de": "Postanschrift (Land, PLZ/Ort, Straße/Hausnr.)", "en": "Address (Country, ZIP/City, Street/Number)", "ro": "Adresa (Țară, Cod poștal/Localitate, Stradă/Număr)" }, "autocomplete": "street-address" }, */ { "field": "country_id", "required": true, "type": "pulldown", "label": { "de": "Land", "en": "Country", "ro": "Țară" }, "vl": "countries" }, { "field": "language_id", "required": true, "type": "pulldown", "label": { "de": "Bevorzugte Sprache", "en": "Preferred language", "ro": "Limba preferată" }, "vl": "languages" }, { "field": "email", "type": "email", "required": true, "label": { "de": "Email", "en": "Email", "ro": "Email" }, "autocomplete": "email" }, /* { "field": "phone", "label": { "de": "Telefon", "en": "Phone", "ro": "Telefon" }, "autocomplete": "tel" }, */ { "field": "termsandconditions", "type": "checkbox", "required": true, "label": { "de": "Ich stimme den Nutzungsbedingungen zu", "en": "I agree to the Terms and Coditions", "ro": "Sunt de acord cu Termenii și condițiile" } }, { "field": "comment", "type": "mediumtext", "label": { "de": "Kommentare, Wünsche, Fragen", "en": "Comments, Questions and Requests", "ro": "Comentarii, întrebări și cereri" }, "autocomplete": "comment" }, /* { "field": "subscribe", "type": "checkbox", "label": { "de": "Newsletter abonnieren", "en": "Subscribe to our Newsletter", "ro": "Abonați-vă la newsletter" } }, */ { "field": "booking_price_categories", "type": "div" }, { "field": "booking_pricelist", "type": "div" }, { "field": "selected_first_day", "type": "var" }, { "field": "selected_last_day", "type": "var" }, { "field": "price_category", "type": "var" }, { "field": "user_timezone", "type": "var" }, { "field": "collateral", "type": "var" } ], "send_button": { "de": "Verbindlich buchen", "en": "Confirm Booking", "ro": "Confirmă rezervarea" }, "email_subject": "VM - Booking Completed", "success": { "de": "Vielen Dank für Ihre Buchung! Wir lassen Ihnen schnellstmöglich eine Bestätigungsmail mit den entsprechenden Zahlungsdetails zukommen.

Wir freund uns darauf, Sie bald in unserer Villa Musica begrüßen zu dürfen!", "en": "Thank you! We will send you a confirmation email as soon as possible.", "ro": "Mulțumim pentru rezervare! Vă vom trimite un email de confirmare cât mai curând posibil." } }, "academy_booking":{ title:{ "de":"Buchung abschließen", "en":"Booking" }, description:{ "de":"Geben Sie für die Buchung noch Ihre Kontaktdaten an.", "en":"Please supply the personal data required to complete the booking process."}, fields:[ { field:"academy_price", required:true, type:"pulldown", label:{"de":"Preiskategorie", "en":"Price Category"}, vl:"academy_prices"}, { condition:{field:"academy_price", value:5}, field:"has_accomodation", type:"checkbox", required:true, label:{"de":"Die gewählte Preiskategorie beinhaltet keine Übernachtung. Ich bestätige, dass ich mich selbst um meine Unterkunft kümmern werde.", "en":"The selected a price category doesn't include accomodation. I confirm that I will arrange my own accomodation."} }, { field:"sex", type:"radio", label:{"de":"Anrede", "en":"Gender"}, vl:"genders"}, { field:"firstname", required:true, label:{"de":"Vorname", "en":"First Name"}, autocomplete:"given-name" }, { field:"lastname", required:true, label:{"de":"Nachname", "en":"Last Name"}, autocomplete:"family-name" }, { field:"address", type:"mediumtext", required:true, label:{"de":"Postanschrift", "en":"Address"}, autocomplete:"street-address" }, { field:"country_id", required:true, type:"pulldown", label:{"de":"Land", "en":"Country"}, vl:"countries"}, { type:"error", condition:{ field:"country_id", "value":51}, label:{"de":"Leider ist dieses Angebot nur für EU-Bürger verfügbar.", "en":"We are sorry, but this offer is only available for EU citizens."} }, { field:"email", type:"email", required:true, label:{"de":"Email", "en":"Email"}, autocomplete:"email" }, { field:"phone", required:true, label:{"de":"Telefon", "en":"Phone"}, autocomplete:"tel" }, { field:"termsandconditions", type:"checkbox", required:true, label:{"de":"Ich stimme den Nutzungsbedingungen zu", "en":"I agree to the Terms and Coditions"} }, { field:"comment", type:"mediumtext", label:{"de":"Kommentare, Wünsche, Fragen", "en":"Comments, Questions and Requests"}, autocomplete:"comment" }, /* { field:"subscribe", type:"checkbox", label:{"de":"Newsletter abonnieren", "en":"Subscribe to our Newsletter"} },*/ ], send_button:{ "de":"Abschicken", "en":"Send" }, email_subject:"VM Academy - Booking Form Sent", success:{ "de":`Vielen Dank für Ihre Anfrage! Wir lassen Ihnen schnellstmöglich eine Bestätigungsmail mit den entsprechenden Zahlungsdetails zukommen.

Wir freund uns darauf, Sie bald in unserer Villa Musica begrüßen zu dürfen!`, "en":"Thank you! We will send you a confirmation email as soon as possible."}, }, "writing_booking":{ title:{ "de":"Buchung abschließen", "en":"Booking" }, description:{ "de":"Geben Sie für die Buchung noch Ihre Kontaktdaten an.", "en":"Please supply the personal data required to complete the booking process."}, fields:[ { field:"writing_price", required:true, type:"pulldown", label:{"de":"Preiskategorie", "en":"Price Category"}, vl:"writing_prices"}, { field:"sex", type:"radio", label:{"de":"Anrede", "en":"Gender"}, vl:"genders"}, { field:"firstname", required:true, label:{"de":"Vorname", "en":"First Name"}, autocomplete:"given-name" }, { field:"lastname", required:true, label:{"de":"Nachname", "en":"Last Name"}, autocomplete:"family-name" }, { field:"address", type:"mediumtext", required:true, label:{"de":"Postanschrift", "en":"Address"}, autocomplete:"street-address" }, { field:"country_id", required:true, type:"pulldown", label:{"de":"Land", "en":"Country"}, vl:"countries"}, { field:"email", type:"email", required:true, label:{"de":"Email", "en":"Email"}, autocomplete:"email" }, { field:"phone", required:true, label:{"de":"Telefon", "en":"Phone"}, autocomplete:"tel" }, { field:"termsandconditions", type:"checkbox", required:true, label:{"de":"Ich stimme den Nutzungsbedingungen zu", "en":"I agree to the Terms and Coditions"} }, { field:"comment", type:"mediumtext", label:{"de":"Kommentare, Wünsche, Fragen", "en":"Comments, Questions and Requests"}, autocomplete:"comment" }, { field:"subscribe", type:"checkbox", label:{"de":"Newsletter abonnieren", "en":"Subscribe to our Newsletter"} } ], send_button:{ "de":"Verbindlich buchen", "en":"Confirm booking" }, email_subject:"VM Writing Retreat - Booking Completed", success:{ "de":`Vielen Dank für Ihre Buchung! Wir lassen Ihnen schnellstmöglich eine Bestätigungsmail mit den entsprechenden Zahlungsdetails zukommen.

Wir freund uns darauf, Sie bald in unserer Villa Musica begrüßen zu dürfen!`, "en":"Thank you! We will send you a confirmation email as soon as possible."}, }, } const floorplan_levels = [ { "de": "Die Villa", "en": "The Villa", "ro": "Vila"}, { "de": "Obergeschoss", "en": "Upper Level", "ro": "Etajul Superior"}, { "de": "Hauptgeschoss", "en": "Main Level", "ro": "Etajul Principal"}, { "de": "Poolbereich", "en": "Pool Level", "ro": "Nivelul Piscinei"}, ]; const loc = { "day" : { "de": "Tag", "en": "Day", "ro": "Zi"}, "days" : { "de": "Tage", "en": "Days", "ro": "Zile"}, "due_date": { "de": "Zahlungsziel", "en": "Due Date", "ro": "Data scadentă"}, "payment_plan" : { "de": "Zahlungsplan", "en": "Payment Plan", "ro": "Plan de plată"}, "amount": { "de": "Betrag", "en":"Amount", "ro": "Sumă"}, "week" : { "de": "Woche", "en": "Week", "ro": "Săptămână"}, "months" : { "de": "Monate", "en": "Months", "ro": "Luni"}, "price" : { "de": "Preis", "en": "Price", "ro": "Preț"}, "total" : { "de": "Summe", "en": "Total", "ro": "Total"}, "selection" : { "de": "Ihre Auswahl", "en": "Your selection", "ro": "Selecția dvs."}, "select_first" : { "de": "Bitte wählen Sie den Tag Ihrer Ankunft aus.", "en": "Please select the day of your arrival.", "ro": "Vă rugăm să selectați ziua sosirii dvs."}, "select_next1" : { "de": "Ankunft am", "en": "Arrival on", "ro": "Sosire pe"}, "select_next2" : { "de": "Bitte wählen Sie den Tag Ihrer Abreise aus.", "en": "Please select the day of your departure.", "ro": "Vă rugăm să selectați ziua plecării dvs."}, "select_done1" : { "de": "Übernachtungen geplant", "en": "nights scheduled", "ro": "nopți programate"}, "select_done2" : { "de": "vom", "en": "from", "ro": "de la"}, "select_done3" : { "de": "bis zum", "en": "to", "ro": "până la"}, "select_reset" : { "de": "Zurücksetzen", "en": "Reset", "ro": "Resetați"}, "min_stay_warning" : { "de": "Mindestanzahl Übernachtungen: ", "en": "Minimum nights: ", "ro": "Număr minim de nopți: "}, "book_now" : { "de": "Jetzt buchen", "en": "Book Now", "ro": "Rezervați acum"}, "our_prices" : { "de": "Unsere Preise", "en": "Our Prices", "ro": "Prețurile noastre"}, "our_price_categories" : { "de": "Preiskategorien", "en": "Our Price Categories", "ro": "Categoriile noastre de preț"}, "your_planned_stay" : { "de": "Ihr geplanter Aufenthalt", "en": "Your Planned Stay", "ro": "Sejurul dvs. planificat"}, "your_price_category" : { "de": "Ihre gewählte Preiskategorie", "en": "Your Price Category", "ro": "Categoria dvs. de preț aleasă"}, "unavailable" : { "de":"Leider bereits ausgebucht", "en":"Unavailable", "ro":"Din păcate, deja rezervat"}, "price_display" : [ {"en":"Price per day", "de":"Preis pro Übernachtung", "ro":"Preț pe zi"}, {"en":"Price per week", "de":"Preis pro Woche", "ro":"Preț pe săptămână"} ], "please_choose" : {"en":"Please Choose", "de":"Bitte auswählen", "ro":"Vă rugăm să alegeți"}, "total_collateral" : { "de":"Gesamtbetrag inkl. Kaution", "en":"Total payment including collateral", "ro":"Plata totală inclusiv garanția"}, "prepayment" : { "de":"Anzahlung", "en":"Prepayment", "ro":"Avans"}, "remainder_collateral" : { "de":"Restzahlung inkl. Kaution", "en":"Remainder including collateral", "ro":"Diferența inclusiv garanția"}, "refund_collateral" : { "de":"Rückerstattung Kaution", "en":"Refund collateral", "ro":"Rambursarea garanției"}, "included_in_price" : { "de": "Inklusivleistungen", "en": "Included in the price", "ro": "Inclus în preț"}, "discounts_and_extra_features" : { "de": "Sonderleistungen und Rabatte", "en": "Discounts and Extra Features", "ro": "Reduceri și facilități suplimentare"}, "amenities": { "de": "Ausstattung (im Preis inbegriffen)", "en": "Amenities (included)", "ro": "Facilități (incluse)"}, "cancellation_information" : { "de":"Stornobedingungen" , "en":"Cancellation policy", "ro":"Politica de anulare" }, "flex_ad": { "de":"Nutzen Sie den Villa FLEX-Tarif, wenn Sie flexibler sein wollen." , "en":"If you want to be more flexible, make use of our Villa FLEX option." , "ro":"Dacă doriți să fiți mai flexibil, utilizați opțiunea noastră Villa FLEX."}, "no_cancel" : { "de":"Augrund des kurzfristigen Reiseantritts ist eine Stornierung nicht möglich (100% Stornogebühr)" , "en":"Cancellation is not possible (100% cancellation fee)" , "ro":"Anularea nu este posibilă (taxă de anulare de 100%)"}, "cancel_until" : { "de":"Stornierung bis einschliesslich DATE ist kostenlos möglich", "en":"Cancellation up to and including DATE is possible (no cancellation fee)" , "ro":"Anularea până la și inclusiv DATE este posibilă (fără taxă de anulare)" }, "no_cancel_after" : { "de":"Stornierung nach dem DATE ist nicht möglich (100% Stornogebühr)", "en":"Cancellation past DATE ist not possible (100% cancellation fee)", "ro":"Anularea după DATE nu este posibilă (taxă de anulare de 100%)" } }