// ! *** VARIABLES Logged in users starts ***
// ! *** VARIABLES Not logged in users starts ***
var favStablesJSON = [];
var isStablePersonnel = 0;
// ! *** VARIABLES Not logged in users ends ***
var hopotiRewardsData = [];
var hopotiAdsData = [];
// ! *** FUNCTIONS Everyone starts ***
/* !Skill selection starts */
/* usage: loadSkills(3,8); */
var buttonsSelected = 0;
var firstPosition;
var secondPosition;
var newPosition;
var distanceFirst;
var distanceSecond;
var minSkill;
var maxSkill;
var userLevel; // user set skill from settings
var userConfirmed;
var userConfirmedPerson;
var userConfirmedDate;
var userConfirmedStable;
var $window = $(window);
var windowsize;
var oldwindowsize;
var totalUserWalletCredits;
var currentStableLink; // currently selected stable
var selectedHorseId;
var combousercalendarevents = true; // if user calendar events are combined
var eventSummaryAlmostFull = 75; // percentage setting for almost full color display on summary
// Init default ID values for card types
var idStablecards = 1;
var idMemberships = 4;
var idGiftcards = 3;
var userStableCardsArray = [];
// Allowed file upload types
var fileUploadTypes = ".jpeg,.jpg,.png,.gif,.bmp,.pdf,.doc,.docx,.odt,.txt,.rtf,.xls,.xlsx,.ppt,.zip,.avi,.mov,.mpg,.mpeg,.mp4,.wmv,.flv,.f4v,.mp3,.mp4,.wma,.wav,.acc,.m4a,.flac";
var carbonOffsetInfo = [
{
date: "2022-01-01",
g: 2600
}
];
function cancellationPolicyModalAdmin(policy){
policyFlexible = '';
policyStandard = '';
policyStrict = '';
policyNoreturn = '';
policyFull = '';
switch(policy) {
case 'flexible':
policyFlexible = 'active';
break;
case 'strict':
policyStrict = 'active';
break;
case 'noreturn':
policyNoreturn = 'active';
break;
case 'full':
policyFull = 'active';
break;
default:
policyStandard = 'active';
}
BootstrapDialog.show({
type: BootstrapDialog.TYPE_INFO,
title: 'Cancellation policies',
message: '
For every lesson, course and event, the business can choose from a variety of cancellation policies. Paid lessons are not refunded in cash as such as the purchase is for a leisure event with a specified date and time. Cancelled events are instead usually refunded with new credits added to the Stablecard. Refunded credits can be used to book an alternative event before the end of the validity period. The "No return" category is an exception, which is meant to be used with seasons and camps as they can’t be returned. Instead, lessons within seasons can be cancelled and refunded in line with the business’s selected cancellation policy.
The lesson is officially cancelled when the rider clicks the cancellation button in the rider’s calendar. Logged in users can find the calendar in Hopoti > Calendar. Riders also receive an email for every cancellation.
Lessons cancelled in line with the cancellation policy are refunded with one Stablecard credit, which is valid:
Season lesson – until the end of the season.
Lesson paid for with Stablecard – until the expiry date of original Stablecard.
Lesson not paid for with Stablecard – 1 month from the date of event.
Even if the deadline to cancel the event has passed, please cancel your events if you can’t attend, so that the stable gets the correct information.
In special cases at the discretion of the stable, it may be possible to get a refund for payments. Please ask the service provider directly.
Flexible: 12 hours before the start of the event
The lesson is officially cancelled when the rider clicks the cancellation button in the rider’s calendar. Logged in users can find the calendar in Hopoti > Calendar. Riders also receive an email for every cancellation.
Lessons cancelled in line with the cancellation policy are refunded with one Stablecard credit, which is valid:
Season lesson – until the end of the season.
Lesson paid for with Stablecard – until the expiry date of original Stablecard.
Lesson not paid for with Stablecard – 1 month from the date of event.
Even if the deadline to cancel the event has passed, please cancel your events if you can’t attend, so that the stable gets the correct information.
In special cases at the discretion of the stable, it may be possible to get a refund for payments. Please ask the service provider directly.
Standard: 24 hours before the start of the event
The lesson is officially cancelled when the rider clicks the cancellation button in the rider’s calendar. Logged in users can find the calendar in Hopoti > Calendar. Riders also receive an email for every cancellation.
Lessons cancelled in line with the cancellation policy are refunded with one Stablecard credit, which is valid:
Season lesson – until the end of the season.
Lesson paid for with Stablecard – until the expiry date of original Stablecard.
Lesson not paid for with Stablecard – 1 month from the date of event.
Even if the deadline to cancel the event has passed, please cancel your events if you can’t attend, so that the stable gets the correct information.
In special cases at the discretion of the stable, it may be possible to get a refund for payments. Please ask the service provider directly.
Strict: 48 hours before the start of the event
The lesson is officially cancelled when the rider clicks the cancellation button in the rider’s calendar. Logged in users can find the calendar in Hopoti > Calendar. Riders also receive an email for every cancellation.
Lessons cancelled in line with the cancellation policy are refunded with one Stablecard credit, which is valid:
Season lesson – until the end of the season.
Lesson paid for with Stablecard – until the expiry date of original Stablecard.
Lesson not paid for with Stablecard – 1 month from the date of event.
Even if the deadline to cancel the event has passed, please cancel your events if you can’t attend, so that the stable gets the correct information.
In special cases at the discretion of the stable, it may be possible to get a refund for payments. Please ask the service provider directly.
No return
Purchased season, camp or other events cannot be cancelled.
It is not possible to get a refund for Stablecard credits if you cancel these.
Typically, the whole season cannot be refunded or cancelled, but individual recurring lessons have their own cancellation policies.
Even though this event cannot be cancelled, please cancel your events if you cannot attend, so that the stable will get the correct information.
In special cases at the discretion of the stable, it may be possible to get a refund for payments. Please ask about this directly from the service provider.
Paid lessons are not refunded in cash as such as the purchase is for a leisure event with a specified date and time. Cancelled events are instead usually refunded with new credits added to the Stablecard. Refunded credits can be used to book an alternative event before the end of the validity period. The "No return" category is an exception, which is meant to be used with seasons and camps as they can’t be returned.
You can cancel your lesson from your calendar, which can be found after login in Hopoti > Calendar. You will also receive a confirmation email after cancelling.
Lessons cancelled with the time available for cancellation according to the policy are refunded with one Stablecard credit, which is valid:
Season lesson – until the end of the season.
Lesson paid for with Stablecard – until the expiry date of original Stablecard.
Lesson not paid for with Stablecard – 1 month from the date of event.
Even if the deadline to cancel the event has passed, please cancel your events if you can’t attend, so that the stable gets the correct information.
In special cases at the discretion of the stable, it may be possible to get a refund for payments. Please ask the service provider directly.
Flexible: 12 hours before the start of the event
You can cancel your lesson from your calendar, which can be found after login in Hopoti > Calendar. You will also receive a confirmation email after cancelling.
Lessons cancelled with the time available for cancellation according to the policy are refunded with one Stablecard credit, which is valid:
Season lesson – until the end of the season.
Lesson paid for with Stablecard – until the expiry date of original Stablecard.
Lesson not paid for with Stablecard – 1 month from the date of event.
Even if the deadline to cancel the event has passed, please cancel your events if you can’t attend, so that the stable gets the correct information.
In special cases at the discretion of the stable, it may be possible to get a refund for payments. Please ask the service provider directly.
Standard: 24 hours before the start of the event
You can cancel your lesson from your calendar, which can be found after login in Hopoti > Calendar. You will also receive a confirmation email after cancelling.
Lessons cancelled with the time available for cancellation according to the policy are refunded with one Stablecard credit, which is valid:
Season lesson – until the end of the season.
Lesson paid for with Stablecard – until the expiry date of original Stablecard.
Lesson not paid for with Stablecard – 1 month from the date of event.
Even if the deadline to cancel the event has passed, please cancel your events if you can’t attend, so that the stable gets the correct information.
In special cases at the discretion of the stable, it may be possible to get a refund for payments. Please ask the service provider directly.
Strict: 48 hours before the start of the event
You can cancel your lesson from your calendar, which can be found after login in Hopoti > Calendar. You will also receive a confirmation email after cancelling.
Lessons cancelled with the time available for cancellation according to the policy are refunded with one Stablecard credit, which is valid:
Season lesson – until the end of the season.
Lesson paid for with Stablecard – until the expiry date of original Stablecard.
Lesson not paid for with Stablecard – 1 month from the date of event.
Even if the deadline to cancel the event has passed, please cancel your events if you can’t attend, so that the stable gets the correct information.
In special cases at the discretion of the stable, it may be possible to get a refund for payments. Please ask the service provider directly.
No return
This event cannot be cancelled.
It’s not possible to get a refund of Stablecard credits if you cancel it.
Even though this event cannot be refunded with Stablecard credits, please cancel your events if you cannot attend so that the service provider gets the correct information.
In special cases and at the discretion of the service provider, it may be possible to get a refund for payments. Please ask the service provider directly.
'
});
}
//!Common help dialog error dialog [help][dialog][error]
function commonHelpDialog(title,message,type){
var dialogType = BootstrapDialog.TYPE_INFO;
if(type == "INFO"){
dialogType = BootstrapDialog.TYPE_INFO;
} else if(type == "DEFAULT"){
dialogType = BootstrapDialog.TYPE_DEFAULT;
} else if(type == "PRIMARY"){
dialogType = BootstrapDialog.TYPE_PRIMARY;
} else if(type == "SUCCESS"){
dialogType = BootstrapDialog.TYPE_SUCCESS;
} else if(type == "WARNING"){
dialogType = BootstrapDialog.TYPE_WARNING;
} else if(type == "DANGER"){
dialogType = BootstrapDialog.TYPE_DANGER;
}
BootstrapDialog.show({
type: dialogType,
title: title,
message: message
});
}
var cacheViewmode;
// !Responsive width changes
// show elements after window resize
function checkWidth() {
console.log("checkWidth");
windowsize = $window.width();
if (windowsize != oldwindowsize){
if(windowsize < 480) {
//console.log("xxs");
viewmode = 'xxs';
$('.mainimage').append($('#editimageprofile'));
//$('.mobilemenu').hide();
//$('.fullmenu').not('.loginlink').hide();
//$('header li').removeClass("mobilemenu-topmargin");
} else if(windowsize < 768) {
// MOBILE
//console.log("xs");
viewmode = 'xs';
$('.mainimage').append($('#editimageprofile'));
//$('.mobilemenu').hide();
//$('.fullmenu').not('.loginlink').hide();
} else if (windowsize < 992) {
//console.log("sm");
viewmode = 'sm';
//$('.mobilemenu').hide();
//$('.fullmenu').show();
} else if (windowsize < 1200) {
//console.log("md");
viewmode = 'md';
//$('.mobilemenu').hide();
//$('.fullmenu').show();
} else {
//console.log("lg");
viewmode = 'lg';
}
// save viewmode variable to body for later use
$('body').attr("data-viewmode",viewmode);
contentAreaSubnaviCheck();
changeFixedWidthElements();
}
var mobiledesktopChange = 0;
var calendarmodeChange = 0;
// trigger only when view mode changes between modes
if(viewmode != cacheViewmode && cacheViewmode != null){ // trigger only when viewmode changes
if(cacheViewmode == "xxs" || cacheViewmode == "xs"){ // trigger only when previous viewmode was mobile
if(viewmode != "xxs" && viewmode != "xs"){ // when changing from mobile to desktop
console.log("mobile > desktop");
mobiledesktopChange = 1;
showHideMobileMenu2022(1);
}
} else {
if(viewmode == "xxs" || viewmode == "xs"){ // when changing from desktop to mobile
console.log("desktop > mobile");
mobiledesktopChange = 1;
}
}
if(cacheViewmode == "xxs"){ // trigger only when previous viewmode was mobile
if(viewmode != "xxs"){ // when changing from mobile to desktop
console.log("cal list - cal grid");
calendarmodeChange = 1;
}
} else {
if(viewmode == "xxs"){ // when changing from desktop to mobile
console.log("cal grid - cal list");
calendarmodeChange = 1;
}
}
}
if(mobiledesktopChange){ // if change between mobile - desktop
console.log("mobile - desktop");
// refresh all horses hc cal
var hcCalPresent = $('.horsecare-calendar-allhorses').children().closest('.horsecare-calendar');
if(hcCalPresent.length){
$(hcCalPresent).fullCalendar('destroy');
$(hcCalPresent).attr('data-dateselector-added', 0);
horseCareOptionsReady = 0;
$(hcCalPresent).find('.horsecare-options-menu').remove();
horsecareCalendar();
}
}
if(calendarmodeChange){
var stableEventCalendarPresent = $('.page-booking-2019 #calendar');
if(stableEventCalendarPresent.length){
changeCalendar();
}
}
cacheViewmode = viewmode;
oldwindowsize = windowsize;
}
// !show confirmed/unconfirmed extra tags on top of skill selection widget
function initConfirmedSkill() {
// addition - confirmed user skill info
userLevel = $('.skillSelection').data("userlevel");
userConfirmed = $('.skillSelection').data("confirmed");
userConfirmedPerson = $('.skillSelection').data("confirmed-person");
userConfirmedDate = $('.skillSelection').data("confirmed-date");
userConfirmedStable = $('.skillSelection').data("confirmed-stable");
confirmedTag = '';
unconfirmedTag = '';
userlevelSkillButton = $(".skillSelection a[data-value='"+userLevel+"']");
originalContent = userlevelSkillButton.attr("data-content");
if(userLevel > 0 && userConfirmed >= userLevel){ // skill level confirmed
userlevelSkillButton.append(confirmedTag);
userlevelSkillButton.attr('data-content', originalContent + '
You have changed your skill level, but this has not yet been confirmed by your riding instructor');
}
}
}
var scaled = 0;
function scaleCalendarTimes(paddingHours,calendarselector){
console.log("scaleCalendarTimes | paddingHours: "+paddingHours+" | scaled: "+scaled);
if(viewmode == "xs" || viewmode == "xxs"){
return false;
}
if(!calendarselector){
calendarselector = $("#calendar");
} else {
calendarselector = $(calendarselector);
}
var viewStart = calendarselector.fullCalendar('getView').start;
var viewEnd = calendarselector.fullCalendar('getView').end;
var viewType = calendarselector.fullCalendar('getView').type;
if(viewType != "agendaThreeDay" && viewType != "agendaWeek" && viewType != "agendaDay"){
return false;
}
var serviceCalPadding = true;
if($("body").hasClass("pageStableServices") && servicecalMode == 1){
serviceCalPadding = false;
}
var padding = paddingHours;
var firstStart;
var firstStartEvent;
var firstEnd;
var firstEndEvent;
var lastStart;
var lastStartEvent;
var lastEnd;
var lastEndEvent;
var evts = calendarselector.fullCalendar('clientEvents');
if(scaled == 0 && evts.length){
scaled = 1;
// add extra filters here if not ok servicefilter etc
var visibleRangeEvents = $.grep(evts, function(e){ // get only events on displayed range
return !e.isException == true && e.start && e.end && e.start < e.end && e.start.isBetween(viewStart, viewEnd, undefined, '[)') || !e.isException == true && e.start && e.end && e.start < e.end && e.end.isBetween(viewStart, viewEnd, undefined, '(]');
});
// console.log("visibleRangeEvents.length: "+visibleRangeEvents.length);
// console.log(visibleRangeEvents);
if(visibleRangeEvents.length){
$(visibleRangeEvents).each(function(index, event){
if(!event.end || !event.start || event.allDay || event.started || event.rendering == "background"){
return true;
}
var currentstart = event.start;
var currentstarttime = currentstart.format('HH:mm');
var comparestart = moment("2000-01-01 "+currentstarttime);
var currentend = event.end;
var currentendtime = currentend.format('HH:mm');
var compareend = moment("2000-01-01 "+currentendtime);
if(currentendtime == "00:00"){
compareend = moment("2000-01-02"+currentendtime);
}
if(!firstStart || comparestart < moment("2000-01-01 "+firstStart)){
firstStart = currentstarttime;
firstStartEvent = event;
}
if(!firstEnd || compareend < moment("2000-01-01 "+firstEnd)){
firstEnd = currentendtime;
firstEndEvent = event;
}
if(!lastStart || comparestart > moment("2000-01-01 "+lastStart)){
lastStart = currentstarttime;
lastStartEvent = event;
}
if(!lastEnd || compareend > moment("2000-01-01 "+lastEnd)){
lastEnd = currentendtime;
lastEndEvent = event;
}
});
//
// console.log("firstStart");
// console.log(firstStart);
// console.log(firstStartEvent);
//
// console.log("firstEnd");
// console.log(firstEnd);
// console.log(firstEndEvent);
//
// console.log("lastStart");
// console.log(lastStart);
// console.log(lastStartEvent);
//
// console.log("lastEnd");
// console.log(lastEnd);
// console.log(lastEndEvent);
}
var mintime;
var minmoment;
if(firstEndEvent){
var selectedStart = firstEndEvent.start.format("HH:mm");
var firstEndEventDuration = moment.duration(firstEndEvent.end.diff(firstEndEvent.start));
if(firstEndEventDuration > 3600000*2 && serviceCalPadding && lastStartEvent.scheduleservices){ // longer than 2 hours
selectedStart = firstEndEvent.end.subtract(2, "hours").format("HH:mm");
}
if(moment("2000-01-01 "+firstEnd) < moment("2000-01-01 "+selectedStart)){ // if event over two dates
minmoment = moment("2000-01-01 "+firstEnd).subtract(firstEndEventDuration).startOf('hour');
} else {
minmoment = moment("2000-01-01 "+selectedStart).startOf('hour');
}
if(padding){
minmoment.subtract(padding, "hours");
}
}
//
// console.log("minmoment");
// console.log(minmoment.format("YYYY-MM-DD HH:mm:ss"));
if(!minmoment || minmoment > moment("2000-01-01 14:00")){
mintime = "14:00";
} else if(minmoment < moment("2000-01-01 00:00:00")){
mintime = "00:00";
} else {
mintime = minmoment.format("HH:mm");
}
var maxtime;
var maxmoment;
if(lastStartEvent){
var selectedEnd = lastStartEvent.end.format("HH:mm");
if(selectedEnd == "00:00"){
selectedEnd = "24:00";
}
var lastStartEventDuration = moment.duration(lastStartEvent.end.diff(lastStartEvent.start));
if(lastStartEventDuration > 3600000*2 && serviceCalPadding && lastStartEvent.scheduleservices){ // longer than 2 hour service event
selectedEnd = lastStartEvent.start.add(2, "hours").format("HH:mm");
}
if(moment("2000-01-01 "+lastStart) > moment("2000-01-01 "+selectedEnd)){
maxmoment = moment("2000-01-01 "+lastStart).add(lastStartEventDuration).endOf('hour').add(1, "minutes");
} else {
maxmoment = moment("2000-01-01 "+selectedEnd).endOf('hour').add(1, "minutes");
}
if(padding){
maxmoment.add(padding, "hours");
}
}
// console.log("firstEndEvent");
// console.log(firstEndEvent);
// console.log("lastStartEvent");
// console.log(lastStartEvent);
if(!maxmoment || maxmoment < moment("2000-01-01 18:00")){
maxtime = "18:00";
} else if(maxmoment >= moment("2000-01-02 00:00:00")){
maxtime = "24:00";
} else {
maxtime = maxmoment.format("HH:mm");
}
console.log('scale cal | mintime: '+mintime+" | maxtime: "+maxtime);
calendarselector.fullCalendar('option', {
minTime: mintime,
maxTime: maxtime,
});
scaled = 0;
}
}
function setSkillsForm(target) {
var skilltarget = $('.skillSelection');
if(target){
skilltarget = target.find('.skillSelection');
}
minSkill = skilltarget.find('.first').data("value");
maxSkill = skilltarget.find('.second').data("value");
skilltarget.nextAll('.minSkill').val(minSkill);
skilltarget.nextAll('.maxSkill').val(maxSkill);
if(maxSkill == null){
skilltarget.nextAll('.maxSkill').val(minSkill);
}
}
function resetSkills(target) {
var skilltarget = $('.skillSelection');
if(target){
skilltarget = target.find('.skillSelection');
}
skilltarget.find("a").removeClass("active first second");
skilltarget.nextAll('.minSkill').val();
skilltarget.nextAll('.maxSkill').val();
minSkill = null;
maxSkill = null;
buttonsSelected = 0;
}
function loadSkills(minSkillInit, maxSkillInit, target) { // target is a parent container for skill selection form elements
var skilltarget = $('.skillSelection');
if(target){
skilltarget = target.find('.skillSelection');
}
resetSkills(target);
if (minSkillInit != null) {
var first = skilltarget.find("a[data-value='"+minSkillInit+"']");
first.addClass("active first");
firstPosition = skilltarget.find(".first").index();
buttonsSelected = 1;
} else {
return false;
}
if (maxSkillInit == minSkillInit) {
} else if (maxSkillInit != null && maxSkillInit != 0) {
var second = skilltarget.find("a[data-value='"+maxSkillInit+"']");
second.addClass("active second");
skilltarget.find('a.first').nextUntil('a.second').addClass("active");
buttonsSelected = 2;
secondPosition = skilltarget.find(".second").index();
}
setSkillsForm(target);
}
/* !Skill selection ends */
/* !Server response feedback for user */
/* Usage: put after ajax call, takes server result, add logic here*/
/* You can add a div class as a second variable if you have a dedicated error div instead of displaying the feedback next to the button */
/* */
/* serverResponseFeedback(result,responseElement) */
var buttonPressed; // which ui element was pressed for form submit, use to view note next to an element
function serverResponseFeedback(result,responseElement) {
$('.alert-inline').remove();
var answer;
var message;
if(result == "ok" || result == "success!"){
answer = "positive";
message = 'Changes saved';
} else if(result == "fail" || result == "error") {
answer = "negative";
message = 'Saving failed for some reason';
} else if(result == "fail-existing-account") {
answer = "negative";
message = 'An account with entered email address already exists!';
} else if(result == "invalid-email") {
answer = "negative";
message = 'Fill a valid email address';
} else if(result == "old pwd was not correct") {
answer = "negative";
message = 'Old password was not correct, please try again';
} else {
if(typeof result === 'object'){
answer = "negative";
message = 'Saving failed for some reason';
} else {
message = result;
}
}
var successHtml = '\
\
'+ message +'\
\
';
var failHtml = '\
\
'+ message +'\
\
';
var neutralHtml = '\
\
'+ message +'\
\
';
var dedicatedResponseSection = $(responseElement);
var location = 'after';
if(dedicatedResponseSection.length != ""){
buttonPressed = dedicatedResponseSection;
location = 'append';
}
if(answer == "positive"){
buttonPressed[location](successHtml);
$('.alert-inline').hide().fadeIn(100).delay(3000).fadeOut(300);
} else if(answer == "negative") {
buttonPressed[location](failHtml);
$('.alert-inline').hide().fadeIn(100);
} else {
buttonPressed[location](neutralHtml);
$('.alert-inline').hide().fadeIn(100);
}
buttonPressed = null;
}
/* Server response feedback ends */
// second level navigation readjustment
var totalnavWidth = 0;
var tolerance = 5;
// calculate total width of visible items
function menuItemsWidth(){
totalnavWidth = 0;
$('.contentnav ul li:visible').each(function(index) {
totalnavWidth += parseInt($(this).outerWidth(), 10);
});
totalnavWidth = totalnavWidth + tolerance;
}
// build second level menu for mobiles
function buildMenu() {
console.log("buildMenu");
// not needed for .register
if($('body').hasClass('register') || $('body').hasClass('stablepage') || $('body').hasClass('pageStable')){
return false;
}
// reset menu if you scale screen bigger
if ($('#contentnav-mobile').length) {
$("#contentnav-mobile li").appendTo(".contentnav ul");
$('#contentnav-mobile').remove();
$('#contentnav-more').remove();
}
menuItemsWidth();
// max space available
var contentnavUlWidth = $(".contentnav ul").width();
// add extra menu if needed
if (totalnavWidth > contentnavUlWidth) {
if (!$('#contentnav-mobile').length) {
$(".maincontainer").prepend('
');
$(".contentnav ul").append('
');
}
}
var max = 0;
// move items one by one to extra menu until everything fits!
while(totalnavWidth > contentnavUlWidth && max < 10) {
$(".contentnav li:last").prev("li").prependTo("#contentnav-mobile");
menuItemsWidth();
max++;
}
// exception on horse pages
if($('body').hasClass('pageHorse')){
if(viewmode == "xs" || viewmode == "xxs") {
$(".contentnav").find(".right").not("#contentnav-more").prependTo("#contentnav-mobile");
}
}
if(viewmode == "xs" || viewmode == "xxs"){
$('.contentnav').hide().removeClass("invisible-xs").delay(100).fadeIn(400);
}
}
// !add spinner to selected element, hide disk image
function addSavingIndicator(selector){
var selector = $('body').find(selector);
selector.addClass("disabled");
selector.find(".glyphicon-ok").addClass("hidden");
selector.append('
');
}
// !remove spinner and present a green ok mark
function removeSavingIndicator(selector){
var selector = $('body').find(selector);
selector.find(".saving-indicator, .glyphicon-ok-sign").remove();
selector.append('');
selector.removeClass("disabled");
setTimeout(function(){
selector.find(".glyphicon-ok-sign").fadeOut(500);
selector.find(".glyphicon-ok").delay(500).hide().removeClass("hidden").fadeIn(100);
}, 500);
setTimeout(function(){
selector.removeClass("btn-success");
}, 1000);
}
// add/remove full screen spinner with optional title text - blocks all interactions and disables scroll
// usage fullscreenSpinner('open/close','Title here')
function fullscreenSpinner(option,titletext){
var spinnerTitle = "";
if(titletext){
spinnerTitle = '
';
}
BootstrapDialog.show({
title: 'Switch account',
message: helpHtml+accountList,
closable: true,
type: BootstrapDialog.TYPE_PRIMARY,
cssClass: 'dialog-change-account dialog-gray-bg '+parentMode,
onshow: function(dialog) {
dialog.getModalFooter().hide();
}
});
}
function accountListHtml(data, urltarget, mode, modedata){
var returnHtml = "";
var urlRoutingTarget = "";
if(urltarget){
urlRoutingTarget = 'data-target="'+urltarget+'"';
}
if(data && parentMode == "parent"){
$.each(data, function(index, user){
var userImageHtml = '';
if(user.UserImage){
userImageHtml = '';
}
// add extra labels for waiver sign info
var extraHelp = "";
if(mode == "sign-waiver"){
extraHelp = 'Form not submitted';
if(modedata && modedata.length){
if(modedata.includes(user.UserId)){
extraHelp = ' Form submitted';
}
}
}
returnHtml += ' '+userImageHtml+user.FirstName+' '+user.LastName+extraHelp+'';
});
} else {
returnHtml = ' Back to parent account';
}
if(returnHtml){
returnHtml = '
'+returnHtml+'
';
}
return returnHtml;
}
// return country formatted prices, if currency is defined, then returns with € etc marking, otherwise with two digits on user country format
function currencyFormat(val,currency){
var langcode = '';
if(!langcode){
langcode = '';
}
var val = Number(val);
if(currency){
val = val.toLocaleString(langcode, { style: 'currency', currency: currency });
} else {
val = val.toLocaleString(langcode, {minimumFractionDigits: 2, maximumFractionDigits: 2});
}
return val;
}
// currency with two values (30,00 - 32,00 €)
function currencyFormatRange(smallval, bigval, currency){
var langcode = '';
if(!langcode){
langcode = '';
}
var bigval = Number(bigval);
var smallval = Number(smallval);
bigval = bigval.toLocaleString(langcode, { style: 'currency', currency: currency });
smallval = smallval.toLocaleString(langcode, {minimumFractionDigits: 2, maximumFractionDigits: 2});
var finalval = smallval + ' - ' + bigval;
return finalval;
}
function vatAmountFormat(val,vat,currency){
var val = Number(val);
var vat = Number(vat);
var langcode = '';
if(!langcode){
langcode = '';
}
var finalval = (val - (val / (vat + 100)*100));
if(currency){
finalval = finalval.toLocaleString(langcode, { style: 'currency', currency: currency });
} else {
finalval = finalval.toLocaleString(langcode, {minimumFractionDigits: 2, maximumFractionDigits: 2});
}
return finalval;
}
function vatAmounts(val, vat){
var val = Number(val);
var vat = Number(vat);
var vatlessval = val / (vat + 100)*100;
var vatlessval = vatlessval.toFixed(2);
var vatamount = val - vatlessval;
vatamount = vatamount.toFixed(2);
var returnobject = {};
returnobject.vatlessamount = vatlessval;
returnobject.vatamount = vatamount;
return returnobject;
}
/* Parse parameters */
/* USE: parameters = parseParms(hash); */
/* alert(parameters['horseremoved']); */
function parseParms(str) {
var pieces = str.split("&"), data = {}, i, parts;
// process each query pair
for (i = 0; i < pieces.length; i++) {
parts = pieces[i].split("=");
if (parts.length < 2) {
parts.push("");
}
data[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]);
}
return data;
}
// New test
var getUrlParameter = function getUrlParameter(sParam) {
var sPageURL = decodeURIComponent(window.location.search.substring(1)),
sURLVariables = sPageURL.split('&'),
sParameterName,
i;
for (i = 0; i < sURLVariables.length; i++) {
sParameterName = sURLVariables[i].split('=');
if (sParameterName[0] === sParam) {
return sParameterName[1] === undefined ? true : sParameterName[1];
}
}
};
var externalLoaded = 0; // if ajax data has been loaded already (1 prevents refreshing)
// Function for handling url hash changes
function hashAction() {
console.log("hashAction");
var hash = window.location.hash.substring(1); //Puts hash in variable, and removes the # character
var multi = hash.split('-'); // split to check if we have more than meets the eye there
// all parameters in an array
parameters = parseParms(hash);
// register complete dialog
if(multi[0] == "guide") {
accountReadyDialog();
}
// edit user profile
if(hash == "intercomtest"){
addIntercomTestBanner();
} else if(hash == "settings-feed"){
userFeedSettingsDialog();
} else if(hash == "settings-language"){
changeLanguageDialog();
} else if(hash == "install-app"){
hopotiAppInstall(true);
} else if(multi[0] == "settings") {
$.get("https://hopoti.com/editprofile", function(data) {
settingsDialog("user", data);
});
}
if(hash == "reloadads"){ // force reloading ads
forceAdReload = true;
}
// edit stable settings
if(multi[0] == "stablesettings" && !settingsDialogOpen) {
$.get(currentStableLink+"/stablesettings", function(data) {
settingsDialog("stable", data);
});
}
if(multi[0] == "hopotimarketing"){
hopotiBusinessMarketing();
}
if(multi[0] == "hopotiservices"){
hopotiBusinessServices();
}
if(multi[0] == "hopotiservicesOK"){
hopotiBusinessServices(true);
history.replaceState({}, document.title, window.location.pathname + window.location.search + "#hopotiservices");
}
} // hashActions ends
// !Remove hash with # sign from url
function removeHash() {
history.pushState("", document.title, window.location.pathname + window.location.search);
}
// !Change skill labels
function relabelSkills(selector) {
// console.log("relabelSkills");
// console.log(selector);
//
$(selector).each(function(index) {
var label;
var UserLevel = $(this).data("userlevel");
var SkillLevelConfirmed = $(this).data("confirmed");
var maxconfirmed = $(this).data("max-confirmed"); // highest confirmed by stable
var NoConfirmation = $(this).data("noconfirmation");
var UnconfirmedLabelHtml = '';
var HorseMinLevel = $(this).data("horselevel");
var HorseMaxLevel = $(this).data("horsemaxlevel");
$(this).empty().append(label);
// console.log("SkillLevelConfirmed: "+SkillLevelConfirmed);
// console.log("UserLevel: "+UserLevel);
//
if(UserLevel > 0 && !NoConfirmation){
if(maxconfirmed){
if(maxconfirmed < UserLevel){
$(this).append(UnconfirmedLabelHtml);
}
} else {
if(!SkillLevelConfirmed){
$(this).append(UnconfirmedLabelHtml);
}
}
// if(maxconfirmed < UserLevel){
// console.log("this??");
// $(this).append(UnconfirmedLabelHtml);
// } else if(!SkillLevelConfirmed){
// $(this).append(UnconfirmedLabelHtml);
// }
//if(SkillLevelConfirmed != 1 && UserLevel > 0){
//}
} else if(!NoConfirmation){
if(UserLevel > 0){
// $(this).append(UnconfirmedLabelHtml);
}
}
// if(SkillLevelConfirmed && !NoConfirmation){
//
// if(SkillLevelConfirmed != 1 && UserLevel > 0){
// $(this).append(UnconfirmedLabelHtml);
// }
//
// } else if(!NoConfirmation){
// if(UserLevel > 0){
// $(this).append(UnconfirmedLabelHtml);
// }
// }
if(HorseMaxLevel != null){ // is horse
$(this).empty();
var skillSlotsHtml = '
0
1
2
3
4
';
$(this).append(skillSlotsHtml);
if(HorseMinLevel == "0"){
$(this).find(".level0").addClass("selected");
} else if (HorseMinLevel == 1) {
$(this).find(".level1").addClass("selected");
} else if (HorseMinLevel == 2) {
$(this).find(".level2").addClass("selected");
} else if (HorseMinLevel == 3) {
$(this).find(".level3").addClass("selected");
} else if (HorseMinLevel == 4) {
$(this).find(".level4").addClass("selected");
}
if (HorseMaxLevel == 1) {
$(this).find(".level1").addClass("selected");
} else if (HorseMaxLevel == 2) {
$(this).find(".level2").addClass("selected");
} else if (HorseMaxLevel == 3) {
$(this).find(".level3").addClass("selected");
} else if (HorseMaxLevel == 4) {
$(this).find(".level4").addClass("selected");
}
if (HorseMaxLevel != HorseMinLevel){
$(this).find(".selected").first().nextUntil(".selected").addClass("selected");
}
} else { // is user
if(UserLevel == 0){
label = "No experience";
} else if (UserLevel == 1) {
label = "Beginner";
} else if (UserLevel == 2) {
label = "Basic skills";
} else if (UserLevel == 3) {
label = "Advanced";
} else if (UserLevel == 4) {
label = "Experienced";
} else {
label = "-";
}
$(this).append(label);
if(viewmode == "xxs"){
$(this).popover({placement : 'top'});
}
}
});
} // relabelSkills ends
// !relabelCurrency
// parse all selected classes for values and convert those to localized prices if contains only numbers, dots and commas - otherwise use as it is
function relabelCurrency(selector) {
$(selector).each(function(index) {
var value = $(this).data("value");
var currency = $(this).data("currency");
var finalvalue = value;
var isValid = /^[0-9,.]*$/.test(value);
if(isValid){
// turn comma to dot
if(value.toString().indexOf(",") >= 0){
value = value.replace(/,/, '.');
}
value = parseFloat(value).toFixed(2);
finalvalue = currencyFormat(value,currency);
}
$(this).html(finalvalue);
});
}
// !escape special characters
function htmlEscape(str) {
if(str){
return str
.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/'/g, ''')
.replace(//g, '>');
}
}
// !unescape special characters
function htmlUnescape(str){
if(str){
return str
.replace(/"/g, '"')
.replace(/'/g, "'")
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/&/g, '&');
}
}
//!Progress counter
function progressBarCounter(index,total,element,custommessage){
var progressCounter = index + 1;
$(element).removeClass("hidden");
console.log(progressCounter+'/'+total);
if(progressCounter >= total){
console.log("progress done");
}
fetchprogress = Math.floor(((progressCounter)/total)*100);
fetchprogress = fetchprogress + "%";
if(custommessage){
$(element).find('.progress-bar').css('width', fetchprogress).html(custommessage);
} else {
$(element).find('.progress-bar').css('width', fetchprogress).html(fetchprogress);
}
}
// !parse stable like links [fav]
function parseFavStableLinks(target){
$(target).each(function() {
var stablefav = $(this).attr("data-fav");
var helpText = 'Add to favourites';
var icon = 'glyphicon-heart-empty';
if(stablefav == 1){
helpText = 'Remove from favourites';
icon = 'glyphicon-heart';
}
if(!myUserId || myUserId < 0){
helpText = 'Sign in to add favourites!';
}
var buttonHtml = '\
'+helpText+'
\
\
';
$(this).empty().html(buttonHtml).removeClass("disabled open disabled-opaque");
});
}
// !Add date selector for calendar
var settingDate = 0;
function addDateSelectorForCalendar(target, view, optTarget, forceadd, placement, container){
settingDate = 1;
var target = $(target);
var calendarDateSelectorAdded = target.data("dateselector-added");
console.log("addDateSelectorForCalendar | added:"+calendarDateSelectorAdded);
var placementTooltip = 'top';
var placementDatepicker = 'auto';
if(placement == 'bottom'){
placementTooltip = 'bottom';
placementDatepicker = 'bottom';
}
var pickerContainer = '.fc-header-toolbar';
if(container){
pickerContainer = container;
}
var currentCalendarDate = $(target).fullCalendar('getDate');
var currentCalendarDatepicker = currentCalendarDate.format('DD.MM.YYYY');
if(!calendarDateSelectorAdded || forceadd){
if(forceadd){
target.find('.calendar-selectday').remove();
}
calendarButtonTooltip = ' data-toggle="tooltip" data-placement="'+placementTooltip+'" data-container="'+pickerContainer+'" title="Select day"';
if(viewmode == "xs" || viewmode == "xxs"){
calendarButtonTooltip = "";
}
var calendarButton = '\
';
if(optTarget){
$(optTarget).find('.calendar-selectday').remove();
$(optTarget).prepend(calendarButton);
} else {
//target.find('.fc-left .fc-button-group').prepend(calendarButton);
target.find('.fc-left').prepend(calendarButton);
}
// var currentCalendarDate = $(target).fullCalendar('getDate');
// var currentCalendarDatepicker = currentCalendarDate.format('DD.MM.YYYY');
var currentCalendarDateBackend = currentCalendarDate.format("YYYY-MM-DD");
var calendarDayOptions = {
format: 'dd.mm.yyyy', // dd.mm.yyyy
autoclose: true,
language: 'en-GB', // fi
todayHighlight: true,
todayBtn: true,
calendarWeeks: true,
orientation: placementDatepicker,
container: container,
weekStart: 1
}
$('.calendar-selectday').datepicker(calendarDayOptions);
$('.calendar-selectday').datepicker('setDate', currentCalendarDatepicker);
$('.calendar-selectday').on('changeDate', function() {
if(!settingDate){
var menuSelectedDate = $(this).datepicker('getDate');
target.fullCalendar('gotoDate', menuSelectedDate);
$('.tooltip').hide();
}
});
$('.calendar-selectday').on('click', function() {
$('.tooltip').hide();
});
target.attr("data-dateselector-added", 1);
$('[data-toggle="tooltip"]').tooltip();
calendarDateSelectorAdded = 1;
}
var buttonTitle;
var pickerDate;
// if(view && view.title){ // use calendar title format if available
// buttonTitle = view.title;
// pickerDate = view.start.format('DD.MM.YYYY');
if(view && view.intervalStart && view.intervalEnd){ // use calendar view settings if available
var startingmoment = view.intervalStart.clone();
var endingmoment = view.intervalEnd.clone().subtract(1, "days"); // select previous from end moment
if(startingmoment.isSame(endingmoment, 'day')){
buttonTitle = startingmoment.format("DD/MM/YYYY");
} else {
buttonTitle = formatDateRange(startingmoment, endingmoment);
}
pickerDate = startingmoment.format('DD.MM.YYYY');
} else {
buttonTitle = currentCalendarDate.format("DD/MM/YYYY");
pickerDate = currentCalendarDatepicker;
}
if(optTarget){
$(optTarget).find('.calendar-selectday-title').html(buttonTitle);
} else {
target.find('.calendar-selectday-title').html(buttonTitle);
}
$('.calendar-selectday').datepicker('setDate', pickerDate);
// set any possible targets for custom date display (printing)
$('body').find('.calendar-date-target').html(buttonTitle);
settingDate = 0;
}
// !Add custom next prev buttons to calendar
function addNextPrevButtonsForCalendar(target, labels, buttondiv, view) {
console.log("addNextPrevButtonsForCalendar");
var elementtarget;
if(buttondiv){
elementtarget = $(buttondiv);
} else {
elementtarget = $(target);
}
elementtarget.each( function(index, e){
var elem = $(e);
var calendarNextPrevAdded = elem.data("nextprevbuttons-added");
var buttonAmount = 2;
var naviStyle = "arrow";
var addCalendarButton = 0;
var scrollTarget ="";
if(buttondiv){
if($(buttondiv).attr("data-navi-style")){
naviStyle = elem.attr("data-navi-style");
}
if($(buttondiv).attr("data-calendar-button")){
addCalendarButton = elem.attr("data-calendar-button");
}
if($(buttondiv).attr("data-scroll-target")){
scrollTarget = 'data-scroll-target="'+elem.attr("data-scroll-target")+'"';
}
}
if(calendarNextPrevAdded){
return false;
}
var prevLabel = '';
var nextLabel = '';
var prevClass = "";
var currentClass = "";
var nextClass = "";
if(naviStyle == "month"){
var prevGone = view.intervalStart < moment();
if(prevGone){
prevClass = " gone";
}
var currentGone = view.intervalEnd < moment();
if(currentGone){
currentClass = " gone";
}
var nextGone = view.intervalEnd.clone().add(1, "month") < moment();
if(nextGone){
nextClass = " gone";
}
var prevThis = view.intervalStart.clone() < moment().add(1, "month") && moment().add(1, "month") < view.intervalEnd.clone();
if(prevThis){
prevClass = " this-month";
}
var currentThis = view.intervalStart.clone() < moment() && moment() < view.intervalEnd.clone();
if(currentThis){
currentClass = " current-this-month";
}
var nextThis = view.intervalStart.clone() < moment().subtract(1, "month") && moment().subtract(1, "month") < view.intervalEnd.clone();
if(nextThis){
nextClass = " this-month";
}
prevLabel = view.intervalStart.clone().subtract(1, "month").format('MMMM');
nextLabel = view.intervalStart.clone().add(1, "month").format('MMMM');
} else if(labels){
prevLabel = ' Older';
nextLabel = 'Newer ';
}
var dateButton = "";
if(view){
if(addCalendarButton){
var dateButtonTitle = view.intervalStart.format('MMMM YYYY');
dateButton = '\
\
';
buttonAmount++;
}
}
var buttonHtml = '\
\
\
'+dateButton+'\
\
';
elem.find('.nextprev-buttons-custom').remove();
elem.append(buttonHtml);
if(!buttondiv){ // static next/prev label buttons, do not rerender always
elem.attr("data-nextprevbuttons-added", 1);
}
});
}
// !MODAL add or edit unregistered user under reservecourse / stable clients / family account
var openDialog;
var selectedActiontype;
var addunregisteredClientModalOpen = 0;
function addunregisteredClientModal(actiontype, identifier) {
if(addunregisteredClientModalOpen){
return false;
}
addunregisteredClientModalOpen = 1;
selectedActiontype = actiontype;
console.log("addunregisteredClientModal / " + actiontype);
var dialogTitle = 'Add participant';
var dialogAcceptText = 'Add';
var passwordContent = '';
var toggleContent = '';
var addchildRequired = '';
var ageRequired = '';
var measuresRequired = ' required="required"';
var phoneRequired = "";
var randomid = Math.floor(Math.random()*10000000);
var notesHtml = '\
\
\
\
\
\
\
State here if the participant has any medical or other conditions the riding instructors should be aware of, such as epilepsy, diabetes, visual impairment, etc. This information is only visible to service provider personnel.\
\
';
if(actiontype == 'new-child' || actiontype == 'edit-child'){ // password part only for adding child accounts and not editing
addchildRequired = "required";
ageRequired = 'required';
toggleContent = '\
\
\
\
';
passwordContent = '\
\
\
\
\
At least 8 characters
\
\
\
\
\
\
\
\
';
dialogTitle = 'New account';
if(identifier){
dialogTitle = 'Edit child account';
dialogAcceptText ='Save changes';
}
addclienthelp1 = 'Add a child without existing Hopoti account. Fill in the fields as accurately as possible so that the business gets precise information about the client.';
if(actiontype == 'edit-child'){
addclienthelp1 = 'Fill in the fields as accurately as possible so that the business gets precise information about the client.';
}
addclienthelp2 = 'By filling in the email and password, the child account can be logged into separately. The child can then log in to Hopoti with their email address and control their events and other information. The email address cannot be the same as the parent’s email.An account can be managed only via the parent account. Bookings will be made with the parent’s account.';
phoneRequired = " required";
} else if(actiontype == 'new-client' || actiontype == 'edit-client' || actiontype == "new-client-lesson"){
measuresRequired = "";
dialogTitle = 'Add a new client';
addclienthelp1 = 'In general, clients should register themselves, then email addresses and other information will be filled in correctly. However, you can use this form to create a client account by asking the client for the required information. The client will receive a Hopoti invitation by email and they can agree on rules and other terms with their own device. Once an account has been created, it can be used immediately for upkeeping.';
addclienthelp2 = 'A client can be added also without an email address. This way, the created preliminary account is meant for temporary use - a client cannot receive notifications about lessons or sign in to their account.';
var notesHtml = '\
\
\
\
\
\
\
This information is not visible to the customer\
\
';
if(identifier){
dialogTitle = 'Edit preliminary client';
dialogAcceptText ='Save changes';
}
} else { // add/edit friend
addclienthelp1 = 'Add participant without a Hopoti account. Fill in the fields as accurately as possible so that the service provider gets precise information about the client.';
addclienthelp2 = 'By filling in the email, you can rest assured that the event entry information will be also sent to the participant. The participant can then log in to Hopoti with their email address and control their events and other information.';
if(identifier){
dialogTitle = 'Edit participant';
dialogAcceptText ='Save changes';
}
}
var addunregisteredClientContent = '\
\
';
BootstrapDialog.show({
size: BootstrapDialog.SIZE_WIDE,
title: dialogTitle,
message: addunregisteredClientContent,
type: BootstrapDialog.TYPE_PRIMARY,
cssClass: 'dialogAddnewClient',
closable: false,
buttons: [{
id: 'btn-ok',
label: ' '+dialogAcceptText,
cssClass: 'btn-success btn-sm pull-left',
autospin: false,
action: function(dialogRef){
openDialog = dialogRef;
$(document).find('.addnewparticipantform').submit();
}
},{
id: 'btn-cancel',
label: ' Cancel',
cssClass: 'btn-default btn-sm',
autospin: false,
action: function(dialogRef){
dialogRef.close();
}
}],
onshow: function(){
fullScreenModalOpen = 1;
},
onshown: function(){
var selectedParticipant;
attachDatepickers("user-birthdate", 2);
if(selectedActiontype == 'new-child'){
checkTelInputFields();
$('input[data-toggle=toggle]').bootstrapToggle();
$('.addclienthelp-2 .independent-login-off').removeClass("hidden");
loadSkills(0);
} else if(selectedActiontype == 'edit-child') {
$('input[data-toggle=toggle]').bootstrapToggle();
$('.addnewparticipantform').addClass("disabled");
var query = "childUserId="+identifier;
// load child data
$.post( '/getChildInfo', query, function(data){
//alert('Saved successfully - the page will be updated for the changes to take effect.');
//window.location.reload();
}).done(function(data){
var childUserName = data[0].UserName;
var childFirstName = data[0].FirstName;
var childLastName = data[0].LastName;
var childSkillLevel = data[0].SkillLevel;
var childWeight = data[0].Weight;
var childHeight = data[0].Height;
var childNote = data[0].Note;
var childContactInfoValue = data[0].ContactInfoValue;
var childBirth = data[0].Birth;
if(childFirstName){
$('.addnewparticipantform input[name="userFirstname"]').val(childFirstName);
}
if(childLastName){
$('.addnewparticipantform input[name="userLastname"]').val(childLastName);
}
if(childSkillLevel > -1){
loadSkills(childSkillLevel);
}
if(childWeight){
$('.addnewparticipantform input[name="userWeight"]').val(childWeight).change();
}
if(childHeight){
$('.addnewparticipantform input[name="userHeight"]').val(childHeight).change();
}
if(childNote){
$('.addnewparticipantform textarea[name="userNote"]').val(childNote);
}
if(childContactInfoValue){
$('.addnewparticipantform input[name="userPhone"]').data("initial-value", childContactInfoValue);
}
if(childBirth && childBirth != "0000-00-00"){
var birthdate = moment(childBirth, "YYYY-MM-DD").toDate();
$('.addnewparticipantform input.user-birthdate').datepicker('setDate', birthdate);
}
$('.addnewparticipantform input[name="childUserId"]').val(identifier);
if(childUserName){
temporaryUserExtension = '@random.hopoti.com';
if(childUserName.indexOf(temporaryUserExtension) != -1){ // is temporary user
$('.addnewparticipantform .independent-login-off').removeClass("hidden");
} else { // is proper user with mail
$('.addnewparticipantform .addclienthelp-2').hide();
$('.addnewparticipantform .checkbox').hide();
}
}
checkTelInputFields();
$('.addnewparticipantform').removeClass("disabled");
}).fail(function(xhr, status, error) {
BootstrapDialog.show({
title: 'Saving failed for some reason',
message: 'This may be because of the information you entered, a weak Internet connection or temporary disruption in the service. Please check the information you entered and your Internet connection and try again in a moment. If the problem persists, contact our customer service.',
buttons: [{
label: 'OK',
action: function(failDialog) {
failDialog.close();
//dialog.close();
}
}],
closable: false,
type: BootstrapDialog.TYPE_DANGER
});
});
} else if(selectedActiontype == 'edit-client') {
getStableTempCustomerInfo(identifier);
} else if(selectedActiontype == 'new-friend' || selectedActiontype == 'edit-friend' ) {
$('.independent-login-email').removeClass("hidden");
if(identifier > -1){
selectedParticipant = selectedParticipants[identifier];
console.log("selectedParticipant");
console.log(selectedParticipant);
// Populate form
$('input[name="index"]').val(identifier);
$('input[name="userFirstname"]').val(selectedParticipant.FirstName);
$('input[name="userLastname"]').val(selectedParticipant.LastName);
$('.addnewparticipantform input[name="userPhone"]').data("initial-value", selectedParticipant.userPhone);
$('textarea[name="userNote"]').val(selectedParticipant.userNote);
$('input[name="userWeight"]').val(selectedParticipant.userWeight);
$('input[name="userHeight"]').val(selectedParticipant.userHeight);
$('input[name="action"]').val(selectedParticipant.action);
if(selectedParticipant.userBirth && selectedParticipant.userBirth != "0000-00-00"){
var birthdate = moment(selectedParticipant.userBirth, "YYYY-MM-DD").toDate();
$('.addnewparticipantform input.user-birthdate').datepicker('setDate', birthdate);
}
if(selectedParticipant.SkillLevel){
loadSkills(selectedParticipant.SkillLevel);
} else {
loadSkills(0);
}
if(selectedParticipant.UserName){
$('input[type="email"]').val(selectedParticipant.UserName);
}
} else {
loadSkills(0);
}
checkTelInputFields();
} else {
$('.independent-login-email').removeClass("hidden");
checkTelInputFields();
}
$("[data-toggle=popover]").popover();
$('.addnewparticipantform').validator('update');
// force validation on editing
if(selectedActiontype == 'edit-friend' || selectedActiontype == 'edit-child' || selectedActiontype == 'edit-client' || selectedActiontype == 'new-client-lesson' ){
setTimeout(function(){
$('.addnewparticipantform').validator('validate');
}, 1000);
}
},
onhide: function(){
fullScreenModalOpen = 0;
addunregisteredClientModalOpen = 0;
}
});
}// full screen modal for add unregistered user ends
// !SUBMIT Add new participant dialog
$(document).on('submit', '.addnewparticipantform', function(e){
if (e.isDefaultPrevented()) {
// handle the invalid form...
} else {
// everything looks good!
e.preventDefault();
$('#btn-ok').addClass("disabled");
if(selectedActiontype == "new-child"){
submitNewChildAccount("new-child");
} else if(selectedActiontype == "edit-child") {
submitNewChildAccount("edit-child");
} else if(selectedActiontype == "new-friend" || selectedActiontype == "edit-friend") {
var formdata = getFormData($('.addnewparticipantform'));
var userbirth = "";
var userbirthdate = $('.addnewparticipantform .user-birthdate:visible').datepicker('getDate');
if(moment(userbirthdate).isValid()){
var converteddate = moment(userbirthdate).format("YYYY-MM-DD");
formdata.userBirth = converteddate;
}
formdata.action = selectedActiontype;
addNewFriend(formdata, selectedActiontype);
openDialog.close();
} else if(selectedActiontype == "new-client" || selectedActiontype == "new-client-lesson"){
submitNewClientAccount(selectedActiontype);
} else if(selectedActiontype == "edit-client"){
submitTempClientEdit();
}
}
})
// !POST new child account data
function submitNewChildAccount(actiontype){
var query = $('.addnewparticipantform').serialize();
console.log(query);
var reserveServicePage = false;
if($('body').hasClass("page-reserveservice-v1")){
reserveServicePage = true;
}
if(actiontype == "new-child"){
submiturl = "/addNewChild";
} else { // edit
submiturl = "/editChild";
}
var userbirth = "";
var userbirthdate = $('.addnewparticipantform .user-birthdate:visible').datepicker('getDate');
if(moment(userbirthdate).isValid()){
var converteddate = moment(userbirthdate).format("YYYY-MM-DD");
userbirth = '&userBirth='+converteddate;
}
$.post( submiturl, query+userbirth, function(data){
// console.log("after submit child!");
// console.log(data);
if(reserveServicePage){
loadFriends("buy-service", data);
} else { // editing under user settings
alert('Saved successfully - the page will be updated for the changes to take effect.');
window.location.reload();
}
})
.fail(function(xhr, status, error) {
BootstrapDialog.show({
title: 'Saving failed for some reason',
message: 'This may be because of the information you entered, a weak Internet connection or temporary disruption in the service. Please check the information you entered and your Internet connection and try again in a moment. If the problem persists, contact our customer service.',
buttons: [{
label: 'OK',
action: function(failDialog) {
failDialog.close();
//dialog.close();
}
}],
closable: false,
type: BootstrapDialog.TYPE_DANGER
});
}).always(function() {
$('#btn-ok').removeClass("disabled");
});
}
//!Load friends [services]
function loadFriends(action, actiondata){
console.log("loadFriends | action: "+action);
$.ajax({
url: '/profile//friends',
type: 'POST',
error: function(err) {
},
success: function(data) {
// console.log("after friends reload!");
// console.log(data);
if(action == "buy-service"){
friendsJSON = data;
friendsJSON.push(myInfoObject);
if(actiondata && actiondata[0].UserId){
addFriendToService(actiondata[0].UserId);
}
buildParticipantSelection(selectedParticipants, participantCount, serviceTags);
openDialog.close();
}
}
});
}
//!Menu stable search function
function searchAndFilter(searchTerm) {
$('.menu-stable-hidden').addClass("hidden");
if (searchTerm == '') {
$("#topFavStables li").show()
} else {
$("#topFavStables li a.favStableLink").each(function() {
var currentText = $(this).text();
currentText = currentText.toUpperCase();
searchTerm = searchTerm.toUpperCase();
if (currentText.indexOf(searchTerm) >= 0) {
$(this).parent().removeClass("hidden").show();
} else {
$(this).parent().hide();
}
});
}
}
// !Build common event calendar - list courses
function buildCommonEventCalendar(data, targetelement, mode, userid){
console.log("buildCommonEventCalendar");
if(!data.length || !targetelement){
return false;
}
$(targetelement).empty();
if(!mode){
mode = "admin";
}
var listTitle = 'Lessons related to invoice';
if($(targetelement).data("list-title")){
listTitle = $(targetelement).data("list-title");
}
var calendarId = 'invoicecourses';
if($(targetelement).data("calendar-id")){
calendarId = $(targetelement).data("calendar-id");
}
var targetInputField;
if($(targetelement).data("select-input")){
targetInputField = $(document).find('#'+$(targetelement).data("select-input"));
}
var editPpButton = "";
$(targetelement).addClass("panel panel-default");
$(targetelement).attr('id', calendarId);
instanceCalEvents = [];
var firstdate;
var firstEventId;
var deletedAmount = 0;
var deletedAlert = "";
$.each(data, function (index, value) {
// get first invoice date
var currentinvoicedate = value['EventStartDateTime'].substr(0, 10);
var currentinvoicedatemoment = moment(currentinvoicedate);
if(currentinvoicedatemoment < moment(firstdate)){
firstdate = currentinvoicedate;
}
if(!firstEventId){
firstEventId = value.EventInstanceId;
}
if(value.Deleted){
deletedAmount++;
}
instanceCalEvents.push({
id: value['EventInstanceId'],
title: value['InstanceName'],
start: value['EventStartDateTime'],
end: value['EventEndDateTime'],
usermaxcount: value['UserMaxCount'],
reservationcount: value['ReservedCount'],
eventprice: value['EventPrice'],
eventsalesstatustypeid: value['EventSalesStatusTypeId'],
deleted: value['Deleted']
});
});
if(mode == "admin"){
var editPppButton = $('body').find('.dialog-edit-pending-payment-plan .change-ppp-events');
editPppButton.removeClass("hidden");
editPppButton.attr("data-userid", userid);
editPppButton.attr("data-eventinstanceid", firstEventId);
var markAsPaidButton = $('body').find('.dialog-edit-pending-payment-plan .invoice-mark-paid');
markAsPaidButton.attr("data-invoice-lesson-amount", data.length);
}
var selectButtons = "";
if(mode == "select" || mode == "select-preselect"){
selectButtons = '\
';
$(targetelement).append(panelHtml);
if(mode == "user" && deletedAmount){ // show alert under user
var amountString = ' lesson';
if(deletedAmount > 1){
amountString = ' lessons';
}
var deletedHelp = 'Some invoice-related lessons have been canceled on behalf of the business. When the invoice is paid you will receive Stablecard credits ([x]) with which to book a replacement lesson.'.replace("[x]", ''+deletedAmount+amountString+'');
deletedAlert = '\
\
'+deletedHelp+'\
';
$(targetelement).parent().prepend(deletedAlert);
}
var ntoday = new Date().getTime();
var offset = new Date().getTimezoneOffset()
ntoday = ntoday - offset;
var renderedEventIds = []; // already rendered events to block multiday event extra rows
var tooltipPlacement = "left";
var viewmode = $('body').attr("data-viewmode");
$(targetelement).find('.common-event-calendar-courses').fullCalendar({
defaultView: 'agendaYearList',
events: instanceCalEvents,
defaultDate: moment(firstdate), // show list based on first event date
locale: 'en-GB',
timeFormat: 'HH:mm',
titleFormat: 'DD/MM/YYYY',
slotLabelFormat: 'HH:mm',
views: {
agendaYearList: {
type: 'listYear',
duration: { months: 24 },
}
},
eventClick: function(event, jsEvent, view) {
if(mode == "select" || mode == "select-preselect"){
if($(jsEvent.target).hasClass("btn")){ // exclude button clicks under list element
return false;
}
$(this).toggleClass("selected");
if(targetInputField){ // pick event ids to separate input field if present
var currentValues = targetInputField.val();
var currentValueArray = [];
if(currentValues){
currentValueArray = currentValues.split(",");
}
if(currentValueArray.indexOf(event.id.toString()) > -1){
currentValueArray.splice(currentValueArray.indexOf(event.id.toString()), 1);
} else {
currentValueArray.push(event.id.toString());
}
targetInputField.val(currentValueArray).change();
}
}
},
eventRender: function(event, element, view) {
var buttons = "";
var preselectedClass = "";
startDateTime = moment(event.start, "YYYY-MM-DD HH:mm");
endDateTime = moment(event.end, "YYYY-MM-DD HH:mm");
eventStartTime = moment(event.start).format("HH:mm");
eventEndTime = moment(event.end).format("HH:mm");
eventStartDate = moment(event.start).format("DD/MM/YYYY");
eventEndDate = moment(event.end).format("DD/MM/YYYY");
eventStartDayname = moment(event.start).format('dd');
eventEndDayname = moment(event.end).format('dd');
var eventGone = 0;
// filter off all already rendered multiday event rows
var eventAlreadyRendered = commonmatch(event.id, renderedEventIds);
if(eventAlreadyRendered.length){
return false;
}
if (!endDateTime){
if (startDateTime < ntoday){
eventGone = 1;
}
} else {
if (endDateTime < ntoday){
eventGone = 1;
}
}
renderedEventIds.push(event.id);
var unpaidClass = "";
if(event.userhaspaid != 1){
unpaidClass = " pending-danger";
}
var deletedClass = "";
var deletedHelp = "";
if(event.deleted){
deletedClass = " event-deleted";
deletedHelp = 'Event deleted';
}
eventTimes = ''+eventStartDate+' ('+eventStartDayname+') '+eventStartTime+'-'+eventEndTime;
if(eventEndDate != eventStartDate){
eventTimes = ''+eventStartDate+' ('+eventStartDayname+') '+eventStartTime+' - '+eventEndDate+' ('+eventEndDayname+') '+eventEndTime;
}
var eventSymbols = "";
if(mode == "select" || mode == "select-preselect"){
unpaidClass = "";
eventSymbols = ' ';
}
if(mode == "select-preselect"){
preselectedClass = " selected";
}
var eventMeta = '\
')
}
$(this).find('.stableCard-credits span').empty().append(workCount);
});
}
//function swedishIdCheck(a,b,c,d){c='';for(b=d=0;b<10;b++)c+=b!=6?a[b]*(d++%2||2):'';b=0;for(d in c)b+=c[d]*1;return b*9%10==a[10]}
function isValidSwedishSSN(ssn) {
ssn = ssn
.replace(/\D/g, "") // strip out all but digits
.split("") // convert string to array
.reverse() // reverse order for Luhn
.slice(0, 10); // keep only 10 digits (i.e. 1977 becomes 77)
// verify we got 10 digits, otherwise it is invalid
if (ssn.length != 10) {
return false;
}
var sum = ssn
// convert to number
.map(function(n) {
return Number(n);
})
// perform arithmetic and return sum
.reduce(function(previous, current, index) {
// multiply every other number with two
if (index % 2) current *= 2;
// if larger than 10 get sum of individual digits (also n-9)
if (current > 9) current -= 9;
// sum it up
return previous + current;
});
// sum must be divisible by 10
return 0 === sum % 10;
};
// !Replace all text strings
String.prototype.replaceAllText = function(searchStr, replaceStr) {
var str = this;
// no match exists in string?
if(str.indexOf(searchStr) === -1) {
// return string
return str;
}
// replace and remove first match, and do another recursirve search/replace
return (str.replace(searchStr, replaceStr)).replaceAllText(searchStr, replaceStr);
}
// !Build Checkout Payment options [checkout]
function buildCheckoutPaymentoptions(paymentResponse){
console.log("buildCheckoutPaymentoptions");
// if paying under stable or user
var mode = "stable";
if($('body').hasClass("pageUserPendingPayments")){
mode = "user";
}
var paymentOptions = paymentResponse;
var paymentOptionsHtml = '';
if(!paymentResponse){
return false;
}
var checkoutGrouping = [
{
"group": "bank",
"title": "Online banking",
"amount": 0,
"html": "",
"logohtml": ""
},{
"group": "creditcard",
"title": "Card payments",
"amount": 0,
"html": "",
"logohtml": ""
},{
"group": "mobile",
"title": "Mobile payments",
"amount": 0,
"html": "",
"logohtml": ""
},{
"group": "credit",
"title": "Credit payments",
"helptitle": "Invoice and part payment options",
"amount": 0,
"html": "",
"logohtml": ""
},{
"group": "other",
"title": "Other",
"amount": 0,
"html": "",
"logohtml": ""
}
];
var extraDescriptionOplaskuId = 'oplasku';
var extraDescriptionOplaskuId2 = 'oplaskuV1';
var extraDescriptionOplasku = 'Pay all at once or split the payment into instalments. An invoice received by email will have a payment time of 45 days with no interest added. Credit includes fixed interest rate and monthly service fee. Continue to pay for more details.';
var extraDescriptionCollectorId = 'collectorb2c';
var extraDescriptionCollector = 'Pay all at once or, if you are granted an account credit, you can also split the payment into instalments. You will receive an invoice via email, and you can easily apply for an account credit online. Continue to pay for more details.';
var lastPaymentType;
if(store.get('settings-payment')){
lastPaymentType = store.get("settings-payment").lastpaymenttype;
}
var lastUsedFound = 0;
var lastUsedGroup = "";
$('body').find('.checkoutForm').remove();
$('.payment-options').empty();
$.each(paymentOptions, function(key, paymentOption) {
// console.log("paymentoption");
var paymentName = paymentOption.name;
var paymentCode = paymentOption.id;
var paymentGroup = paymentOption.group;
var paymentLogo = paymentOption.icon;
var formOptions = paymentOption.parameters;
var paymentId = paymentCode + "-"+key;
var lastUsedHelp = "";
if(paymentId == lastPaymentType && paymentGroup != "credit"){ // exclude credit options from preselected payment type
lastUsedFound = 1;
lastUsedGroup = paymentGroup;
lastUsedHelp = 'Last used payment type';
}
var extraDescription = '';
if(paymentCode == extraDescriptionCollectorId){
extraDescription = extraDescriptionCollector;
} else if (paymentCode == extraDescriptionOplaskuId || paymentCode == extraDescriptionOplaskuId2){
extraDescription = extraDescriptionOplasku;
}
if(extraDescription){
extraDescription = '
'+extraDescription+'
';
}
var extraInfoSetting = 0;
if(paymentGroup == "credit"){
extraInfoSetting = 1;
}
var paymentOptionHtml = '\
';
$('body').find(".dialogPaymentSelection .payments-pendingpayments").append(finalOptionsHtml);
$('body').find('#paymentExtraInfo').validator('update');
} else { // under stable
$('.payment-options').append(finalOptionsHtml);
$('.panel-extra-form').append(checkoutExtraInfoHtml);
$('body').find('#paymentExtraInfo').validator('update');
}
// if(lastUsedFound){ // removing preselected payment type per eu regulations 16.08.2023
// selectPaymentOption(lastPaymentType, mode);
// var target = $('.payment-group-'+lastUsedGroup);
// target.addClass("in");
// }
}
var checkoutPreSubmitConfirmationOk = 0;
// !Checkout reminder to return to Hopoti after payment
function checkoutPreSubmitConfirmation(mode){
var preSubmitContentHtml = 'Return to Hopoti after the payment!
After a successful transaction, tap \"Return to service\" or similar button. Don\'t close the window until you see the Hopoti confirmation page. If you close the window immediately after the transaction and before the Hopoti confirmation page, the payment will appear in Hopoti after 1–3 days delay.';
var checkoutPreSubmitConfirmDialog = BootstrapDialog.show({
title: 'You are redirected to payment service',
message: preSubmitContentHtml,
type: BootstrapDialog.TYPE_WARNING,
closable: false,
btnOKLabel: 'messages-general.ok',
btnOKClass: 'btn-default btn-sm pull-left',
buttons: [{
icon: 'glyphicon glyphicon-ok',
label: 'OK',
cssClass: 'btn-default btn-sm',
autospin: false,
action: function(dialogRef){
checkoutPreSubmitConfirmationOk = 1;
dialogRef.close();
if(mode == "user-invoices"){
submitCheckoutPaymentRequest();
} else {
buildSubmitQuery("submit");
}
}
}]
});
checkoutPreSubmitConfirmDialog.open();
}
// ! *** Select payment option (bank etc) ***
function selectPaymentOption(paymentOptionId, mode){
console.log("selectPaymentOption");
console.log(paymentOptionId);
$('.payment-options button, .payment-options-loaded button').removeClass("active");
$('.select-payment-option-button[data-payment-id="'+paymentOptionId+'"]').addClass("active").removeClass("hidden").parent().removeClass("hidden");
var paymentProvider = $('.select-payment-option-button[data-payment-id="'+paymentOptionId+'"]').attr("data-payment-provider");
if(paymentProvider == "checkout") { // checkout
} else { // mt
$('.select-payment-option-button:not(.active)').parent().slideUp(300);
$('.btn-change-payment-type').show().removeClass("hidden");
}
selectedPaymentOption = {};
selectedPaymentOption.code = paymentOptionId;
selectedPaymentOption.name = $('.select-payment-option-button[data-payment-id="'+paymentOptionId+'"]').attr("data-payment-name");
selectedPaymentOption.extrainfo = $('.select-payment-option-button[data-payment-id="'+paymentOptionId+'"]').attr("data-payment-extrainfo");
selectedPaymentOption.paymentgroup = $('.select-payment-option-button[data-payment-id="'+paymentOptionId+'"]').attr("data-payment-group");
if(viewmode == "xs" || viewmode == "xxs"){
if($("#select-payment").length){
$('html, body').animate({
scrollTop: $("#select-payment").offset().top
}, 500);
}
if(paymentProvider == "checkout") { // hide other checkout options on mobile
$('.select-payment-option-button:not(.active)').parent().slideUp(300);
$('.select-payment-group-button').removeClass("open");
setTimeout(function(){
$('.select-payment-option-button:not(.active)').parent().addClass("hidden").show();
}, 300);
}
}
if(mode != "user"){
processSelection();
} else {
validatePaymentForm();
}
}
function resetPaymentOption(){
console.log("resetPaymentOption");
$('.payment-options button, .payment-options-loaded button').removeClass("active");
$('.panel-extra-info').addClass("hidden");
$('#summaryPaymentmethod').html(' Please choose payment method')
selectedPaymentOption = null;
}
//!contentAreaSubnaviCheck [scroll]
function contentAreaSubnaviCheck(){
if(viewmode == "xs" || viewmode == "xxs"){
// console.log("contentAreaSubnaviCheck");
var subnavielement = $('ul.horizontal-scroll-navi');
subnavielement.find(".scroll-indicator-left, .scroll-indicator-right").remove();
subnavielement.removeClass("scroll-horizontally scroll-right scroll-left");
if(subnavielement.length){
var naviwidth = subnavielement.width();
var contentwidth = 0;
$(subnavielement.find('li').not('.hidden-xs')).each(function(index, item){
var itemwidth = $(item).outerWidth();
contentwidth = contentwidth + itemwidth;
});
// add scrolling if content doesn't fit
if(naviwidth < contentwidth){
subnavielement.addClass("scroll-horizontally scroll-right");
var scrollIndicators = '';
subnavielement.append(scrollIndicators);
}
// scroll automatically to active navi item only if it doesn't fit to navi
var activeItem = subnavielement.find('.active');
if(activeItem.length){
var activeLeft = activeItem.position().left;
var activeWidth = activeItem.outerWidth();
if(activeLeft+activeWidth > naviwidth){
$('ul.horizontal-scroll-navi').animate({scrollLeft: activeLeft-15}, 700);
}
}
}
}
}
//!horizontalScrollCheck [scroll]
function horizontalScrollCheck(item){
console.log("horizontalScrollCheck");
item.removeClass("scroll-both scroll-left scroll-right");
var width = item.outerWidth()
var scrollWidth = item[0].scrollWidth;
var scrollLeft = item.scrollLeft();
if (scrollWidth - width === scrollLeft){
item.addClass("scroll-left");
} else if (scrollLeft == 0){
item.addClass("scroll-right");
} else {
item.addClass("scroll-both");
}
}
// !Check if element vs content is scrollable (with tolerance)
function isScrollableY (element) {
var elementheight = element.outerHeight();
var childheight = element.children().outerHeight();
var tolerance = 3; // how many pixels to scroll before considering element scrollable
if(childheight > elementheight + tolerance){
return true;
} else {
return false;
}
}
function checkClusterHeaders(){
$('.clusterize-content').each(function(index, item){
var clusterWidth = $(this).width();
var clusterHeaderTarget = $(this).closest(".clusterize").find(".clusterize-div-table-header");
if(clusterWidth && clusterHeaderTarget.length){
clusterHeaderTarget.width(clusterWidth);
}
});
}
//!just return glyphicon from string
function getIcon(icon){
//console.log(icon);
if(icon && icon.match("_")){
icon = icon.replace("_"," ");
}
if(!icon){
return "";
}
if (icon.match("glyphicon-")) {
return ' ';
} else if(icon.match("fa-")){
if(icon.match("fa-solid") || icon.match("fa-regular" || icon.match("fa-light") || icon.match("fa-thin") || icon.match("fa-duotone") || icon.match("fa-sharp"))){
return ' ';
} else {
return ' ';
}
} else {
return "";
}
}
var shareLinkDialogOpen = 0;
var shareLinkDialog;
// !Common share link button etc
function buildShareLinkContent(element, link, linktext, messagetext, dialogMode, showDialog){
// console.log("buildShareLinkContent");
// console.log(element);
var target;
if(element){
target = $(element);
}
var shareLink = link;
var shareText = messagetext;
var shareLinkClass = "hidden";
var shareButtonClass = "";
var shareLinkButton = '\
\
'+linktext+'\
';
var shareLinkArea = '';
if(!dialogMode){
shareLinkArea = '\
';
} else {
shareLinkClass = "";
}
var shareLinkContent = '\
';
}
if(imageAction == "validate-diary"){
validateDiary();
}
if(blob){
return buttonElements;
} else {
$(targetelement).empty().append(buttonElements);
$(targetelement).removeClass("hidden");
$('[data-toggle="tooltip"]').tooltip();
}
}
//!images remove common image
function removeCommonImage(targetelement){
console.log("removeCommonImage");
$('[data-toggle="tooltip"]').tooltip("hide");
var buttonElementTarget = targetelement.closest(".image-button-parent");
changeImageButton(buttonElementTarget);
var formName = buttonElementTarget.data('formname');
buttonElementTarget.append('');
}
function checkBetaFeatures(betalevel){
console.log("checkBetaFeatures - level:"+betalevel);
if(betalevel && betalevel > 0 && !hopotiPlusPublished){
//Insert beta note button to elements
var betaHtml = '\
\
Learn more about the Beta Program\
';
$('.beta-alert').append(betaHtml).removeClass("hidden");
} else {
$('.beta-alert').remove();
}
}
function betaTesterDialog(){
var betaDialogContent = '\
\
\
Congratulations, you are now a member of the Hopoti Beta Program! This means you can use Hopoti features that are still under development and will be released later, well ahead of other users. In return, we would love to hear your feedback on the features under development, as user feedback is one of the most important tools for us. Thanks!
Here are a few things to keep in mind:
Features are still under development, so unfortunately you may occasionally encounter errors.
In case of an error, be sure to contact us via feedback or chat.
Features and availability may still change in the final version.
Please do not publicise the features of the beta program, especially with images or videos.
Thank you in advance for participating in our Beta Program!
Hopoti Team
\
';
BootstrapDialog.show({
title: 'Learn more about the Beta Program',
message: betaDialogContent,
type: BootstrapDialog.TYPE_DANGER,
cssClass: 'dialog-beta-tester',
buttons: [
{
// id: 'btn-ok',
label: ' Send feedback',
cssClass: 'btn-success btn-sm pull-left btn-beta-feedback',
autospin: false,
action: function(dialogRef){
}
},
{
id: 'btn-cancel',
label: 'Close',
cssClass: 'btn-default btn-sm',
autospin: false,
action: function(dialogRef){
dialogRef.close();
}
}],
onshow: function(){
},
onshown: function(){
},
onhide: function(){
}
});
}
//!Mobile calendar navi [calendar][diary]
var naviCalRenderedHcGroupEvents = [];
var naviCalRenderedEventIds = [];
function initNaviCalendar(target, mother){
$(target).fullCalendar({
customButtons: {
customPrev: {
click: function() {
animateCalendarStart(mother);
$(mother).fullCalendar('prev');
}
},
customNext: {
click: function() {
animateCalendarStart(mother);
$(mother).fullCalendar('next');
}
},
customToday: {
text: 'Today',
click: function() {
animateCalendarStart(mother);
$(mother).fullCalendar('today');
}
}
},
buttonIcons: {
customPrev: 'fc-icon-left-single-arrow',
customNext: 'fc-icon-right-single-arrow'
},
header: {
left: 'customPrev,customNext customToday title',
right: ''
},
titleFormat: 'MMMM YYYY', // DD.MM.YYYY
firstDay: 1,
eventRender: function(event, element, view) {
var countType = "event";
if(event.type == "polar" && userCalendarFilters.includes(7) && !commonmatch(userCalendarFilters, [1,2,6]).length && event.connected){ // is polar
return false;
} else if(event.type == "polar" && event.connected){
countType = "polar";
}
if(event.invoiceevent && !userCalendarFilters.includes(5)){ // is invoice
return false;
} else if(event.invoiceevent){
countType = "invoice";
}
if (event.horseeventtypeid && !userCalendarFilters.includes(4)){ //is horsecare
return false;
} else if(event.horseeventtypeid && userCalendarFilters.includes(4)){ // prevent counting hc events multiple times
if(naviCalRenderedHcGroupEvents.includes(event.sourceObject.HorseEventGroupId)){
return false;
} else {
countType = "horsecare";
naviCalRenderedHcGroupEvents.push(event.sourceObject.HorseEventGroupId);
}
}
if (event.DiaryEventId && !userCalendarFilters.includes(3)){ // is diary
return false;
} else if(event.DiaryEventId) {
countType = "diary";
}
if(event.userevent && !userCalendarFilters.includes(1)){ // filter own events
return false;
}
if(event.childevent && !userCalendarFilters.includes(2)){ // filter child events
return false;
}
if(event.trainerevent && !userCalendarFilters.includes(6)){ // filter training events
return false;
}
if(event.lessonevent && !userCalendarFilters.includes(8)){ // filter gone events (shown if rating not done)
//return false;
}
// if(event.lessonevent && event.end.clone().add(14, "days") < moment() && !userCalendarFilters.includes(7)){ // filter gone events (shown if rating not done)
// return false;
// }
var eventrange;
if(event.start && event.end && event.start.format("YYYY-MM-DD") != event.end.clone().subtract(1, "days").format("YYYY-MM-DD")){
eventrange = enumerateDaysBetweenDates(event.start.clone(), event.end.clone(), "moment");
} else if(event.start){
eventrange = [event.start];
}
if(event.id && !event.trainerevent){
if(naviCalRenderedEventIds.includes(event.id)){
return false;
} else {
naviCalRenderedEventIds.push(event.id)
}
}
if(eventrange){
$(eventrange).each(function(index, item){
var startdate = item.format("YYYY-MM-DD");
var caltarget = $(target).find('.fc-day[data-date="'+startdate+'"]');
var currentvalue = caltarget.attr('data-'+countType+'-count');
if(currentvalue == 0 || !currentvalue){
currentvalue = 1;
} else {
currentvalue++;
}
caltarget.attr('data-'+countType+'-count', currentvalue);
});
}
return false;
},
eventAfterAllRender: function(event, element, view) {
$('.fc-day[data-event-count]').each(function(index, item){
var eventcount = $(this).data("event-count");
$(this).append(''+eventcount+'');
});
$('.fc-day[data-diary-count]').each(function(index, item){
var eventcount = $(this).data("diary-count");
if(eventcount == 1){
eventcount = "";
}
$(this).append(''+eventcount+'');
});
$('.fc-day[data-horsecare-count]').each(function(index, item){
var eventcount = $(this).data("horsecare-count");
if(eventcount == 1){
eventcount = "";
}
$(this).append(''+eventcount+'');
});
$('.fc-day[data-invoice-count]').each(function(index, item){
var eventcount = $(this).data("invoice-count");
if(eventcount == 1){
eventcount = "";
}
$(this).append(''+eventcount+'');
});
naviCalRenderedHcGroupEvents = naviCalRenderedEventIds = [];
},
dayClick: function(date, jsEvent, view) {
// clicked outside current month
if(date < view.intervalStart){
$(mother).fullCalendar('prev');
} else if(date > view.intervalEnd){
$(mother).fullCalendar('next');
} else {
$(mother).fullCalendar('gotoDate', moment(date));
animateCalendarDayScroll(moment(date));
setTimeout(function(){
$('body').removeClass("show-header-date-picker");
}, 100);
}
}
});
$('.navi-calendar-wrapper').on('click', function(e) {
if($(e.target).hasClass("navi-calendar-wrapper")){
setTimeout(function(){
$('body').removeClass("show-header-date-picker");
}, 100);
}
});
}
function refreshNaviCalendar(target, mother, events){
console.log("refreshNaviCalendar");
// console.log(events);
var motherdate = $(mother).fullCalendar('getDate');
$(target).fullCalendar('gotoDate', moment(motherdate));
$(target).find('.fc-day').attr('data-event-count', null);
$(target).find('.fc-day').attr('data-horsecare-count', null);
$(target).find('.fc-day').attr('data-invoice-count', null);
$(target).find('.fc-day').attr('data-diary-count', null);
$(target).find('.event-count, .horsecare-count, .invoice-count, .diary-count').remove();
$(target).fullCalendar('removeEvents');
$(target).fullCalendar('addEventSource', events);
}
function animateCalendarDayScroll(momentdate){
console.log("animateCalendarDayScroll");
console.log(momentdate);
var dateformat = momentdate.format("YYYY-MM-DD");
var datedate = momentdate.toDate();
var target = $(document).find('.fc-list-heading[data-date="'+dateformat+'"]');
if(!target.length){ // selected date doesn't contain events - find the closest one which does
var allHeadings = $('.fc-list-heading[data-date]');
var availableDates = [];
$(allHeadings).each(function(index, item){
var singleDate = $(item).data("date");
availableDates.push(moment(singleDate, "YYYY-MM-DD").toDate());
});
var closestDates = availableDates.sort(function(a, b) {
var distancea = Math.abs(datedate - a);
var distanceb = Math.abs(datedate - b);
return distancea - distanceb;
});
var closestDateFormat = moment(closestDates[0]).format("YYYY-MM-DD");
target = $(document).find('.fc-list-heading[data-date="'+closestDateFormat+'"]');
}
if(target.length){
$('html, body').animate({
scrollTop: $(target).offset().top-60
}, 700);
}
}
function animateCalendarStart(mother){
var position = $(mother).position().top;
var headercontainerheight = $('.headercontainer-2019').height();
$('html, body').animate({
scrollTop: position+headercontainerheight-15
}, 700);
}
function truncate(str, limit) {
var trimmable = '\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u2028\u2029\u3000\uFEFF';
var reg = new RegExp('(?=[' + trimmable + '])');
var words = str.split(reg);
var count = 0;
var result = words.filter(function(word) {
count += word.length;
return count <= limit;
}).join('');
if(count > limit){
result += '...';
}
return result;
}
//!Common validate for submit button - disables button click, shows error field title and slides dialog to missing info location on click [validate]
function validationButtonFail(target, saveButton){
console.log("validationButtonFail");
var erroramount = 0;
var fieldLabel = [];
var fieldLabelContent;
var errorTooltip = "";
target.find('.has-error:visible').each(function() {
erroramount++;
if(erroramount == 1){
fieldLabel = $(this).find('label');
if(fieldLabel.length){
fieldLabelContent = fieldLabel.html();
}
}
});
if(fieldLabel.length && erroramount > 0){
var errorAmountString = "";
if(erroramount == 2){
errorAmountString = ' and one more detail';
} else if(erroramount > 2){
errorAmountString = ' and [x] more details'.replace("[x]", erroramount-1);
}
errorTooltip = 'Info missing: '+fieldLabelContent+''+errorAmountString;
saveButton.unbind();
saveButton.bind("click", function() {
fieldLabel[0].scrollIntoView({
behavior: "smooth",
block: "start"
});
});
}
validationButtonDisable(saveButton, errorTooltip);
}
// disable submit
function validationButtonDisable(saveButton, tooltip, showtooltip){
saveButton.addClass("disabled-continue");
if(tooltip){
var errorString = "";
if(tooltip.constructor === Array){ // if given an array of errors
if(!tooltip.length){
return false; // empty array
}
var errorAmountString = "";
if(tooltip.length == 2){
errorAmountString = ' and one more detail';
} else if(tooltip.length > 2){
errorAmountString = ' and [x] more details'.replace("[x]", tooltip.length-1);
}
errorString = 'Info missing: '+tooltip[0]+''+errorAmountString;
} else { // only an error string
errorString = tooltip;
}
saveButton.attr('data-toggle', 'tooltip');
saveButton.attr('data-trigger', 'hover focus');
saveButton.attr('data-html', 'true');
saveButton.attr('data-original-title', errorString);
if(showtooltip){
saveButton.tooltip("show");
} else {
saveButton.tooltip();
}
}
}
//!Common validate ok, remove tooltip and disabled class
function validationButtonOk(saveButton){
console.log("validationButtonOk");
saveButton.tooltip('destroy');
saveButton.removeClass("disabled-continue");
}
// cross reference multiple arrays
// USAGE:
// values: ['name', 'credits']
// source: ['name', 'credits', 'price', 'vat', 'validNumber', 'description']
// target: ['Nimi', 'Saldo', 'Hinta', 'ALV', 'Voimassa', 'Kuvaus']
// return: ['Nimi', 'Saldo']
function getArrayMatches(values, source, target){
console.log("getArrayMatches");
var tempArray = [];
$.each(values, function(index, value) {
var valueindex = source.indexOf(value)
if(valueindex > -1){
var matchtarget = target[valueindex];
if(matchtarget){
tempArray.push(matchtarget);
}
}
});
return tempArray;
}
//Add "more" label to bottom of dialog if dialog content is scrollable
function addDialogMoreInfoLabel(dialogRef){
console.log("addDialogMoreInfoLabel");
$('.more-info-note').remove();
var showMoreLabel = '\
'
});
},
onFocus: function(){
$("#hopotiSearch-selectized").typed({
strings: ['Search centres by name...', 'Search centres by location...', 'Search centres by name...', 'Search centres by address...'],
attr: 'placeholder',
typeSpeed: 2,
startDelay: 300,
backDelay: 3000,
loop: true,
cursorChar: '|',
showCursor: false,
});
}
});
}
function ImagetoPrint(source, type){
//
//
//
//
//
//
//
//
//
var content = "";
if(type == "pdf"){
content = "";
}
return "function step1(){\n" +
"setTimeout('step2()', 10);}\n" +
"function step2(){window.print();window.close()}\n" +
"\n" +
content+"";
}
function printcontent(source, type){ // !print
console.log("printcontent");
console.log(source);
var Pagelink = "about:blank";
var pwa = window.open(Pagelink, "_new");
pwa.document.open();
pwa.document.write(ImagetoPrint(source, type));
pwa.document.close();
}
function stablecardDialog(data){
console.log("stablecardDialog");
console.log(data);
if(!data){
return false;
}
creditTransferred = false;
var bigStablecardHtml = buildDisplayCard(data, "big");
var dialogTitle = ' Stablecard Information';
var cardHelpString = 'With the card, you can book suitable events and services from the company's calendar. Please contact [stablename] if you have any questions about the card or the event eligibility.';
var nameLabel = 'Stablecard';
var transferLabel = 'Transfer credits';
var noTrasfersLabel = 'Credit cannot be transferred';
if(data.TypeId == idGiftcards){ // giftcard labels
transferLabel = 'Transfer card';
noTrasfersLabel = 'Card cannot be transferred';
}
var stablecardActionButtons = [{
label: ' '+data.StableName,
cssClass: 'btn-default btn-sm pull-left btn-stable-link',
autospin: false,
action: function(dialogRef){
window.location.href = 'https://hopoti.com/stable/'+data.StableLinkName;
}
},{
id: 'btn-close',
label: 'Close',
cssClass: 'btn-default btn-sm',
autospin: false,
action: function(dialogRef){
dialogRef.close();
}
}];
var transferButton = {
label: ' '+transferLabel,
cssClass: 'btn-default btn-sm pull-left btn-transfer-credits',
autospin: false,
action: function(dialogRef){
dialogRef.getModalDialog().find('.btn-transfer-credits, .btn-stable-link, .btn-book-link').remove();
dialogRef.getModalDialog().find('.btn-accept-transfer').removeClass("hidden");
moveStablecardCredit(data, dialogRef);
}
};
var noTransfersButton = {
label: ' '+noTrasfersLabel,
cssClass: 'btn-default btn-sm pull-left grayed-out',
autospin: false,
action: function(dialogRef){
if(data.TypeId == idGiftcards){ // giftcard labels
noMoveReasonDialog("card-no-transfers");
} else {
noMoveReasonDialog("credit-no-transfers");
}
}
};
var acceptTransferButton = {
label: ' Accept transfer',
cssClass: 'btn-success btn-sm pull-left hidden btn-accept-transfer',
autospin: false,
action: function(dialogRef){
submitMoveStablecardCredit(data, dialogRef)
}
};
var walletTags;
if(data.WalletTags == null){
walletTags = "2";
} else {
walletTags = "2,"+data.WalletTags;
}
var stablecardValidDateDb = moment(data.ValidDate, "YYYY-MM-DD HH:mm:ss").toISOString();
var bookButton = {
label: ' Show valid lessons',
cssClass: 'btn-default btn-sm pull-left btn-book-link',
autospin: false,
action: function(dialogRef){
window.location.href = 'https://hopoti.com/stable/'+data.StableLinkName+'/booking?free=1&part=1&sc='+data.UserWalletId+'&tags='+walletTags+'&valid='+stablecardValidDateDb+'&cal=all';
}
};
var validUntil = moment(data.ValidDate, "YYYY-MM-DD HH:mm:ss").format('DD/MM/YYYY');
var validString = 'Valid until [x]'.replace('[x]', validUntil);
var validRow = '\
\
\
'+validString+'
\
';
var giftcardValue = "";
if(data.TypeId == idMemberships){
dialogTitle = ' Membership information';
cardHelpString = 'From the membership description you can find more information about the membership's content and benefits. Please contact [stablename] if you have any questions about membership.';
nameLabel = 'Membership name';
} else if(data.TypeId == idGiftcards){ // giftcard
dialogTitle = ' Redeeming a gift card';
cardHelpString = 'From the gift card description you can find more information about the gift card's content and redeem instructions. Please contact [stablename] if you have any questions about gift card.';
nameLabel = 'Gift card name';
giftcardValue = '\
';
function keypress(event){
if(event.originalEvent.keyCode == 80){
$(document).off('keydown', keypress);
$(document).find('.pro-selector').slideDown(300);
promode = 1;
}
}
var promodevalid = 1;
BootstrapDialog.show({
type: BootstrapDialog.TYPE_PRIMARY,
cssClass: 'dialog-select-icon',
title: 'Select icon',
message: iconselectorContent,
onshow: function(dialog) {
dialog.getModalFooter().hide();
},
onshown: function(dialog) {
var target = dialog.getModal();
target.on('click', '.btn-icon', function(e) {
selectedIcon = $(this).data("iconname");
$('.btn-icon.btn-primary').removeClass("btn-primary").addClass("btn-default");
if(promode){
$(this).addClass("btn-primary");
target.find('input[name="icon"]').val(selectedIcon);
target.find('input[name="icon"]').removeClass("bg-danger");
var iconHtml = getIcon(selectedIcon);
target.find('.input-icon').html(iconHtml);
promodevalid = 1;
} else {
dialog.close();
}
});
target.on('click', '.nav-tabs a', function(e) { // navigate
e.preventDefault();
var icongroup = $(this).data("icongroup");
target.find('.btn-icon').addClass("hidden");
target.find('.btn-icon[data-icongroup="'+icongroup+'"]').removeClass("hidden");
target.find('.nav-tabs li').removeClass("active");
$(this).parent().addClass("active");
});
target.on('change keyup blur', 'input[name="icon"]', function(e){ // change pro field
var iconvalue = $(this).val();
var strippedvalue = iconvalue.match(/(?:"[^"]*"|^[^"]*$)/);
if(strippedvalue){
iconvalue = strippedvalue[0].replace(/"/g, "");
$(this).val(iconvalue);
}
var iconHtml = getIcon(iconvalue);
if(iconHtml){
$('.btn-icon.btn-primary').removeClass("btn-primary").addClass("btn-default");
}
target.find('.input-icon').html(iconHtml);
var newiconwidth = target.find('.input-icon span').width();
if(newiconwidth){
target.find('input[name="icon"]').removeClass("bg-danger");
promodevalid = 1;
selectedIcon = iconvalue;
} else {
target.find('input[name="icon"]').addClass("bg-danger");
promodevalid = 0;
}
});
if(!promode && allowuserpro){
$(document).on('keydown', keypress);
}
},
onhide: function(dialog) {
var target = dialog.getModal();
$(document).off('keydown', keypress);
var buttonTarget;
console.log("promode: "+promode+" | promodevalid: "+promodevalid);
if(!promode || promodevalid){ // update values on pro mode only if "valid"
if(buttonelement){
buttonTarget = buttonelement.closest('.icon-selector-buttons');
} else {
buttonTarget = $(document).find('.icon-selector-buttons');
}
buttonTarget.empty();
buttonTarget.append(getIconSelectorButtons(selectedIcon, fieldname, recommendedid));
$(document).find('.'+fieldname).val(selectedIcon).change();
}
}
});
}
function testSubmitQuery(query, returnmissingvalues){
test = true;
var missingvaluefields = [];
$.each(query, function(key, value) {
console.log("key: "+key+" | value: "+value);
if(!value){
test = false;
if(returnmissingvalues){
missingvaluefields.push(key);
}
}
});
if(returnmissingvalues){
return missingvaluefields;
} else {
if (test){
return true;
} else{
return false;
}
}
}
function forceSameContainerHeights(elements){
var maxheight = 0;
$(elements).each(function(index, item){
console.log($(this).outerHeight());
if($(this).outerHeight() > maxheight){
maxheight = $(this).outerHeight();
}
});
if(maxheight){
maxheight = Math.ceil(maxheight);
$(elements).css("height", maxheight+'px');
}
}
function forceSameContentHeights(inputelements, heightelements){
var maxheight = 0;
$(inputelements).each(function(index, item){
var thisItemHeight = 0;
$(item).children().each(function(){
thisItemHeight += $(this).outerHeight(true);
});
if(thisItemHeight > maxheight){
maxheight = thisItemHeight;
}
});
if(maxheight && heightelements){
maxheight = Math.ceil(maxheight);
$(heightelements).css("min-height", maxheight+'px');
}
}
function addTooltip(target, tooltip){
target.attr('data-toggle', 'tooltip');
target.attr('data-trigger', 'hover focus');
target.attr('data-html', 'true');
target.attr('data-original-title', tooltip);
target.tooltip();
}
function removeTooltip(target){
target.tooltip('destroy');
target.removeAttr("data-toggle").removeAttr("data-trigger").removeAttr("data-html").removeAttr("data-original-title");
}
function openImageDialog(imageurl){
BootstrapDialog.show({
type: BootstrapDialog.TYPE_DEFAULT,
size: BootstrapDialog.SIZE_WIDE,
cssClass: 'image-display-dialog',
title:'',
message: ''
});
}
var postId;
var postDatatypeid;
var postAction;
function getSinglePostContent(id, datatypeid, action, url, dialog){
console.log("getSinglePostContent | id: "+id+" | datatypeid: "+datatypeid+" | action: "+action+" | url: "+url);
if(singlePostDial){
return false;
}
postId = id;
postDatatypeid = datatypeid;
postAction = action;
if(url){
changePostUrl(url, action);
}
var query = {};
query.objectid = id;
query.type = datatypeid;
query.action = action;
$.ajax({
url: '/getSinglePostContent',
type: 'POST',
data: query,
error: function(err) {
commonHelpDialog('Action failed','Please check your Internet connection and try again in a moment. If the problem persists, contact our customer service.');
},
success: function(data) {
console.log("singlepost data");
console.log(data);
if(dialog){ // open in dialog
if(data.length && data[0].SportType){ // load map data
var actionData = {};
actionData.action = "singlepost-dialog";
actionData.data = data[0];
actionData.query = query;
loadExerciseData(data[0].DataNumber, actionData);
} else if(data.length){
singlePostDialog(data[0], query);
} else {
commonHelpDialog('Action failed','Please check your Internet connection and try again in a moment. If the problem persists, contact our customer service.');
}
} else { // inpage
if(data.length && data[0].SportType){ // load map data
var actionData = {};
actionData.action = "singlepost-inpage";
actionData.data = data[0];
actionData.query = query;
loadExerciseData(data[0].DataNumber, actionData);
} else if(data.length){
singlePostInpage(data[0], query);
} else {
commonHelpDialog('Action failed','Please check your Internet connection and try again in a moment. If the problem persists, contact our customer service.');
}
}
}
});
}
var singlePostDial;
function singlePostDialog(data, query){ // Display post in dialog
console.log("singlePostDialog");
console.log(data);
console.log(query);
if(singlePostDial){
return false;
}
var datatypeid = data.DataTypeId;
var postid = data.CommentId;
if(data.DataTypeId == 1 || data.DataTypeId == 7){ // user diary
postid = data.DataNumber;
}
console.log("datatypeid: "+datatypeid+" | postid: "+postid);
var dialogButtons = [];
var settings = {};
settings.singlepostdialog = true;
var content = infinitePostConstruct(data, settings);
// console.log("infinite content");
// console.log(content);
var dialogTitle = getIcon('fas fa-pencil-alt')+' messages-riders.post-post';
var reportHidden = "hidden";
if(query.action == "report"){
reportHidden = "";
}
var reportHelp = '\
\
\
We want Hopoti to be a safe and nice site for everyone. However, if you encounter any inappropriate content - please be kind and report the matter to us. We check the content and, if necessary, remove any offensive material.\
');
}
} else { // number invalid
$('input[name="'+submitFieldName+'"]').val("");
var errorCode = iti.getValidationError();
$('input[name="'+submitFieldName+'"]').attr("data-error", errorMap[errorCode]);
//addition for stable settings
cTel.closest('.form-group').find('.help-block').empty().html('
'+errorMap[errorCode]+'
');
cTel.closest('.form-group').addClass("has-error has-danger");
}
} else {
$('input[name="'+submitFieldName+'"]').val("");
$('input[name="'+submitFieldName+'"]').attr("data-error", "Info missing");
}
});
if(initialValue && initialValueIsValid){ // populate field if initial value is valid
initialValue = String(initialValue);
iti.setNumber(initialValue);
} else if(initialValue && !initialValueIsValid){ // add note with old number to update
var noteString = 'Old number is [x] - check the number and country code'.replace("[x]", ''+initialValue+'');
var oldNumberNote = '
'+noteString+'
';
cTel.closest('.form-group').append(oldNumberNote);
}
setTimeout(function(){
cTel.data("init-complete", 1);
}, 500);
});
}
// custom console logging, only for superadmins
function logging(data, color){
}
//takes date and time variables in date or moment format and outputs either fixed string or moment objects
function getCombinedDateTime(date, time, format){
var datemoment;
var timemoment;
if(date instanceof Date){ // is date variable
datemoment = moment(date);
} else if(date.isValid()){ // is moment already
datemoment = date;
} else {
return null;
}
if(time instanceof Date){ // is date variable
timemoment = moment(time);
} else if(time.isValid()){ // is moment already
timemoment = time;
} else {
return null;
}
var dateString = datemoment.format("YYYY-MM-DD");
var timeString = timemoment.format("HH:mm");
var combinedString = dateString + " " + timeString;
if(format == "moment"){
return moment(combinedString, "YYYY-MM-DD HH:mm");
} else {
return combinedString;
}
}
// combine any amount of arrays picking array items every second
// usage: braidArrays(['a','b','c','d'], [1,2,3], [99,98,97,96,95]);
const braidArrays = (...arrays) => {
const braided = [];
for (let i = 0; i < Math.max(...arrays.map(a => a.length)); i++) {
arrays.forEach((array) => {
if (array[i] !== undefined) braided.push(array[i]);
});
}
return braided;
};
function clickAnimateToElement(element){
logging("clickAnimateToElement");
var target = element.data("scroll-target");
var scrollAmount = $(target).offset().top;
var scrollTime = scrollAmount/2;
$([document.documentElement, document.body]).animate({
scrollTop: $(target).offset().top-15
}, scrollTime);
}
var stableAllWaivers = [];
var stableOpenWaiver;
var loadingAllWaivers = false;
var forceRefreshWaivers = false; // dev force waiver reload always without cache
var userWaiverStableIds = [];
var userWaiverStableUsers = [];
function loadStableActiveWaivers(initquery){ // load active waivers for any users (testing for now)
if(!waiversFeature){
return false;
}
console.log("loadStableActiveWaivers");
console.log(initquery);
if(loadingAllWaivers){
return false;
}
loadingAllWaivers = true;
var query = {};
if(initquery){
query = initquery;
}
query.url = '/getStableActiveWaivers';
if(!query.stableids && typeof currentStableId !== "undefined"){
query.stableids = [currentStableId];
} else if(userWaiverStableIds.length){
query.stableids = userWaiverStableIds;
}
if ($('body').hasClass("pageStableFrontpage")) { // reload forms faster on stable front page
query.cachetime = [1, "minutes"];
}
var refreshWaivers = true;
if(store.get('forms-user-'+myUserId) && !forceRefreshWaivers){
refreshWaivers = false;
// check if stable ids found from asked cache
if(query.stableids.every(r => store.get('forms-user-'+myUserId).stableids.includes(r))){
logging("cache contains all stableids");
} else {
logging("cache DOES NOT contain all stableids");
refreshWaivers = true;
}
var formsCacheTime = store.get('forms-user-'+myUserId).timestamp;
var formsCacheMoment = moment.unix(formsCacheTime/1000);
var cacheEndingMoment;
if(query.cachetime){
cacheEndingMoment = formsCacheMoment.add(query.cachetime[0], query.cachetime[1]);
} else {
cacheEndingMoment = formsCacheMoment.add(1, 'hours');
}
if(moment() > cacheEndingMoment){ // check cache time
refreshWaivers = true;
}
if(typeof stableActiveWaiver !== 'undefined' && stableActiveWaiver && stableActiveWaiver.StableWaiverTypeId){
var activeWaiverMatch = $.grep(store.get('forms-user-'+myUserId).forms, function(e){ return e.StableWaiverTypeId == stableActiveWaiver.StableWaiverTypeId });
if(!activeWaiverMatch.length){
refreshWaivers = true;
}
}
if(!refreshWaivers){
logging("use waiver cache", "teal");
stableAllWaivers = store.get('forms-user-'+myUserId).forms;
initStableAllWaivers(stableAllWaivers);
if(query.openwaiver){
waiverSign(query.openwaiver);
}
loadingAllWaivers = false;
return false;
}
}
logging("load waivers", "teal");
stableAllWaivers = [];
let getStableActiveWaivers = getPromise(query.url, query);
getStableActiveWaivers.then(
(values) => {
stableAllWaivers = JSON.parse(values.result);
store.set('forms-user-'+myUserId, {
forms: stableAllWaivers,
stableids: query.stableids,
timestamp: moment().format('x')
});
logging("stableAllWaivers");
logging(stableAllWaivers);
initStableAllWaivers(stableAllWaivers);
if(query.openwaiver){
waiverSign(query.openwaiver);
}
loadingAllWaivers = false;
}
).catch(
(error) => {
console.error(error.message);
loadingAllWaivers = false;
commonHelpDialog('Action failed','Please check your Internet connection and try again in a moment. If the problem persists, contact our customer service.');
}
).finally(() => {
});
}
function removeWaiverCache(){
if(myUserId){
store.remove('forms-user-'+myUserId);
}
}
function reloadWaivers(){
$('[data-append-waiver]').each(function(index, item){
$(item).find('.waiver-append-content').remove();
$(item).removeAttr("data-waiver-added");
});
loadStableActiveWaivers();
}
function initStableActiveWaivers(data){ // init everything waiver related if active waiver found
logging("initStableActiveWaivers");
logging(data);
if(!data.length){
return false; // no active waiver found
}
// logging("userWaiverStableUsers");
// logging(userWaiverStableUsers);
var userCalendarPage = $('body').hasClass('pageUserCalendar-v2');
var userFeedPage = $('body').hasClass('user-wall-feed');
if(userCalendarPage || userFeedPage){ // add extra waiver elements for user pages
if(userWaiverStableUsers.length){
$(userWaiverStableUsers).each(function(index, item){
if(userFeedPage){
var waiverMissingRow = '';
$('body').not('[append-waivers-added]').find('.user-feed-summary').prepend(waiverMissingRow);
} else {
var waiverMissingRow = '
';
$('body').not('[append-waivers-added]').find('.content').prepend(waiverMissingRow);
}
});
$('body').attr('append-waivers-added', 1);
}
}
$(data).each(function(index, waiver){
// logging("single waiver");
// logging(waiver);
if(waiver.UserSignRequire){
$('[data-append-waiver]').each(function(index, item){
//logging("parsing waivers", "red");
var waiverAdded = $(item).attr("data-waiver-added");
var waiverSetup = {};
waiverSetup.action = $(item).attr("data-append-waiver");
waiverSetup.stableid = $(item).attr("data-waiver-stableid");
waiverSetup.eventdate = $(item).attr("data-waiver-event-date");
if($(item).attr("data-userids")){
waiverSetup.users = $(item).attr("data-userids").toString().split(",");
}
if(waiver.StableId == waiverSetup.stableid && !waiverAdded){ // correct stable and note not added
var waiverSignInfo = getWaiverSignHtml(waiverSetup, waiver);
logging("waiverSignInfo", "teal");
logging(waiverSignInfo);
if(waiverSignInfo.html){
$(item).append(waiverSignInfo.html).attr("data-waiver-added", 1);
if(waiverSetup.action == "event-dialog-user-row"){ // remove switch account link if missing waivers to not confuse user
$(document).find('.dialog-user-calendar-event .participant-item .switchaccount-account').remove();
}
}
if(waiverSignInfo.datewarning){
var blinkingWarning = '
An event is about to begin - please sign immediately!
';
$(document).find('[data-append-waiver="user-page"]:not([data-datewarning="1"]) .info-waiver .list-group').prepend(blinkingWarning);
$(document).find('[data-append-waiver="user-page"]').attr("data-datewarning", 1);
}
}
});
}
});
}
function getWaiverSignHtml(setup, waiver){
logging("getWaiverSignHtml");
logging("setup");
logging(setup);
logging("waiver");
logging(waiver);
var usersValid = false;
var waiverUsersValid = [];
var waiverUsersInvalid = [];
var returnData = {};
returnData.datewarning = false;
if(!setup.users && myUserId){
setup.users = [myUserId.toString()];
}
if(!setup.eventdate){
setup.eventdate = moment().format("YYYY-MM-DD HH:mm:ss"); // use current moment if no date
} else {
if(moment() < moment(setup.eventdate) && moment(setup.eventdate) < moment().add(3, "days")){
returnData.datewarning = true;
}
}
//logging(setup);
if(setup.users){ // check each users for valid/invalid waivers
$(setup.users).each(function(index, userid){
var signatureMatch = $.grep(waiver.UserSignatures, function(e){
if(e.ValidToDateTime){
return e.UserId == userid && moment(e.ValidToDateTime) > moment(setup.eventdate);
} else {
return e.UserId == userid;
}
});
if(signatureMatch.length){
waiverUsersValid.push(parseInt(userid));
} else {
waiverUsersInvalid.push(parseInt(userid));
}
});
if(waiverUsersValid.length == setup.users.length){
usersValid = true;
}
}
// logging("usersValid: "+usersValid);
// logging("waiverUsersValid");
// logging(waiverUsersValid);
// logging("waiverUsersInvalid");
// logging(waiverUsersInvalid);
returnData.usersvalid = usersValid;
returnData.waiverusersvalid = waiverUsersValid;
returnData.waiverusersinvalid = waiverUsersInvalid;
var extraStyles = "";
var signWaiverLink = "";
var waiverHelpText = "Participation in the events requires acceptance of the Registration Form.";
var signButton = "";
var waiverUrlLink = 'https://hopoti.com/stable/'+waiver.StableInfo[0].StableLinkName+'/?page=forms&f='+waiver.StableWaiverId;
var waiverStableLink = 'https://hopoti.com/stable/'+waiver.StableInfo[0].StableLinkName;
var childData = [];
//if(waiverUsersInvalid.length && waiverUsersInvalid[0] != myUserId){
var childData = $.grep(userChildrenJSON, function(e){ return waiverUsersInvalid.includes(e.UserId) });
logging("childData", "red");
logging(childData);
if(waiverUsersInvalid.includes(myUserId)){ // current account
signButton = ' Sign Registration Form';
} else if(childData.length){ // other than current account = child
signButton = '\
\
Sign the Registration Form for the child account\
';
}
if(setup.action == "event-calendar-user"){
if(usersValid){ // user calendar event ok
return returnData;
} else { // user calendar event waiver missing
var eventLabel = '
Sign Registration Form!
';
returnData.html = eventLabel;
return returnData;
}
} else if(setup.action == "event-dialog-user"){
if(usersValid){
return returnData;
}
waiverHelpText = "You have booked an event in which participation requires acceptance of a Registration Form. Fill and sign the form before the start of the event or the service provider may deny participation.";
if(waiverUsersInvalid.length > 1){
waiverHelpText += " Signature is missing from [x] accounts.".replace('[x]',''+waiverUsersInvalid.length+'');
}
signWaiverLink = '\
';
} else if(setup.action == "event-dialog-user-row"){
if(usersValid){
var dialogWaiverValidRow = '\
';
returnData.html = signWaiverRow;
return returnData;
}
} else if(setup.action == "event-booking"){
extraStyles = "no-padding";
} else if(setup.action == "booking"){ // no option to sign waiver on payment page
extraStyles = "col-md-6";
signButton = "";
waiverHelpText += " Sign the Registration Form for all participants before the event begins or the service provider may deny participation. You can sign the form immediately after booking or later under your calendar.";
} else if(setup.action == "confirm"){ // booking confirmation page
extraStyles = "col-sm-6";
waiverHelpText = "You have booked an event in which participation requires acceptance of a Registration Form. Fill and sign the form before the start of the event or the service provider may deny participation. You can also find a link to sign the Registration Form in your email or under your calendar bookings.";
} else if(setup.action == "user-page"){ // under user feed and calendar common top alert
if(usersValid){
return returnData;
}
waiverHelpText = "You have booked an event in which participation requires acceptance of a Registration Form. Fill and sign the form before the start of the event or the service provider may deny participation.";
if(waiverUsersInvalid.length > 1){
waiverHelpText += " Signature is missing from [x] accounts.".replace('[x]',''+waiverUsersInvalid.length+'');
}
var signRows = '\
\
Registration Form has been created and published, but the feature has been turned off in the settings. The form is not shown to customers. Activate the feature in settings if you want to enable the feature.\
\
// The feature has been activated in <a href="#stablesettings-waivers">settings</a>, but no Registration Form has been published. Create a Registration Form and set its state <strong>published</strong>.\
//
\
//
\
//
';
// $('#waivers').prepend(noActiveWaiverHtml);
// //}
// }
var waiverSummaryDisplayedTypes = [4]; function initStableWaiverTypeSummaries(data){
logging("initStableWaiverTypeSummaries");
logging(data);
$('.filled-forms-summary').empty().addClass("hidden");
var summaryLink = "";
$(data).each(function(index, waiver){
if(waiver.WaiverFilledCount && waiverSummaryDisplayedTypes.includes(waiver.WaiverTypeId)){
var amountTooltip = 'Total submitted forms [x]'.replace('[x]', waiver.WaiverFilledCount);
summaryLink = '\
\
#'+waiver.StableWaiverId+" "+waiver.WaiverHeader+'\
'+waiver.WaiverFilledCount+'\
'+summaryLink;
}
});
if(summaryLink){
summaryLink = '\
\
Form summaries
\
'+summaryLink+'\
';
$('.filled-forms-summary').append(summaryLink).removeClass("hidden");
}
}
function showStableWaiverSummary(id){
logging("showStableWaiverSummary | id: "+id);
logging(stableSignedWaivers);
var singleWaivertypeData = $.grep(stableSignedWaivers, function(e){ return e.StableWaiverTypeId == id});
var waiverTypeData = $.grep(stableWaiverTypes, function(e){ return e.StableWaiverTypeId == id});
var returnArrayHeaders = [];
var returnArrayContentType = [];
var returnArrayContent = [];
var firstDate;
var lastDate;
var returnAmount = singleWaivertypeData.length;
$(singleWaivertypeData).each(function(index, waiver){
var formContent = JSON.parse(waiver.Content);
// logging("formContent here", "red");
// logging(formContent);
if(!firstDate || moment(waiver.MessageSentDateTime) < moment(firstDate)){
firstDate = waiver.MessageSentDateTime;
}
if(!lastDate || moment(waiver.MessageSentDateTime) > moment(lastDate)){
lastDate = waiver.MessageSentDateTime;
}
$(formContent).each(function(index, row){
if(!returnArrayHeaders[index] && row.label){
returnArrayHeaders.push(row.label);
}
if(!returnArrayContentType[index]){
returnArrayContentType.push(row.type);
}
if(row.userData){
if(!returnArrayContent[index]){
returnArrayContent[index] = [row.userData];
} else {
returnArrayContent[index].push(row.userData);
}
}
});
});
if(returnArrayHeaders){
var summaryObject = {};
summaryObject.header = returnArrayHeaders;
summaryObject.contenttype = returnArrayContentType;
summaryObject.content = returnArrayContent;
summaryObject.amount = returnAmount;
summaryObject.firstdate = firstDate;
summaryObject.lastdate = lastDate;
summaryObject.waivertypedata = waiverTypeData[0];
stableWaiverSummaryDialog(summaryObject);
}
}
function stableWaiverSummaryDialog(data){
logging("stableWaiverSummaryDialog");
logging(data);
var waiverSummaryContent = "";
var filledDates = moment(data.firstdate).format('DD/MM/YYYY')+ ' - '+moment(data.lastdate).format('DD/MM/YYYY')
var waiverHelp = 'The form has been submitted a total of [x] times between [y].'.replace("[x]", ''+data.amount+'').replace("[y]", ''+filledDates+'');
waiverHelp = '
'+waiverHelp+'
';
$(data.header).each(function(index, item){
var type = data.contenttype[index];
logging(type);
var values = data.content[index];
logging(values);
var itemHeader = '';
if(type == "header"){
itemHeader = '
'+item+'
';
} else if(type == "paragraph"){
itemHeader = '
'+item+'
';
}
var singleContent = "";
if(values){
if(type == "ratingstar" || type == "ratingemoji"){
singleContent += '
';
}
}
if(type == "ratingstar" || type == "ratingemoji" || type == "textarea"){
waiverSummaryContent += '\
\
'+itemHeader+'
\
\
'+singleContent+'\
\
';
} else {
waiverSummaryContent += '\
\
'+itemHeader+'\
'+singleContent+'\
';
}
});
var waiverSummaryDial = BootstrapDialog.show({
type: BootstrapDialog.TYPE_PRIMARY,
size: BootstrapDialog.SIZE_WIDE,
cssClass: 'dialog-waiver-summary',
title: "Form summaries",
message: waiverHelp+waiverSummaryContent,
closable: true,
onshown: function(dialogRef){
var graphElements = dialogRef.getModalDialog().find('.graph');
$(graphElements).each(function(index, graph){
var graphId = $(this).attr('id');
var graphIndex = $(this).data('index');
var graphValues = data.content[graphIndex];
getRatingGraph('#'+graphId, graphValues);
});
}
});
}
function getRatingGraph(elementid, ratingArray){
logging("getRatingGraph");
// logging(elementid);
//logging(ratingArray);
var values1 = ratingArray.filter(x => x == 1).length;
var values2 = ratingArray.filter(x => x == 2).length;
var values3 = ratingArray.filter(x => x == 3).length;
var values4 = ratingArray.filter(x => x == 4).length;
var values5 = ratingArray.filter(x => x == 5).length;
var totalArray = [
values1,
values2,
values3,
values4,
values5,
];
var biggestValue = Math.max.apply(Math, totalArray);
totalArray = ["Stats"].concat(totalArray);
var yTickList = [];
for (var i = 1; i <= biggestValue; i++) {
yTickList.push(i);
}
var sRatings = c3.generate({
bindto: elementid,
data: {
columns: [totalArray],
type : 'bar'
},
bar: {
width: {
ratio: .80
}
},
axis: {
x: {
type: 'category',
categories: ["1","2","3","4","5"]
},
y: {
tick: {values: yTickList}
}
},
legend: {
show: false
}
});
}
var waiverEditDial;
var waiverChanges = false;
function waiverEdit(id, copydata){
logging("waiverEdit: "+id);
logging("copydata");
logging(copydata);
if(waiverEditDial){
return false;
}
var disableEditing = false;
var waiverdata;
var waiverEditTitle = 'Create new form';
var waiverFilledHelp = "";
waiverChanges = false;
var panelSelection = "";
var typeSelection = "hidden"
if(copydata){
waiverdata = copydata;
panelSelection = "hidden";
typeSelection = ""
} else if(id){
waiverdata = $.grep(stableWaiverTypes, function(e){ return e.StableWaiverId === id });
if(waiverdata.length){
waiverdata = waiverdata[0];
} else {
commonHelpDialog('Action failed','Please check your Internet connection and try again in a moment. If the problem persists, contact our customer service.');
return false;
}
waiverEditTitle = 'Edit form';
if(waiverdata.WaiverFilledCount){
disableEditing = true;
var helpString = 'The form has been submitted [x] times. After customers have submitted the form, its content can no longer be edited. You can make a copy of the form to which you can make changes.'.replace('[x]', ''+waiverdata.WaiverFilledCount+'');
waiverFilledHelp = '\
';
// var attachmentArea = $(document).find("#"+fieldData.name);
// attachmentArea.append(attachmentElements);
// }
// };
// return returnObject;
// }
function getAttachmentElement(fieldData, extraclass){
logging("getAttachmentElement");
logging("fieldData");
logging(fieldData);
var requiredHtml = "";
if(fieldData.required){
requiredHtml = ' data-attachment-required="1"';
}
var returnObject = {
field: '
',
onRender: function() {
var attachmentElements = '\
\
\
\
\
Drop files here or click to upload
\
\
\
';
var attachmentArea = $(document).find("#"+fieldData.name);
attachmentArea.append(attachmentElements);
}
};
return returnObject;
}
function getAttachmentReadyElement(fieldData){
logging("getAttachmentReadyElement");
logging("fieldData");
logging(fieldData);
var returnObject = {
field: '
',
onRender: function() {
var attachmentElements = '\
\
\
\
Attachment loading missing!\
\
';
var attachmentArea = $(document).find("#"+fieldData.name);
attachmentArea.append(attachmentElements);
}
};
return returnObject;
}
function getStarRatingElement(fieldData){//TODO Form builder star rating
var returnObject = {
field: '
',
onRender: function() {
// logging("STAR RATING ELEMENTS");
// logging(fieldData);
var ratingType = "star-all";
var ratingClass = "rating-stars";
if(fieldData.type == "ratingemoji"){
ratingType = "emoji-all";
ratingClass = "rating-emojis";
}
var requiredHtml = "";
if(fieldData.required){
requiredHtml = ' required="required"';
}
var ratedInfo = "";
if(fieldData.userData){ // fill rated values
ratedInfo = 'data-rated="'+fieldData.userData+'" data-color="'+fieldData.userData+'"';
}
var starElements = '\
\
\
\
\
'+buildRatingStars(null, ratingType)+'\
\
\
\
\
';
var attachmentArea = $(document).find("."+fieldData.name);
attachmentArea.append(starElements);
}
};
return returnObject;
}
function getUserInfoElement(fieldData, data){//TODO Form builder user basic info
logging("getUserInfoElement");
// logging("fieldData");
// logging(fieldData);
// logging("data");
// logging(data);
var userInfoHtml = '\
\
\
\
The information saved in the user's profile at the time of submit is automatically added to this section\
\
';
if(fieldData && fieldData.userData){ // form saved user data
userInfoHtml = getUserInfoData(fieldData.userData, true);
if(userInfoHtml){
userInfoHtml = '\
\
\
\
\
'+userInfoHtml+'\
\
These are the information stored in the user's settings at the time the form is submitted.\
\
\
\
\
';
}
} else if(data && data.UserFeatures){ // user settings data
userInfoHtml = getUserInfoData(data.UserFeatures[0]);
if(userInfoHtml){
userInfoHtml = '\
\
\
\
\
'+userInfoHtml+'\
\
This is information stored in your settings. Carefully check the accuracy of the information. If necessary, edit the information in your settings.\
Account settings\
\
\
\
\
\
';
}
}
var returnObject = {
field: '
',
onRender: function() {
logging("USER INFO ELEMENTS");
logging(fieldData);
var infoElements = '\
\
'+userInfoHtml+'\
';
var attachmentArea = $(document).find("."+fieldData.name);
attachmentArea.append(infoElements);
$('[data-toggle="tooltip"]').tooltip();
}
};
return returnObject;
}
function getUserInfoData(data, userawdata){ // parse user info data for forms
logging("getUserInfoData");
logging(data);
if(!myUserId){
return '';
}
// values which will be used
var acceptedValues = ['UserName','InsertDateTime','Phone','Birth','Weight','Height','SkillLevel','Note','ICEFirstName','ICELastName','ICENumber','UserAssociations'];
var acceptedValueLabels = ['Login name','Registration date','Phone number','Date of birth','Weight','Height','Skill Level','Rider notes for stable or service provider','ICE First name','ICE Last name','ICE Phone','Club membership'];
var userInfo = "";
$(acceptedValues).each(function(index, value){
logging(value);
if(data[value]){
if(userawdata){
if(value == "SkillLevel"){
var infoValue = data[value];
var skillTitle = "";
if(infoValue == 1) {
skillTitle = "Beginner";
} else if(infoValue == 2) {
skillTitle = "Basic skills";
} else if(infoValue == 3) {
skillTitle = "Advanced";
} else if(infoValue == 4) {
skillTitle = "Experienced";
} else {
skillTitle = "No experience";
}
var skillLabel = '
',
onRender: function() {
console.log("formbuilderReadyLayout");
console.log(fieldData);
logging("signature place svg");
logging(fieldData.userData);
var signatureArea = '\
\
\
';
if(fieldData.userData){
signatureArea = '';
}
var signatureElements = '\
\
'+signatureArea+'\
\
\
\
\
\
';
var signatureArea = $(document).find("#"+fieldData.name);
signatureArea.append(signatureElements);
signatureArea.find("svg").removeAttr("viewBox").removeAttr("width").removeAttr("height");
}
};
},
files: function(fieldData) {
return getAttachmentReadyElement(fieldData);
},
ratingstar: function(fieldData) {
return getStarRatingElement(fieldData);
},
ratingemoji: function(fieldData) {
return getStarRatingElement(fieldData);
},
userinformation: function(fieldData) {
return getUserInfoElement(fieldData);
}
}
var customFormFields = [{
label: 'Signature',
attrs: {
type: 'signature',
subtype: 'p'
},
icon: ''
},{
// label: 'Image attachment',
// type: 'files',
// icon: ''
// },{
label: 'Star rating',
attrs: {
type: 'ratingstar'
},
icon: ''
},{
label: 'Emoji rating',
attrs: {
type: 'ratingemoji'
},
icon: ''
},{
label: 'User information',
attrs: {
type: 'userinformation'
},
icon: ''
}];
var waiverTypeContent = [];
waiverTypeContent[0] ='\
With the forms feature, you can create documents intended for customers to fill out - for example, Registration Forms, waiver documents, contracts or feedback surveys. Read more about the feature.\
';
waiverTypeContent[1] ='\
\
\
\
\
\
\
The form is saved as a draft and cannot be filled out by customers\
\
\
The form is published and it is possible to fill it out\
\
\
\
\
This information is not visible to the customer\
\
\
\
Registration Form is a mandatory form to be signed before participating lessons.
\
Edit the form fields to your liking. Mandatory fields cannot be deleted or reordered. On the right side, you can add fields that you can reorder by dragging with the mouse. With the preview button, you can check how the form looks to customers. You can save the form as a draft, but the feature is activated for customers to use only after the form has been published and the feature is active under business settings. Read more about the feature
\
\
';
waiverTypeContent[2] ='\
\
\
\
\
\
\
The form is saved as a draft and cannot be filled out by customers\
\
\
The form is published and it is possible to fill it out\
\
\
\
\
This information is not visible to the customer\
\
\
\
Other waiver is an optional document that the customer can sign if needed.
\
Edit the form fields of the form to your liking. Mandatory fields cannot be deleted or reordered. On the right side, you can add fields that you can reorder by dragging with the mouse. With the preview button, you can check how the form looks to customers. You can save the form as a draft, but the form can be signed by customers only after the form has been published. Read more about the feature
\
\
';
waiverTypeContent[3] ='\
\
\
\
\
\
\
The form is saved as a draft and cannot be filled out by customers\
\
\
The form is published and it is possible to fill it out\
\
\
\
\
This information is not visible to the customer\
\
\
\
A contract is an optional free-form document that the customer can sign if needed.
\
Edit the form fields of the form to your liking. Mandatory fields cannot be deleted or reordered. On the right side, you can add fields that you can reorder by dragging with the mouse. With the preview button, you can check how the form looks to customers. You can save the form as a draft, but the form can be signed by customers only after the form has been published. Read more about the feature
\
\
';
waiverTypeContent[4] ='\
\
\
\
\
\
\
The form is saved as a draft and cannot be filled out by customers\
\
\
The form is published and it is possible to fill it out\
\
\
\
\
This information is not visible to the customer\
\
\
\
Feedback form is an optional free-form document that the customer can fill out if needed. Add star or emoji type rating fields to the form. You can later see a summary of all submitted forms.
\
Edit the form fields of the form to your liking. On the right side, you can add fields that you can reorder by dragging with the mouse. With the preview button, you can check how the form looks to customers. You can save the form as a draft, but the form is visible for customers only after the form has been published. Read more about the feature
\
\
';
waiverTypeContent[5] ='\
\
\
\
\
\
\
The form is saved as a draft and cannot be filled out by customers\
\
\
The form is published and it is possible to fill it out\
\
\
\
\
This information is not visible to the customer\
\
\
\
The waiting list form can be used to collect, for example, participants for a new season or full lessons.
\
Edit the form fields of the form to your liking. On the right side, you can add fields that you can reorder by dragging with the mouse. With the preview button, you can check how the form looks to customers. You can save the form as a draft, but the form is visible for customers only after the form has been published. Read more about the feature
\
\
';
waiverTypeContent[6] ='\
\
\
\
\
\
\
The form is saved as a draft and cannot be filled out by customers\
\
\
The form is published and it is possible to fill it out\
\
\
\
\
This information is not visible to the customer\
\
\
\
The competition form can be used to collect competition registrations.
\
Edit the form fields of the form to your liking. On the right side, you can add fields that you can reorder by dragging with the mouse. With the preview button, you can check how the form looks to customers. You can save the form as a draft, but the form is visible for customers only after the form has been published. Read more about the feature
\
\
';
waiverTypeContent[7] ='\
\
\
\
\
\
\
The form is saved as a draft and cannot be filled out by customers\
\
\
The form is published and it is possible to fill it out\
\
\
\
\
This information is not visible to the customer\
\
\
\
The "Forms" type form can be used freely for whatever purposes you want.
\
Edit the form fields of the form to your liking. On the right side, you can add fields that you can reorder by dragging with the mouse. With the preview button, you can check how the form looks to customers. You can save the form as a draft, but the form is visible for customers only after the form has been published. Read more about the feature
\
\
';
var defaultFieldsAgreement = [{
type: 'header',
label: 'Form title',
name: 'waiver-header',
className: 'waiver-header-element'
},{
type: 'paragraph',
subtype: 'p',
label: 'Insert legal text here',
className: 'waiver-legal-element'
},{
type: 'checkbox-group',
required: true,
label: 'Electronic signature consent',
className: 'waiver-accept-element',
toggle: false,
inline: false,
access: false,
other: false,
values: [{
label: 'Insert accept text here',
value: 'accept',
selected: false
}]
},{
type: 'signature',
subtype: 'p',
required: true,
label:"Signature",
className: 'waiver-signature-element'
}];
var defaultFieldsWaiver = [{
type: 'header',
label: 'Registration Form header',
name: 'waiver-header',
className: 'waiver-header-element'
},{
type: 'paragraph',
subtype: 'p',
label: 'Insert legal text here',
className: 'waiver-legal-element'
},{
type: 'checkbox-group',
required: true,
label: 'Electronic signature consent',
className: 'waiver-accept-element',
toggle: false,
inline: false,
access: false,
other: false,
values: [{
label: 'Insert accept text here',
value: 'accept',
selected: false
}]
},{
type: 'signature',
subtype: 'p',
required: true,
label:"Signature",
className: 'waiver-signature-element'
}];
var defaultFieldsFeedback = [{
type: 'header',
label: 'Feedback form title',
name: 'waiver-header',
className: 'waiver-header-element'
},{
type: 'ratingstar',
label: 'How likely would you recommend us?',
className: 'nps-recommend',
required: true
},{
type: 'ratingstar',
label: 'How do you rate the teaching?',
className: 'nps-teaching',
required: true
},{
type: 'ratingstar',
label: 'How do you rate horses?',
className: 'nps-horses',
required: true
},{
type: 'ratingstar',
label: 'How do you rate the facilities?',
className: 'nps-spaces',
required: true
},{
type: 'textarea',
label: 'Open feedback',
className: 'form-control'
},{
type: 'paragraph',
subtype: 'p',
label: 'The feedback you send can only be seen by the staff of the business.'
}];
var defaultFieldsForm = [{
type: 'header',
label: 'Form title',
name: 'waiver-header',
className: 'waiver-header-element'
}];
var formBuilder;
function waiverInitNewWaiver(dialog, presetdata, waivertype){
logging("waiverInitNewWaiver | waivertype: "+waivertype);
logging("presetdata");
logging(presetdata);
var waiverTypeElement = dialog.getModalDialog().find('.waiver-type-content');
var waiverElement = dialog.getModalDialog().find('#waiver-container');
var initReady = false;
var presetFields = null;
formBuilder = null;
var disableEditing = false;
var editingCurrentlyActive = false;
waiverElement.addClass("disabled");
waiverElement.empty();
dialog.getModalFooter().find('.btn-waiver-save, .btn-waiver-preview, .btn-waiver-clear').addClass("hidden");
if(presetdata){ //normal editing
if(presetdata.WaiverTypeId){
waivertype = presetdata.WaiverTypeId;
}
try {
presetFields = JSON.parse(presetdata.Content);
} catch (e) { // json not valid
commonHelpDialog('Action failed','File is corrupted (JSON not valid)', 'DANGER');
dialog.close();
return false;
}
if(presetdata.WaiverFilledCount){ // if waiver filled - disable editing
disableEditing = true;
}
if(presetdata.StableWaiverTypeId == stableActiveWaiver.StableWaiverTypeId){
editingCurrentlyActive = true;
}
} else {
if(waivertype == 1 || waivertype == 2){
presetFields = defaultFieldsWaiver;
} else if(waivertype == 3){
presetFields = defaultFieldsAgreement;
} else if(waivertype == 4){
presetFields = defaultFieldsFeedback;
} else {
presetFields = defaultFieldsForm;
}
}
waiverTypeElement.empty();
dialog.getModalDialog().find('.alert-existing-waiver').addClass("hidden");
if(waivertype){
waiverTypeElement.append(waiverTypeContent[waivertype]);
if(waivertype == 1 && !editingCurrentlyActive){
dialog.getModalDialog().find('.alert-existing-waiver').removeClass("hidden");
}
} else {
waiverTypeElement.append(waiverTypeContent[0]);
return false;
}
var mobileHelpContent = '
To ease the editing, we recommend making changes on a larger screen.
';
waiverTypeElement.append(mobileHelpContent)
var templates = formbuilderPreviewLayout;
var fields = customFormFields;
var formBuilderOptions = {
disableFields: [
'autocomplete',
'file',
'date',
'button',
'hidden'
],
showActionButtons: false,
disabledAttrs: ["access", "className", "inline", "name", "subtype"],
controlOrder: ["header", "paragraph"],
onAddField: function(fieldId, data) {
logging(fieldId);
logging(data);
if(data.type == "file"){
}
if(initReady){
waiverChanges = true;
dialog.setClosable(false);
}
waiverCheckFormOrder(dialog);
},
typeUserEvents: {
// files: {
// onadd: function(fld) {
// logging("add file field")
// logging(fld);
// // var $patternField = $(".fld-pattern", fld);
// // var $patternWrap = $patternField.parents(".pattern-wrap:eq(0)");
// // $patternField.prop("disabled", true);
// // $patternWrap.hide();
// // fld.querySelector(".fld-subtype").onchange = function(e) {
// // var toggle = e.target.value === "password";
// // $patternField.prop("disabled", !toggle);
// // $patternWrap.toggle(toggle);
// // };
// }
// }
},
fields,
templates
};
if(presetFields){ // populate preset content
formBuilderOptions.formData = presetFields;
formBuilderOptions.dataType = 'json';
}
// fill if existing waiver content
if(presetdata){
if(presetdata.WaiverComment){
dialog.getModalDialog().find('textarea[name="waivercomment"]').val(presetdata.WaiverComment);
}
if(presetdata.StatusId == 2 || presetdata.StatusId == 4){
dialog.getModalDialog().find('#waiverstatus').attr("checked", "checked");
}
}
formBuilder = waiverElement.formBuilder(formBuilderOptions);
dialog.getModalDialog().find('#waiverstatus').bootstrapToggle();
//logging("disable waiver attachments temporarily", "teal");
// setTimeout(() => {
// dialog.getModalDialog().find('.frmb-control .input-control[data-type="files"]').addClass("disabled overline");
// dialog.getModalDialog().find('.frmb-control .input-control[data-type="files"]').remove();
// }, 1000);
autosize(dialog.getModalDialog().find('textarea[name="waivercomment"]'));
if(!disableEditing){
waiverElement.removeClass("disabled");
}
waiverElement.removeClass("hidden");
setTimeout(() => {
if(presetdata && presetdata.copy){
dialog.getModalDialog().find('.select-waivertype-parent .form-group').removeClass("disabled");
}
initReady = true;
}, 300);
}
function waiverSave(data, settings, originaldata, dialog){ //TODO Save created waiver
logging("waiverSave");
logging("form data");
logging(data);
logging("settings");
logging(settings);
logging("originaldata");
logging(originaldata);
var edit = false;
if(originaldata && !originaldata.copy){
edit = true;
}
if(data.length > 65535){ // prevent too long data for backend
commonHelpDialog('Action failed','The content you entered is too long ('+data.length+'/65535)');
dialog.getModalDialog().find('.modal-body, .modal-footer').removeClass("disabled");
return false;
}
var waiverDataContent = JSON.parse(data);
// logging("waiverDataContent");
// logging(waiverDataContent);
$(waiverDataContent).each(function(index, row){ // check radio button and checkbox row options
if(row.type == "radio-group" || row.type == "checkbox-group" || row.type == "select"){
$(row.values).each(function(index, value){
logging("value");
logging(value);
value.value = "option-"+(index+1);
});
}
});
// logging("waiver checked data before save", "teal");
// logging(waiverDataContent);
var waiverHeader = $.grep(waiverDataContent, function(e){ return e.className ==="waiver-header-element" });
var saveData = JSON.stringify(waiverDataContent);
var query = {};
query.stableid = currentStableId;
query.status = 0; // published/temp
query.content = saveData;
if(waiverHeader.length){
query.header = waiverHeader[0].label;
}
query.comment = "";
query.definition = "definition";
query.from = undefined;
query.to = undefined;
query.waivertypeid = 1; // waiver type
if(settings){ // override & add default query if settings found
query = Object.assign(query, settings);
}
var formDataChanged = false;
if(originaldata){ // editing
query.stablewaivertypeid = originaldata.StableWaiverTypeId;
if(query.publish == 1){
if(query.waivertypeid == 1){
query.status = 2;
} else {
query.status = 4;
}
} else {
query.status = 1;
}
} else {
if(query.publish == 1){
if(query.waivertypeid == 1){
query.status = 2;
} else {
query.status = 4;
}
}
}
var waiverSaveUrl = 'https://hopoti.com/insertWaiverType';
if(edit){
waiverSaveUrl = 'https://hopoti.com/updateWaiverType';
}
$.ajax({
url: waiverSaveUrl,
type: 'POST',
data: query,
error: function(err) {
commonHelpDialog('Action failed','Please check your Internet connection and try again in a moment. If the problem persists, contact our customer service.');
dialog.getModalDialog().find('.modal-body, .modal-footer').addClass("disabled");
loadStableWaiverTypes();
removeWaiverCache();
},
success: function(data) {
dialog.close();
if(query.copy){
loadStableWaiverTypes(data[0].StableWaiverId);
//waiverEdit(data[0].StableWaiverId);
} else {
//waiverEdit();
loadStableWaiverTypes();
}
removeWaiverCache();
}
});
}
var waiverFormTimeout;
function waiverCheckFormOrder(dialog){
console.log("waiverCheckFormOrder");
clearTimeout(waiverFormTimeout);
waiverFormTimeout = setTimeout(function(){
waiverAlterForms(dialog);
var waiverData = formBuilder.actions.getData('js');
if(waiverData){
var waiverDataCheck = rearrangeWaiverData(waiverData);
if(waiverDataCheck.reorder == true){
formBuilder.actions.setData(waiverDataCheck.data);
}
}
var waiverData = formBuilder.actions.getData('js');
validateWaiverData(waiverData);
}, 50);
}
function rearrangeWaiverData(data){
logging("rearrangeWaiverData");
console.log(data);
var finalData = [];
var reorder = true;
var headerindex = data.findIndex(x => x.className ==="waiver-header-element");
//logging("headerindex: "+headerindex);
if(headerindex < 0){
var returnObject = {};
returnObject.reorder = false;
return returnObject;
}
var legalindex = data.findIndex(x => x.className ==="waiver-legal-element");
var acceptindex = data.findIndex(x => x.className ==="waiver-accept-element");
var signatureindex = data.findIndex(x => x.className ==="waiver-signature-element");
var childindex = data.findIndex(x => x.className ==="waiver-child-element");
logging("childindex: "+childindex);
if(headerindex == 0 && legalindex == 1 && acceptindex == data.length-2 && signatureindex == data.length-1){ // do not reorder form if order ok
reorder = false;
} else if(headerindex == 0 && legalindex == -1 && acceptindex == -1 && signatureindex == -1){
reorder = false;
}
var waiverHeader = $.grep(data, function(e){ return e.className ==="waiver-header-element" });
var waiverLegal = $.grep(data, function(e){ return e.className ==="waiver-legal-element" });
var waiverChilds = $.grep(data, function(e){ return e.className ==="waiver-child-element" });
var waiverAccept = $.grep(data, function(e){ return e.className ==="waiver-accept-element" });
var waiverSignature = $.grep(data, function(e){ return e.className ==="waiver-signature-element" });
if(childindex > -1 && childindex != data.length-3){
reorder = true;
}
//logging(waiverChilds);
if(waiverHeader.length){
finalData.push(waiverHeader[0]);
}
if(waiverLegal.length){
finalData.push(waiverLegal[0]);
}
$(data).each(function(index, row){
if(row.className == "waiver-header-element" || row.className == "waiver-legal-element" || row.className == "waiver-accept-element" || row.className == "waiver-signature-element" || row.className ==="waiver-child-element"){
return true;
} else {
finalData.push(row);
}
});
if(waiverChilds.length){
finalData.push(waiverChilds[0]);
}
if(waiverAccept.length){
finalData.push(waiverAccept[0]);
}
if(waiverSignature.length){
finalData.push(waiverSignature[0]);
}
var returnObject = {};
returnObject.data = finalData;
returnObject.reorder = reorder;
return returnObject;
}
function waiverAlterForms(dialog){ // remove unwanted elements after render
logging("waiverAlterForms");
var currentDial = dialog.getModalDialog();
var headerElement = currentDial.find('.waiver-header-element').closest(".form-field");
headerElement.find('a[type="remove"], a[type="copy"]').remove();
var legalElement = currentDial.find('.waiver-legal-element').closest(".form-field");
legalElement.find('a[type="remove"], a[type="copy"]').remove();
var acceptElement = currentDial.find('.waiver-accept-element').closest(".form-field");
acceptElement.find('a[type="remove"], a[type="copy"], .toggle-wrap, .other-wrap, .field-options .option-actions').remove();
acceptElement.find('.required-wrap .fld-required').addClass("disabled");
acceptElement.find('.field-options .option-selected').addClass("hidden");
acceptElement.find('.field-options .option-value').addClass("hidden");
acceptElement.find('.field-options .option-label').css("width", "100%");
var signatureElement = currentDial.find('.waiver-signature-element').closest(".form-field");
signatureElement.find('a[type="remove"], a[type="copy"]').remove();
signatureElement.find('.required-wrap .fld-required').addClass("disabled");
signatureElement.find('.placeholder-wrap, .value-wrap').addClass("hidden");
var altSignatureElements = currentDial.find('.signature-element:not(.waiver-signature-element)');
altSignatureElements.each(function(index, item){
var singleElement = $(item).closest('.form-field');
singleElement.find('.placeholder-wrap, .value-wrap').addClass("hidden");
});
var ratingElements = currentDial.find('.ratingstar-field, .ratingemoji-field');
ratingElements.each(function(index, item){
$(item).find('.placeholder-wrap, .value-wrap').addClass("hidden");
});
var userinfoElements = currentDial.find('.userinformation-field');
userinfoElements.each(function(index, item){
$(item).find('.placeholder-wrap, .value-wrap, .required-wrap').addClass("hidden");
});
var attachmentElements = currentDial.find('.files-field');
attachmentElements.each(function(index, item){
$(item).find('.placeholder-wrap, .value-wrap, .required-wrap').addClass("hidden");
});
var optionsElements = currentDial.find('.checkbox-group-field, .radio-group-field, .select-field');
optionsElements.each(function(index, item){
$(item).find('.option-value, .toggle-wrap, .multiple-wrap').addClass("hidden"); // hide option and toggle fields
});
var otherOptions = currentDial.find('input.other-option');
otherOptions.each(function(index, item){
$(item).parent().find("label").not('[data-translated]').prepend("Other");
$(item).parent().find("label").attr("data-translated", 1); //fix for "other" translations
});
}
function waiverSign(waiverId, stableId, action){
logging("waiverSign | waiverId: "+waiverId+" | stableId: "+stableId+" | action:"+action);
if(!stableId){
stableId = currentStableId;
}
if(!action){
action = "user-sign";
}
var query = {};
query.stableids = [stableId];
query.waiverid = waiverId;
let getStableActiveWaivers = getPromise('/getStableActiveWaivers', query);
getStableActiveWaivers.then(
(values) => {
var waiverdata = JSON.parse(values.result);
if(waiverdata.length){
stableOpenWaiver = waiverId;
if($('body').hasClass("pageStableFrontpage")){
changeUrl();
}
waiverViewWaiver(waiverdata[0], action);
} else {
commonHelpDialog('Action failed','Please check your Internet connection and try again in a moment. If the problem persists, contact our customer service.');
}
}
).catch(
(error) => {
commonHelpDialog('Action failed','Please check your Internet connection and try again in a moment. If the problem persists, contact our customer service.');
}
).finally(() => {
});
}
var waiverViewDial;
var waiverViewDialChanges = false;
function waiverViewWaiver(data, action){
logging("waiverViewWaiver | action: "+action);
// actions: stable-preview, user-sign, user-view, stable-view
logging("data");
logging(data);
if(waiverViewDial){
return false;
}
if(!myUserId){
action = "view";
}
var waiverdata;
var waivermeta;
var businessdata;
var waiverAlreadyFilledHtml = "";
var waiverFillerInfoHtml = "";
var fillerUserHtml = "";
var signDateString = "";
var validToString = "";
var userButton = "";
var waiverMatchData;
var signedIds = [];
var switchAccount = false;
if(store.get('switch-account') && store.get('switch-account').action == "sign-waiver"){
switchAccount = true;
}
if(data.UserSignatures && data.UserSignatures.length){
var waiverMatchData;
var waiverMatch = $.grep(data.UserSignatures, function(e){ return e.UserId == myUserId && !e.UserSignedWaiverExpired });
if(waiverMatch.length){
waiverMatchData = waiverMatch[waiverMatch.length-1];
}
$(data.UserSignatures).each(function(index, item){
if(!signedIds.includes(item.UserId && !item.UserSignedWaiverExpired)){
signedIds.push(item.UserId);
}
});
}
// logging("waiverMatchData");
// logging(waiverMatchData);
// logging("signedIds");
// logging(signedIds);
var changeAccountButton = "";
if(action == "user-sign" && data.StableWaiverId){
if(parentMode == "parent" || parentMode == "child" && userParentId){
var urlLink = 'https://hopoti.com/stable/'+data.StableInfo[0].StableLinkName+'/?page=forms&f='+data.StableWaiverId;
changeAccountButton = '';
}
}
if(action == "stable-view"){
userButton = clientModalButtonHtml(data);
}
if(data && data.ValidToDateTime){
var validTo = moment(data.ValidToDateTime).format('DD/MM/YYYY');
validToString = 'Valid until [x]'.replace('[x]',validTo)
}
if(action == "view-active" && stableInfo){
waiverdata = data;
businessdata = stableInfo;
signDateString = moment().format('DD/MM/YYYY');
} else if(action == "stable-preview" && stableInfo){
waiverdata = data;
var arrangedata = rearrangeWaiverData(data);
if(arrangedata.reorder){
waiverdata = arrangedata.data;
}
businessdata = stableInfo;
signDateString = moment().format('DD/MM/YYYY');
} else if(action == "user-view" || action == "stable-view"){
if(data.StableInfo){
businessdata = data.StableInfo[0];
} else {
businessdata = data;
}
signDateString = moment(data.ConfirmedDateTime).format('DD/MM/YYYY HH:mm');
} else if(action == "user-sign" || action == "view"){
if(data.StableInfo){
businessdata = data.StableInfo[0];
} else {
businessdata = stableInfo;
}
signDateString = moment().format('DD/MM/YYYY');
if(waiverMatchData){
var filledDate = moment(waiverMatchData.UserSignedWaiverTime).format('DD/MM/YYYY HH:mm');
var alreadyFilledString = 'You have already filled out this form on [x] - if you want, you can fill it out and submit it again.'.replace('[x]', ''+filledDate+'');
if(!switchAccount){
// show filled button
alreadyFilledString += 'Show filled form';
}
waiverAlreadyFilledHtml = '
'+alreadyFilledString+'
';
}
}
if(data.Content){
var waivercontent = JSON.parse(data.Content);
waiverdata = $.grep(waivercontent, function(e){ return e.type != "meta"; }); // remove meta from form data
var waivermetamatch = $.grep(waivercontent, function(e){ return e.type == "meta"; }); // only meta
if(waivermetamatch.length){
waivermeta = waivermetamatch[0];
}
}
var waiverFillerString = "";
var nameChangeString = "";
var metaHtml = "";
if(data.UserId){
fillerUserHtml = ''+(userButton || data.FirstName + ' ' + data.LastName)+'';
waiverFillerString = 'The form has been filled out for account [x]'.replace('[x]', fillerUserHtml);
if(waivermeta){
if(data.FirstName != waivermeta.FirstName || data.LastName != waivermeta.LastName){
nameChangeString = '(messages-stables.forms-username-when-filled)'.replace('[x]', ': '+waivermeta.FirstName+' '+waivermeta.LastName+'');
}
}
} else if(typeof myInfoObject != "undefined") {
fillerUserHtml = ''+ownInfoObject.FirstName + ' ' + ownInfoObject.LastName+'';
waiverFillerString = 'The form will be filled out for account [x]'.replace('[x]', fillerUserHtml);
}
if(nameChangeString){
metaHtml += '\