// used with a STRING locationId, returns FALSE or the corresponding location object -- used with an array of strings, returns an array of location objects
var i, locs, loc;
if (typeof (locationId) === 'string') {
var locLower = locationId.toLowerCase();
for (i = 0; i < locationInfo.length; ++i) {
if (locationInfo[i].id === locationId) {
return locationInfo[i];
}
}
} else if (typeof (locationId) === 'object') {
return getLocationsById(locationId);
}
return false;
}
function getLocationsById(locationIds) {
// locationNames can be a string or an array;
// Returns an array of the corresponding locations
var i, loc, locs;
if (typeof (locationIds) === 'undefined') {
return [];
} else if (typeof (locationIds) === 'string') {
loc = getLocationById(locationIds);
if (loc === false) {
return [];
}
return [loc];
} else {
locs = [];
for (i = 0; i < locationIds.length; ++i) {
loc = getLocationById(locationIds[i]);
if (loc !== false) {
locs.push(loc);
}
}
}
return locs;
}
function getLocationByName(locationName) {
// gets a single location by name
var i;
if (typeof (locationName) === 'string') {
var locLower = locationName.toLowerCase();
for (i = 0; i < locationInfo.length; ++i) {
if (locationInfo[i].description.toLowerCase() === locLower) {
return locationInfo[i];
}
if (locationInfo[i].id.toLowerCase() === locLower) {
return locationInfo[i];
}
}
} else if (typeof (locationName) === 'object') {
return getLocationsByName(locationName);
}
return false;
}
function getLocationsByName(locationNames) {
// locationNames can be a string or an array;
// Returns an array of the corresponding locations
var i, loc, locs;
if (typeof (locationNames) === 'undefined') {
return [];
} else if (typeof (locationNames) === 'string') {
loc = getLocationByName(locationNames);
if (loc === false) {
return [];
}
return [loc];
} else {
locs = [];
for (i = 0; i < locationNames.length; ++i) {
loc = getLocationByName(locationNames[i]);
if (loc !== false) {
locs.push(loc);
}
}
}
return locs;
}
function getLocation(locationRef) {
// trys to get location by id, if that fails, then by name
var location;
location = getLocationById(locationRef);
if (location === false) {
location = getLocationByName(locationRef);
}
return location;
}
function getCoords(location) {
// location is the location object
if (typeof (location) !== 'object') {
return false;
}
var coords = location.coords;
if (coords === undefined) {
return false;
}
return coords.split(",");
}
function getMarkerLocation(marker) {
var i;
for (i = 0; i < locationInfo.length; ++i) {
if (locationInfo[i].marker === marker) {
return locationInfo[i];
}
}
return false;
}
function showLocationDetails() {
if ($('#more_location_details').hasClass('bt-active')) {
function increaseEventsPerDay(event) { // TO DO: count multi-day events for each day
var date = formatDate(event.start, 'yyMMdd');
if (eventsPerDay[date] !== undefined) {
eventsPerDay[date] += 1;
} else {
eventsPerDay[date] = 1;
}
// Count event types per day (for use in calendar)
for (var category in event.category) {
if (eventsPerDay[category][date] !== undefined) {
eventsPerDay[category][date] += 1;
} else {
eventsPerDay[category][date] = 1;
}
}
}
function increaseEventsPerLocation(location) {
var locationObj;
locationObj = getLocation(location);
if (locationObj !== false) {
locationObj.numberEvents += 1;
} else {
locationObj = getLocation(location);
}
}
function increaseHiddenEventsPerLocation(location) {
var locationObj;
locationObj = getLocation(location);
if (locationObj !== false) {
locationObj.numberHiddenEvents += 1;
}
}
// functions dealing with events
function shortLocation(locationName, source) { // Returns the short location of an event, if available -- MAY NOT BE NEEDED
// TO DO (if to be employed for many calendars and locations): restrict search to possible locations for a given calendar
var short = locationName;
var fullLocation = locationName.toLowerCase();
for (var i = 0; i < shortLocations.length; i++) {
if (fullLocation.indexOf(shortLocations[i].search) !== -1) {
short = shortLocations[i].short;
break;
}
}
return short;
}
function getLocations(locations) {
// locations can be a string (locationId), or an array of location objects or locationIds
// Returns an array of the locations (can be empty)
var i;
var getLocs = [];
var loc;
var locs;
if (typeof (locations) === 'undefined') {
return [];
} else if (typeof (locations) === 'string') { // Is a location id
locs = [locations];
} else {
locs = locations;
}
for (i = 0; i < locs.length; i++) {
if (isLocationObject(locs[i])) {
getLocs.push(locs[i]);
} else {
loc = getLocation(locs[i]);
if (loc !== false) {
getLocs.push(loc);
}
}
}
return getLocs;
}
function getLocationIds(locations) {
// locations can be a string (locationId), or an array of location objects or locationIds
// Returns an array of the location ids (can be empty)
var i;
var locIds = [];
var locs;
if (typeof (locations) === 'string') { // Is a location id
return [locations];
} else {
locs = locations;
}
for (i = 0; i < locs.length; i++) {
if (isLocationObject(locs[i])) {
locIds.push(locs[i].id);
} else {
locIds.push(locs[i]);
}
}
return locIds;
}
function getLocationByDescription(location, source) { // Returns the location (object) of an event, given a full location description, if possible
var short;
var locationLower = location.toLowerCase();
var i;
var locs;
for (i = 0; i < shortLocations.length; i++) {
if (locationLower.indexOf(shortLocations[i].search) !== -1) {
short = shortLocations[i].description;
break;
}
}
if (source.locationExclusive === true) {
locs = getLocations(source.location);
} else if (source.locationsPossible !== undefined) {
locs = source.locationsPossible;
} else {
locs = locationInfo;
}
for (i = 0; i < locs.length; i++) {
if (short === locs[i].description) {
return locs[i];
}
}
return false;
}
function showDetails(event) {
function urlX(u) {
return u;
}
function idX(id) {
return id;
}
var dayBegin = formatDate(event.start, 'dd');
var dayEnd = formatDate(event.end, 'dd');
var monthBegin = formatDate(event.start, 'MMMM');
var monthEnd = formatDate(event.end, 'MMMM');
var timeBegin = formatDate(event.start, 'H:mm');
var timeEnd = formatDate(event.end, 'H:mm');
var day = dayBegin + ". ";
var time = "";
var gmapIconEventId = 'gmap_' + calendarDivId;
var addEventToCalendarId = 'addevent_' + calendarDivId;
if (monthBegin !== monthEnd)
{
day += monthBegin;
}
if (dayBegin !== dayEnd && dayEnd !== '' && dayEnd !== undefined) // all day events that last only one day have no recorded event end.
{
day += "- " + dayEnd + ". ";
}
if (monthEnd !== '' && monthEnd !== undefined) { // all day events that last only one day have no recorded event end.
day += monthEnd;
}
if (!event.allDay || event.mostDay) {
if (event.autoGenerated === true) {
time += timeBegin + " Uhr"; // No specified end time
} else {
time += timeBegin + " - " + timeEnd + " Uhr";
}
}
var title = html_sanitize(event.title || '', urlX, idX);
var location = html_sanitize(event.location || '', urlX, idX);
var shortLocation = event.shortLocation;
var locationId = event.locationId;
var locationObj = getLocationById(locationId);
var description = html_sanitize(event.description || '', urlX, idX);
var id = event.domId;
if ($("#" + id).hasClass('fc-event-sel')) {
unselectEvents();
return;
// If already selected, then deselect
}
unselectEvents();
$("#" + id).removeClass("fc-event").removeClass("fc-event-loc-sel").addClass("fc-event-sel").css("border", calendarGemeindenOptions.locationSelectedBorder); // Add CSS event selected class to newly selected event, and draw a red border
var html;
html = '<a onclick="$(\'.fc-event-sel\').btOff();">' + calendarGemeindenOptions.locationDetailsCloseGraphic + '</a>';
var editGraphic = calendarGemeindenOptions.locationDetailsEditGraphic;
var calObjs = $(gemeindenFixedDiv).find('.singlecalendar');
var calIds = [];
calObjs.each(function()
{
cal = getCalendarByDomId($(this).attr('id'));
if (cal !== false) {
calIds.push(cal.id);
}
});
var calString = calIds.join(',');
storeCalendarOption('calendarOrder', calString);
}
function getStoredCalendarOrder() {
var calOrderString = getCalendarOption('calendarOrder');
if (calOrderString === undefined) {
return [];
}
return calOrderString.split(',');
}
function getStoredCalendarOptions(cal) {
var calName;
var disp;
var sel;
var selectBox;
var defaultOption;
calName = cal.id;
sel = getCalendarOption(calName + '_selectBox');
disp = getCalendarOption(calName);
if (cal.displayCalendar === false) {
selectBox = false;
} else {
if (sel === 'true') {
//|| (disp === 'true' && googleMapsDialog === true) }) { // if stored as selectable, or if displayed and the map is a dialog (and so not shown at the beginning)
if (disp === "true" && (selectBox === true || (googleMaps === true && googleMapsDialog === false))) { // don't display events from the calendar if the calendar itself is invisible to begin with
cal.display = true;
} else if (disp === "false") {
cal.display = false;
}
storeCalendarOption(calName, cal.display);
}
function getStoredOptions() {
var minutesDiff;
userId = _getCalendarOption('user'); // Always get this
if (userId === undefined) {
initializeUser();
_storeCalendarOption('user', userId); // Always store this
}
if (getCalendarOption('date') !== undefined && storeOptionsLocally === true) {
if (time === event2.time && title === event2.title && description === event2.description) { // Add this event to the particular day, if not already present
if (event2.days.indexOf(days[i]) !== -1) { // This day already present
found = true;
break;
} else {
event2.days.push(days[i]); // Add this day to this type of event
found = true;
break;
}
}
}
if (found === false) {
if (description !== undefined) {
eventList.push({days: [days[i]], time: time, title: title, description: description});
} else {
eventList.push({days: [days[i]], time: time, title: title});
if (locationRef === undefined || location !== false) {
cal.events = createGenerateEvents(cal, location); // A hack to allow us to load locations after calendars; TO DO: rewrite this
}
}
locExtended = cal.locationExtended;
if (locExtended !== undefined) {
coords1 = locExtended[0].split(",");
coords2 = locExtended[1].split(",");
cal.mapBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(coords1[0], coords1[1]),
new google.maps.LatLng(coords2[0], coords2[1])
);
}
locRestricted = cal.locationRestricted;
if (cal.mapBoundsRestricted === undefined) {
if (locRestricted !== undefined) {
coords1 = locRestricted[0].split(",");
coords2 = locRestricted[1].split(",");
cal.mapBoundsRestricted = new google.maps.LatLngBounds(
new google.maps.LatLng(coords1[0], coords1[1]),
new google.maps.LatLng(coords2[0], coords2[1])
);
} else if (location !== false) { // calendar is linked with just one location
coords = getCoords(location);
var boundsSw = new google.maps.LatLng(parseFloat(coords[0]) - 0.05, parseFloat(coords[1]) - 0.05); // A guess at how far away most communities might celebrate from their principal church
var boundsNe = new google.maps.LatLng(parseFloat(coords[0]) + 0.05, parseFloat(coords[1]) + 0.05);
cal.mapBoundsRestricted = new google.maps.LatLngBounds(boundsSw, boundsNe);
cal.locationsPossible = getLocationsInBounds(cal.mapBoundsRestricted); // Need to always update this, in case more locations have been added (TO DO: perhaps add a flag for this)
{8: 'Unbeflecktes Empfängnis', 24: 'Heiliger Abend', 25: 'Weihnachten', 26: 'Stephanitag'}]; // on new year's eve special masses are more usually in the evening.
}
function getFeastDay(date) {
// returns false if not a feast day, true if a feast day without a specific name, or the name of the feast day
var dayofMonth = date.getDate();
var month = date.getMonth();
var year = date.getFullYear();
var yearFeasts = feastdays.moveableFeasts[year];
var moveableFeast = false;
var monthFeasts;
var feastDay;
if (yearFeasts !== undefined) {
monthFeasts = yearFeasts[month];
if (monthFeasts !== undefined) {
if (monthFeasts[dayofMonth] !== undefined) {
moveableFeast = monthFeasts[dayofMonth];
}
}
}
if (moveableFeast !== false) {
feastDay = moveableFeast;
} else if (feastdays.fixedFeasts[month][dayofMonth]) {
posTitle = titleLower.indexOf(filterWord); // Would a user expect that all words must be present in title, or all words must be present in description?
//if (displayFilterLocation == false) {
posLocation = location.indexOf(filterWord); // Always check, so that one can search for a special type of event OR all events in a location
codeString = codeString.replace(/kategorie:/i, ''); // For human readability, the code or list of codes separated by commas can optionally begin with "Kategorie:"
codes = codeString.split(",");
for (j = 0; j < codes.length; j++) {
code = codes[j].toLowerCase();
if (code.substring(0, 1) === ' ') {
code = code.substring(1); // Remove an empty space at the beginning
}
if (code.substring(code.length - 1) === ' ') {
code = code.substring(0, code.length - 1); // Remove an empty space at the end
}
if (code.substring(0, 1) === '-') { // When the code is followed by a minus, it excludes the event from being automatically classified in a category
categorization = false;
code = code.substring(1);
} else {
categorization = true;
}
category = getEventCategoryByCode(code);
if (category !== false) {
eventCategories[category] = categorization;
validCode = true;
}
}
}
if (validCode) {
descriptionProcessed = descriptionProcessed.replace(searchResult[1], "").replace(" ", " "); // After processing valid codes, remove them from the description
setupDatepicker(); // Wait to initalize, as initializing the hidden date picker to begin with can cause the other, visible datepicker to have a date of 1900
function setSearchLocationFilter(value, refreshLocationInput) {
var newfilterText;
locationChanging = false;
if (displayFilterLocation === 'activate') {
activateFilterLocation();
}
if (displayFilterLocation === false) {
setSearchFilter(value, refreshLocationInput);
} else {
if (typeof (value) === 'string') {
newfilterText = value.toLowerCase();
if (newfilterText.toLowerCase() !== filterLocationText.toLowerCase()) {
filterLocationText = value;
setFilterText(value, filterLocations, ' /,'); // Since an event cannot be in two locations, assume spaces also indicate an event in ANY of the given locations
if (isLocationCalendarExclusive(locations)) { // If location(s) ONLY has events from certain calendars, return those calendars
return calendarsForLocation(locations);
}
locArray = getLocations(locations);
locationIds = getLocationIds(locArray);
for (c = 0; c < calendars.length; c++) {
if (calendars[c].locationExclusive === true) { // If calendar only has events for certain locations
locs = calendars[c].location;
if (typeof (locs) === 'string') { // should be either string or array
if (searchInObject(locationIds, locs) !== -1) { // if this location is identical to string locationId or contained in an array locationId
cals.push(calendars[c]);
}
} else if (typeof (locs) === 'object') {
for (l = 0; l < locs.length; l++) {
if (searchInObject(locationIds, locs[l]) !== -1) {
cals.push(calendars[c]);
}
}
}
} else {
cals.push(calendars[c]); // If the calendar isn't determined to particular locations, we have to add it
}
}
n = 0;
for (l = 0; l < locArray.length; l++) {
cal = locArray[l].calendar;
if (typeof (cal) === 'string') {
calNames[n++] = cal;
} else if (typeof (cal) === 'object') {
calNames = calNames.concat(cal);
n = calNames.length;
}
}
cals2 = getCalendarsByName(calNames);
return mergeCalendars(cals, cals2);
}
function calendarsDisplayedForLocation(locations) {
// locations can be a string (locationId), an array of strings (locationId), or of locations
// RETURNS: an array of the calendars for this location which are current displayed
var c, cals = [], calsVisible = [];
cals = calendarsForLocation(locations);
for (c = 0; c < cals.length; c++) {
if (cals[c].display === true) { // If calendar especially shows certain locations
calsVisible.push(cals[c]);
}
}
return calsVisible;
}
function areCalendarsForLocationVisible(locations) {
// locations can be a string (locationId), an array of strings (locationId), or of locations
// Returns true if at least one calendar that COULD have events in this/these locations is visible
var c, cals, otherCals;
if (calendarsDisplayedForLocation(locations).length > 0) {
return true; // Some calendars are displayed, that have events in this location
}
if (isLocationCalendarExclusive(locations)) { // There are only specific calendars that have events in the location
return false; // and none of these calendars is currently displayed
} else {
cals = calendarsForLocation(locations);
otherCals = subtractCalendars(calendars, cals);
for (c = 0; c < otherCals.length; c++) {
if (otherCals[c].display === true && otherCals[c].locationExclusive === false) { // If calendar is displayed, and is not restricted to certain locations
return true; // It could potentially have events in this location
}
}
}
return false;
}
function searchArray(searchCorpus, searchTerms) {
// returns true if all the terms in searchTerms are found in searchCorpus, otherwise false
if (typeof (searchTerms) === 'string') {
if (searchInObject(searchCorpus, searchTerms) !== -1) {
return true;
}
return false;
} else {
for (var i = 0; i < searchTerms.length; i++) {
if (searchInObject(searchCorpus, searchTerms[i]) === -1) {
return false;
}
}
return true;
}
}
function areCalendarsForLocationExclusive(locations, calSelection) {
// locations can be a string (locationId), an array of strings (locationId), or of locations
// If there are calendars that COULD (calSelection = 'all') or especially ('some') contain events for a location, and
// these calendars ONLY contain events for that location, returns true; otherwise returns false
// if locationId is an array of locations, returns true if in each case calendars are exclusively for them
// These can used, e.g., to determine whether location can be restricted to a given location by restricting calendars
var c, cals;
var locationId = getLocationIds(locations);
if (typeof (calSelection) === 'undefined') {
calSelection = 'some';
}
if (calSelection === 'some') {
cals = calendarsForLocation(locations);
} else {
cals = allCalendarsForLocation(locations);
}
for (c = 0; c < cals.length; c++) {
if (cals[c].location !== undefined && cals[c].locationExclusive === true) { // If calendar only shows certain locations
if (searchArray(locationId, cals[c].location) === false) {
return false; // This location could display events in other locations
}
} else if (calSelection === 'all') {
return false; // This location is not determinate, so it could potentially display events in other locations
}
}
return true;
}
function isLocationCalendarExclusive(locations) {
// Returns true if only specified calendars may have events in each one of the location(s) (locationId, array thereof, or of calendars)
// otherwise returns false
var locArray, l;
locArray = getLocations(locations);
if (locArray.length > 0) {
for (l = 0; l < locArray.length; l++) {
if (locArray[l].calendarExclusive !== true) { // If false or if undefined
return false;
}
}
return true;
}
}
function displayCalendarLocation(locations) {
// Displays any calendars that especially have events in the given location -- Returns true if any are additionally displayed.
alreadyRestricted = true; // there is already a filter equal to locationName
}
} else {
if (isLocation(filterWordLower)) { // If location is restricted, make it restricted to the array locationName
filterArray[set] = locationName;
changed = true;
}
}
} else {
if (filterArray[set].length === locationNameArray.length) {
alreadyRestricted = true;
for (l = 0; l < locationNameArray.length; l++) {
if (searchInObject(filterArray[set], locationNameArray[l]) === -1) {
alreadyRestricted = false;
break;
}
}
}
if (alreadyRestricted === false) {
filterArray[set] = locationName;
changed = true;
}
}
}
if (changed === false && alreadyRestricted === false) { // If no change is necessary, function has already returned -- at this point, we need to add the location
filterArray[filterArray.length] = locationName;
changed = true;
}
if (filterArray.length === 0) {
filterArray[0] = locationName;
changed = true;
}
return changed;
}
function removeAllSearchLocations() {
var set, l, changed;
var onlyLocations;
changed = false;
set = 0;
if (displayFilterLocation === true) {
if (filterLocationText !== '') {
filterLocations = [];
filterLocationsExpanded = [];
filterLocationText = '';
changed = true;
}
}
while (set < filterWords.length) {
if (typeof (filterWords[set]) === 'string') {
if (isLocation(filterWords[set])) { // If it is a location, remove it
if (filterWords[set].toLowerCase() !== filterLower) {
return true; // There is a filter different from the input "filter"
}
} else {
inGroup = false;
for (num = 0; num < filterWords[set].length; num++) {
if (filterWords[set][num].toLowerCase() === filterLower) {
inGroup = true;
break;
}
}
if (inGroup === false) {
return true;
}
}
}
return false; // Either there are not search filters, or the filter "filter" is always one of them
}
function getLocationFilterWordList() {
if (displayFilterLocation === true) {
return filterLocations;
} else {
return filterWords;
}
}
function getLocationFilterWordListExpanded() {
if (displayFilterLocation === true) {
return filterLocationsExpanded;
} else {
return filterWordsExpanded;
}
}
function isAdditionalLocation(location) {
// if events may be displayed for any location other than the single locationName
// TO DO (if needed): allow checking for locations beyond a set of locations
var set, num, locationLower, wordList, cals, c;
var locationName;
var isPresent;
var loc = getLocationById(location);
if (loc === false) {
return true;
}
locationName = loc.description;
locationLower = locationName.toLowerCase();
wordList = getLocationFilterWordListExpanded();
for (set = 0; set < wordList.length; set++) {
if (typeof (wordList[set]) === 'string') {
if (wordList[set] === locationLower) {
return false; // There is a filter equal to the input "locationName" -- thus the location has to be present
}
} else if (wordList[set].length === 1) {
if (wordList[set][0] === locationLower) {
return false; // There is a filter equal to the input "locationName" -- thus the location has to be present
}
}
else {
isPresent = false;
for (num = 0; num < wordList[set].length; num++) {
if (isLocation(wordList[set][num]) && wordList[set][num] !== locationLower) {
if (areCalendarsForLocationVisible(wordList[set][num])) {
return true; // There is another allowed location for which some calendar is displayed
}
}
}
}
}
if (areCalendarsForLocationExclusive(location)) {
//if (areCalendarsForLocationExclusive(locationId) , 'all') // to check all calendars that COULD display locations here?
//cals = subtractCalendars(calendar, calendarsForLocation(locationId)); // The calendars that aren't for thise one;
cals = subtractCalendars(calendars, allCalendarsForLocation(location)); // The calendars that aren't for thise one;
for (c = 0; c < cals.length; c++) {
if (cals[c].display === true) {
return true; // Other calendars are displayed;
}
}
return false;
}
return true;
}
function isSearchLocationRestricted(location) {
// If there is a filter restricting the search to a location other than the given one, return a location to which it is restricted, otherwise return false
var set, num, locationLower, locationInGroup, thisLocationInGroup;
var locationName;
var loc = getLocationById(location);
if (loc === false) {
locationName = 'nolocation';
} else {
locationName = loc.description;
}
locationLower = locationName.toLowerCase();
for (set = 0; set < filterWordsExpanded.length; set++) {
if (typeof (filterWordsExpanded[set]) === 'string') {
if (filterWordsExpanded[set] !== locationLower && isLocation(filterWordsExpanded[set])) {
return filterWordsExpanded[set]; // There is a filter for a location other than the given location
}
} else {
locationInGroup = false;
thisLocationInGroup = false;
for (num = 0; num < filterWordsExpanded[set].length; num++) {
if (isLocation(filterWordsExpanded[set][num])) {
locationInGroup = filterWordsExpanded[set][num];
}
if (filterWordsExpanded[set][num] === locationLower) {
thisLocationInGroup = true;
}
}
if (locationInGroup !== false && thisLocationInGroup === false) {
return locationInGroup;
}
}
}
return false;
}
function areSearchLocationsRestricted(locations) {
var t = typeof (locations);
if (t === 'undefined') {
return false;
} else if (t === 'string') {
return isSearchLocationRestricted(locations);
}
for (var i = 0; i < locations.length; i++) {
if (isSearchLocationRestricted(locations[i]) === false) {
return false; // If at least one of the locations is shown
}
}
return true;
}
function isSearchLocationCalendarRestricted(location) {
// if specific calendars especially show this location, and are not shown, returns true. Otherwise false
var c, cals;
cals = calendarsForLocation(location);
for (var c = 0; c < cals.length; c++) {
if (cals[c].display === false) { // If calendar is not displayed, and calendar especially shows certain locations
return true;
}
}
return false;
}
function updateSearchLocationDone(value) {
locationChanging = false;
notRestrictToVisibleMap();
setSearchLocationFilter(value, false);
}
var timerUpdateLocationFilter;
function updateSearchLocationChanging(value) {
var newfilterText;
locationChanging = true;
newfilterText = value.toLowerCase();
if (newfilterText !== filterLocationText.toLowerCase()) {
$(this).removeClass("fc-event-sel").addClass("fc-event").css("border", "1px solid " + borderColor); // Remove CSS event selected class from any previously selected event and return to normal
$(this).removeClass("fc-event-loc-sel").addClass("fc-event").css("border", "1px solid " + borderColor); // Remove CSS event selected class from any previously selected event and return to normal
});
$("tr.fc-event-loc-sel").removeClass("fc-event-loc-sel").css("border", ""); // Remove CSS event selected class from any previously selected event and return to normal
$(".fc-eventlist-title-loc-sel").removeClass("fc-eventlist-title-loc-sel"); // Remove CSS event selected class from any previously selected event and return to normal
setupDatepicker(); // Wait to initalize, as initializing the hidden date picker to begin with can cause the other, visible datepicker to have a date of 1900
$(calendarDiv).fullCalendar('render');
calendarOnceVisible = true;
} else {
$(calendarDiv).fullCalendar('updateSize');
}
//updateWhatToDisplay(); // In the event that the user refreshes the page (some browsers retain what was previously selected)
//if (calendarMessageHidden !== '') {
// calendarMessage(calendarMessageHidden);
//}
if (calendarsLoading) {
showCalendarsLoading();
} else {
hideCalendarsLoading();
}
} else {
$(calendarDiv).fullCalendar('windowResize');
}
calendarVisible = true;
}
function showCalendarsLoading() {
if (calendarVisible !== false) {
$(loadingDiv).css('visibility', 'visible');
}
}
function hideCalendarsLoading() {
if (calendarVisible !== false) {
$(loadingDiv).css('visibility', 'hidden');
}
clearTimeout(timerIsLoading);
}
function nowNotVisible() {
unselectEvents();
hideCalendarMessage();
hideCalendarsLoading();
if (googleMapsDialog === true) {
googleMapOff();
}
calendarVisible = false;
}
function getEventType(filterSelection) {
for (var i = 0; i < eventTypes.length; i++) {
if (filterSelection === eventTypes[i].id) {
return eventTypes[i];
}
}
return []; // No event type found
}
function updateWhatToDisplay() {
if (calendarLoading) {
return;
}
var newFilterEventId = $('#' + terminauswahlId + ' :selected').val();
if (newFilterEventId !== filterEventId) {
addInfo(newFilterEventId); // records searches, to improve the processing of them
if (cal.selectBox === false && cal.displayCalendar !== false) {
listExtraCalendars();
}
setLocationDetails();
} else {
removeCalendarQueue.push(cal);
queue(function() {
refreshCalendars();
}, refresh, 'refreshCalendars');
}
}
}
function displayFixedCalendarSelector(cal) {
var selector = '#' + cal.divId;
var html;
var addAfter;
if ($(selector).length === 0) { // Need to create calendar selector
cal.selectBox = true;
html = getCalendarHtml(cal, true);
if (cal.ordered === true) {
$(gemeindenFixedDiv).append(html);
} else {
addAfter = getCalendarOrderPrevVisible(cal);
if (addAfter === 'first') {
$(gemeindenFixedDiv).prepend(html);
} else if (addAfter === 'last') {
$(gemeindenFixedDiv).append(html);
} else {
$('#' + addAfter.divId).after(html);
}
cal.ordered = true;
}
} else if (cal.selectBox === false) { // is not already in the list
cal.ordered = true;
moveCalendarToFixedList(cal);
} else {
$(selector).html(getCalendarInnerHtml(cal, true)); // refresh -- not sure if this is still necessary
}
}
function displayFixedCalendar(cal) {
if (typeof (cal.id) !== 'undefined') {
displayFixedCalendarSelector(cal);
queue(function() {
displayCalendar(cal);
}
);
} else { // multiple calendars
$.each(cal, function(index, singleCal) {
displayFixedCalendar(singleCal);
});
}
}
function getCalendars(condition) {
if (condition === undefined) {
condition = function() {
return true;
};
}
var cals = [];
for (var i = 0; i < calendars.length; i++) {
if (condition(calendars[i])) {
cals.push(calendars[i]);
}
}
return cals;
}
function getCalendarInnerHtml(cal, checkBox) {
var html;
var calendarId = calendarChkboxId(cal.id);
var oneLocation = false;
checkBox = checkBox || !restrictedToVisibleMap(); // If no check box associated with calendar, but it's not determined by the map, make a temporary check box
html = '<a onclick="' + calendarFunctionString + '(\'addSearchLocationManual\', \'' + location.id + '\')">Auch Termine an diesem Ort zeigen</a>';
} else if ($(calendarDiv).calendarGemeinden('isAdditionalSearchFilter', location.id) && location.numberHiddenEvents > 0) {
html = '<a onclick="' + calendarFunctionString + '(\'allLocationEvents\',\'' + location.id + '\')">Alle Termine an diesem Ort zeigen</a>';
} else {
html = '';
}
if (location.numberEvents > 0) { // If some events in this location are visible, allow one to view only them
if ($(calendarDiv).calendarGemeinden('isAdditionalLocation', location.id)) {
if (html !== '') {
html += '<br/>';
}
html += '<a onclick="' + calendarFunctionString + '(\'restrictSearchLocationManual\',\'' + location.id + '\')">Nur Termine an diesem Ort zeigen</a>';
}
}
if (html !== '') {
html = '<div id="show_this_location">' + html + '</div>';
}
return html;
}
/* Elements from the jQuery Client Side Logging Plugin by Remy Bach, version 1.1.2 (MIT license http://remybach.mit-license.org) is here used to record calendar searches; this may be used to improve the search procedure; searches are not associated with IP addresses or otherwise personally identifiable information */
$.info = function(what) {
if (recordInfoAddress !== false) {
_send(recordInfoAddress, what);
}
};
// Log errors whenever there's a generic js error on the page.
window.onerror = function(message, file, line) {
if (recordErrorAddress !== false) {
_send(recordErrorAddress, {
message: message,
file: file,
line: line
});
}
};
/*===== Private Functions =====*/
/**
* Send the log information to the server.
* @param url The url to submit the information to.
* @param what The information to be logged.
*/
_send = function(url, what) {
url += url.match(/\?.+$/) ? '&' : '?';
if (typeof what === 'object') {
// Let's grab the additional logging info before we send this off.
calendarDiv: calendarDiv, // The div in which the calendar itself is located
calendarOptionsDiv: '#calendar-options', // The div in which the calendar options are located (selection of communities, filters, location, etc.)
recordInfoAddress: false, // server-side script to record searches, etc. -- FALSE if not recording
recordErrorAddress: false, // server-side script to record javascript errors -- FALSE if not recording
loadingDiv: '#loading', // a div for displaying a loading icon -- should already be populated; it will only be made visible and invisible by the plugin
calendarMessageDiv: '#cal_message', // a div for displaying calendar messages (z.B. keine Termine an dem Ort gefunden)
googleMaps: true, // Whether to enable google maps
googleMapsDialog: true, // if true, displays the map in a dialog box
dialogWidth: 510, // The width and height of the dialog box to be opened
dialogHeight: 420,
googleMapsStartType: google.maps.MapTypeId.ROADMAP, // The default view type for the map
googleMapsStartLocation: 'Dom', // The starting location for the map
googleMapsStartZoom: 12, // The starting zoom for the map
googleMapsFixedOptions: false, // Indicates whether fixed options are present above where additional calendars will be shown for the map
// if true such calendars will be separated from this by a horizontal line
mapContainer: '#map_container', // a div for the google maps itself
mapOptionsDiv: '#map-options', // a div in which map options occur
collapseMapOptions: true, // map options are rendered invisible when there are no calendars to display (can be of use when all options are related to those calendars)
mapCalendarsDiv: '#map-calendars', // a div in which calendars will be placed
displayFilterLocation: 'activate', // TRUE/FALSE/'activate' -- if true, displays a second filter for filtering locations;
// if 'activate', displays a second filter when restricting location programatically
// if false, never displays
storeOptionsLocally: true, // Whether to store the options in local storage
storeCalendarDuration: 60 * 36 * 1, // How long, in minutes, to store the selection of calendars displayed and in the choice. Only applies if storeOptionsLocally is true
storeCalendarOrderDuration: 60 * 24 * 14, // How long, in minutes, to store the selection of calendars displayed and in the choice. Only applies if storeOptionsLocally is true
storeFilterDuration: 10, // How long, in minutes, to store search filters, selection of event types, etc. Only applies if storeOptionsLocally is true
//storeViewDuration: 60, // How long to store view type (month, week, day) and date -- NOT YET IMPLEMENTED: Would it be desirable?
additionalButtons: false, // STRING of html code for additional buttons (e.g., select a group of calendars)
additionalEventSelectionCode: false, // STRING of html code for additional options to select types of events, etc.
calendarConfigurationName: 'cg', // The name of the calendar configuration -- enables the possibility of multiple sets on the same domain
defaultFilter: 'any', // 'selected' shows only special important events for Wr. Neustadt, 'all' shows all events (apart from other filters applied)
repeatWeekDaysAfterManyEvents: 7, // Applies only to calendar month view; shows the day of the week on each row when at least one row has this many events; a value of false disables the option
terminAuswahlText: 'Terminauswahl:', // Text to display for the selection of event types
searchText: 'Suchbegriff:', // Text to display for entering an arbitrary search term; FALSE disables this search
calendarVisible: true, // Whether the calendar is visible (if it is hidden, will not pop up messages, etc.)
eventTypes: [
{id: 'any',
menu: 'Alle Termine',
description: 'Termine', // Description is shown in messages, etc.
test: true
},
{id: 'selected', // Events matching 'selected' or 'families' are not excluded from the event type 'other'
menu: 'Ausgewählte, besondere Termine',
description: 'ausgewählte, besondere Termine', // Those events particularly important for the area Wr. Neustadt (the type of event for which one makes flyers or posters, etc.)
test: function(event) { // eventTypes is passed so that one can check which other types the event matches (for the sake of an event type: 'other events')
if (event.source.className == 'ssr') { // if the event is in the calendar for a pastoral area (considered important by default for Wr. Neustadt); needs this comparison -- strict comparison doesn't work; not sure why
return true;
}
return event.special;
},
code: 'fa'
},
{id: 'families',
menu: 'Für Kinder + Familien',
description: 'Angebote für Kinder und Familien',
test: function(event) {
var titleModified = event.title.replace(/Familienkirche/g, '');
var isFamilySearchExp = /kind|jungschar|famili/i;
var isFamily = isFamilySearchExp.test(titleModified);
if (isFamily) {
return true;
}
var descriptionModified = event.description.replace(/Familienkirche/g, '');
var isLiturgyHoursSearchExp = /morgengebet|morgenlob|laudes|vesper|abendlob|komplett|trauermette|terz|sext|none|mittagshore/gi;
return isLiturgyHoursSearchExp.test(event.title);
},
eventGroup: 'type'
},
{id: 'liturgy',
menu: 'Messen, Andachten, Gebete, usw.',
description: 'Gottesdienste, Gebetsstunden, oder Ähnliches',
test: function(event) {
var isGottesdienstSearchExp = /gottesdienst|wort-gottes-feier|auferstehungsfeier|auferstehungsfest|wortgottesfeier|messfeier|andacht|messe|rorate|patrozinium|hochamt|eucharist|anbetung|gebet|rosenkranz|kreuzweg|liturgie|laudes|vesper|bibelkreis|abend der barmherzigkeit|abendmahl|cruzifix|erstkommunion/i;
var isGroupSearchExp = /Ministrantenstunde|Ministunde|-Minis|Jungscharstunde|Firmstunde|Jugendstunde|Jugendgruppe|firmvorbereitung/;
if (isGroupSearchExp.test(event.title)) {
return true;
}
return isGroupSearchExp.test(event.description);
},
code: ['gs', 'gruppenstunde'],
eventGroup: 'type'
},
{id: 'faith',
menu: 'Glaubensvertiefung',
description: 'Glaubensvertiefung',
test: function(event) {
var isFaithSearchExp = /katechese|bibelrunde|bibelgruppe|bibelkreis/i;
return isFaithSearchExp.test(event.title);
},
code: ['gv', 'glaubensvertiefung'],
eventGroup: 'type'
},
{id: 'concert',
menu: 'Konzerte',
description: 'Konzerte',
test: function(event) {
var isConcertSearchExp = /konzert/i;
return isConcertSearchExp.test(event.title);
},
code: ['gv', 'glaubensvertiefung'],
eventGroup: 'type'
},
{id: 'other',
menu: 'sonstige Veranstaltungen oder Termine',
description: 'sonstige Veranstaltungen oder Termine',
test: function(event, eventTypes) {
for (var i = 0; i < eventTypes.length; i++) {
if (eventTypes[i].eventGroup === 'type') {
if (isEventType(event, eventTypes[i])) {
return false;
}
}
}
return true;
}
// 'other' // an event is considered to be this type of event if it doesn't match any of the other types (events with eventType: true
},
{id: 'option-group', // To make an unnamed separator between the previous options and the option to filter by search term
menu: ''},
{id: 'option-group-end'},
{id: 'filter', // Important! (1) events matching 'filter' are not excluded from the event type 'other'
searchTerm: true, // Uses the specified search term
menu: 'Mit Suchbegriff übereinstimmend',
description: 'mit dem Suchbegriff', // unused at present
test: function(event) {
return compareFilter(event);
}
}
],
messages: {
inSelectedCalendarText: 'im gewählten Kalender',
inSelectedCalendarsText: 'in den gewählten Kalendern'
},
automaticLocationNotice: '<br/><br/><strong>Hinweis:</strong>Termine an diesem Ort werden von einer Liste wiederkehrenden Termine automatisch erzeugt.' +
'Gegebenenfalls kontrollieren Sie bei der Gemeinde, ob eine Änderung vorliegt.', // Notice given in the details of a location, if events are automatically generated by a set of rules
automaticEventNotice: 'dieser Termin wurde von einer Liste wiederkehrenden Termine in der Gemeinde genommen. Gegebenenfalls kontrollieren Sie bei der Gemeinde, ob eine Änderung vorliegt.',
//automaticEventNoticeFeast: 'dieser Termin wurde von einer Liste wiederkehrenden Termine in der Gemeinde genommen. In diesem Fall fällt der Termin mit einem Festtag zusammen! Kontrollieren Sie gegebenenfalls bei der Gemeinde, ob der Termin auch an diesem Festtag stattfindet.',
automaticEventNoticeFeast: function(feast) {
return 'dieser Termin wurde von einer Liste regelmäßigen Termine an Sonntagen in der Gemeinde genommen. ' +
'Da dieser Sonntag ein besonderer Festtag (' + feast + ') ist, kontrollieren Sie gegebenenfalls bei der Gemeinde, ' +
'ob der Termin auch an diesem Festtag stattfindet.';
},
calendarSelectionText: 'Gemeinden: ', // Text displayed before the list of calendars that the user can select or deselect
noticeCalendarsVisible: 'Zusätzliche Kalender/Orte auf der Karte sichtbar:',
noticeCalendarsSelected: 'Zusätzlich zu den allgemein wählbaren Kalendern sind ausgewählt:',
noticeCalendarsShown: 'Zusätzlich zu den allgemein wählbaren Kalendern werden nun angezeigt:',
restrictedToVisibleMap: function() { // Returns true if only calendars and locations should be shown which are visible on the map, otherwise false
if ($('#restrict_to_visible').is(':checked')) {
return true;
} else {
return false;
}
},
restrictToVisibleMap: function() { // Sets the option to have only calendars and locations should be shown which are visible on the map, otherwise false
$('#restrict_to_visible').prop('checked', true);
},
notRestrictToVisibleMap: function() { // Clears the option to have only calendars and locations should be shown which are visible on the map, otherwise false
$('#restrict_to_visible').prop('checked', false); // Is called when a change is made manually to to the locations (e.g., "show only events in this location")
},
// restrictVisibleChange is an exported function which should be called if a change is made as to whether the display of calendars
// is restricted to visible locations
getLocationViewOptions: function(location) { // FALSE, or a function that returns html code for appropiate options under the "mehr Details" of a location
// (z.B., zeige auch Termine an diesem Ort, zeige nur Termine an diesem Ort, usw.)
standard: {icon: 'http://www.google.com/mapfiles/ms/micons/red-dot.png', shape: standardShape}, // The normal pin icon
selected: {icon: 'http://www.google.com/mapfiles/ms/micons/blue-dot.png', shape: standardShape}, // The icon for a location that the user has selected
noEvents: {icon: 'grafiken/red-dot-transparent.png', shape: standardShape}, // The icon for a location for which no events are shown
small: {icon: 'grafiken/red-dot-small.png'} // A small icon, used in the calendar options to toggle the map when it is a dialog
},
locationSelectedBorder: '4px solid Red', // The border of an event that is selected
eventLocationSelectedBorder: '3px solid #FFB000', // The border of events for which the location is selected
equivalentSearchs: {// When a search is made for an item contained in this list, the search will return events that match any of the words in the corresponding array
kind: ['kind', 'kinder', 'jungschar'],
kinder: ['kind', 'kinder', 'jungschar']
},
areas: [],
calendars: [], // An array of the calendars and info for them
// each calendar is an object with the possible properties
// name: STRING unique internal name for the calendar
// description: STRING name used on the site to describe the calendar
// location: STRING/ARRAY string or array of the location(s) for which this calendar especially has events --
// If a single location is assigned for a calendar, the events in that calendar for which no particular location is assigned
// will be assumed to be in that location.
// at present it must match the name property of the location (in the future location should also have a unique id, so that two locations can have the same name)
// locationExclusive: TRUE/FALSE, // if this calendar only contains events in the given location(s)
// color: "#DC3670", // color of the calendar and events in it -- if unassigned, a color will be assigned based on a hase of the name
// borderColor: "#6B1B38", // border color -- if unassigned, a darker tone of the calendar color will be assigned
// className: STRING, // a class added to events of the calendar (the class 'ssr' is used for 'special selected events' -- 'besondere, ausgewählte Termine')
// selectBox: TRUE/FALSE, // whether there is initially a select box to select/unselect the calendar
// display: TRUE/FALSE, // whether the calendar is initially displayed -- if omitted, and a select box is present, defaults to TRUE
// // if set to true, displays when there is no selectBox, and the map is not displayed (because it is a dialog)
// url: feed for the calendar, e.g., "http://www.google.com/calendar/feeds/h4578d3uo4kpv1drhd4mvq1shc%40group.calendar.google.com/public/basic",
// feedid: "h4578d3uo4kpv1drhd4mvq1shc%40group.calendar.google.com" // when caching is used, feed id is used to build the url for the feed and the cache server
// cacheServer="http://www.erloeserkirche.at/scripts/cache/", // root location of a server that can cache requests for feeds -- WARNING! Have not tested for several revisions
// -- under frequent usage of the calendar by various users, caching could increase responsiveness; otherwise does not help much
// locations: [], // An array of info for the locations
// description: 'Herz Mariä' - STRING, the location's description
// calendar: ['hm','nk'] - STRING or ARRAY - the calendars that especially have events in this location
// calendarExclusive: TRUE/FALSE -- whether ONLY those calendars have events in this location - defaults to FALSE
// coords: '47.831423,16.263058', ' STRING - coordinates of the location
// info: 'Herz Mariä', STRING, 'info displayed on the map for the location
// moreInfo: 'Die katholische Pfarrkirche Mariä<br>Adresse: Pottendorfer Straße 117, 2700 Wiener Neustadt' STRING (can have html markup),
// info displayed for the location in a popup window from the map
shortLocations: [{search: 'katharinenkapelle', description: 'Katharinenkapelle'}, // An array of short locations; they are search in sequential order; if the search term "search" is found
{search: 'erlöserkirche', description: 'Erlöserkirche'}, // the short location is the value of "short"; otherwise the short location defaults to the full location
{search: 'familienkirche', description: 'Familienkirche'}, // In place of an array, a function(location){... return shortLocation}
{search: 'schmuckerau', description: 'Familienkirche'}, // which takes as input the full location and returns the short location can be provided
week: " d [ MMM] [ yyyy]{ '- 'd MMM yyyy}", // Sep 7 - 13 2009
day: 'dddd, d.MMM.yyyy' // Tuesday, Sep 8, 2009
},
columnFormat: {
month: 'ddd', // September 2009
week: "ddd d.M", // Sep 7 - 13 2009
day: 'dddd d.M' // Tuesday, Sep 8, 2009
},
timeFormat:
{
// for agendaWeek and agendaDay
agenda: 'H:mm{ - H:mm}', // 5:00 - 6:30
// for all other views
'': 'H:mm{ - H:mm}'
},
defaultView: 'agendaWeek',
fetch: 'auto',
prefetch: true,
prefetchMonths: 1, // Number of months ahead to prefetch
cacheToleration: 51, // Retrieve a cached list of events that includes up to this many more days than the range we're looking for
agendaList: {
location: 'short',
skipLocation: false, // Can skip displaying this location (useful when, e.g., it is a "default" location, which can be taken for granted when no location is listed
timeRange: true, // If true, displays starting time till ending time -- if false, displays only starting time
minTimeRange: 0, // displays only starting time, unless event is longer than minTimeRange hours
completeMonth: true, // always displays till the end of a month
repeatMultidayEvents: 60, // Number of times to repeat multi-day events in agenda list view
repeatMultidayEventDescriptions: 7 // Number of times to repeat multi-day events in agenda list view
//maxDescriptionLength: 200 // Descriptions longer than this will be cut off with an ellipsis in the list
},
agendaListOrder: 'times', // the default sorting order for the agenda list view -- by 'times', or by 'places'
agendaListAllowReorder: true, // Give the user an option to swap from ordering by times to places or conversely
agendaListDisplayRange: true, // Displays the range of dates displayed
agendaListPreviousEvents: 'Zeige auch frühere Termine.', // is put in a span with class fc-agendaList-previous
agendaListNextEvents: 'Zeige auch weitere Termine.', // is put in a span with class fc-agendaList-next
defaultDaysAgendaList: 14, // Default number of days to show in agenda list mode (is only relevant when defaultView is agendaWeek -- otherwise the range is taken from the previous range (day, week, or month)
agendaListExtend: 7,
agendaListExtendAfterMonth: 28,
modules: ['scripts/jquery.icalendar.js'], // Modules loaded upon initialization
echoUrl: 'http://www.erloeserkirche.at/scripts/ical/' // echos an ical entry to be downloaded