From 4471a4a08cb5d3b01508217d0f41dbf6c056a6e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@cs.tu-darmstadt.de> Date: Sun, 1 Mar 2020 15:29:40 +0100 Subject: [PATCH 01/15] Improve Model Add dependency django-timezone-field Add timezone field to Event Introduce i18n for default_slot field Add new and missing translations Add title property to Room (for better access of combined building + name form) --- AKModel/locale/de_DE/LC_MESSAGES/django.po | 232 +++++++++++---------- AKModel/migrations/0027_event_timezone.py | 19 ++ AKModel/models.py | 19 +- AKPlanning/settings.py | 1 + requirements.txt | 1 + 5 files changed, 160 insertions(+), 112 deletions(-) create mode 100644 AKModel/migrations/0027_event_timezone.py diff --git a/AKModel/locale/de_DE/LC_MESSAGES/django.po b/AKModel/locale/de_DE/LC_MESSAGES/django.po index 0424d243..cb70a53a 100644 --- a/AKModel/locale/de_DE/LC_MESSAGES/django.po +++ b/AKModel/locale/de_DE/LC_MESSAGES/django.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-10-30 13:18+0000\n" +"POT-Creation-Date: 2020-03-01 14:21+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -23,17 +23,17 @@ msgstr "Ist ein Wunsch" msgid "Is not a wish" msgstr "Ist kein Wunsch" -#: admin.py:53 +#: admin.py:54 msgid "Export to wiki syntax" msgstr "In Wiki-Syntax exportieren" -#: availability.py:38 models.py:30 models.py:51 models.py:103 models.py:121 -#: models.py:152 models.py:201 models.py:237 models.py:263 +#: availability.py:38 models.py:37 models.py:58 models.py:110 models.py:128 +#: models.py:159 models.py:208 models.py:244 models.py:274 msgid "Event" msgstr "Event" -#: availability.py:39 models.py:52 models.py:104 models.py:122 models.py:153 -#: models.py:202 models.py:238 models.py:264 +#: availability.py:39 models.py:59 models.py:111 models.py:129 models.py:160 +#: models.py:209 models.py:245 models.py:275 msgid "Associated event" msgstr "Zugehöriges Event" @@ -45,7 +45,7 @@ msgstr "Person" msgid "Person whose availability this is" msgstr "Person deren Verfügbarkeit hier abgebildet wird" -#: availability.py:56 models.py:241 models.py:256 +#: availability.py:56 models.py:248 models.py:267 msgid "Room" msgstr "Raum" @@ -53,17 +53,15 @@ msgstr "Raum" msgid "Room whose availability this is" msgstr "Raum dessen Verfügbarkeit hier abgebildet wird" -#: availability.py:65 models.py:205 models.py:255 +#: availability.py:65 models.py:212 models.py:266 msgid "AK" msgstr "AK" #: availability.py:66 -#, fuzzy -#| msgid "Availabilities" msgid "AK whose availability this is" msgstr "Verfügbarkeiten" -#: availability.py:74 models.py:107 +#: availability.py:74 models.py:114 msgid "AK Category" msgstr "AK Kategorie" @@ -79,70 +77,86 @@ msgstr "Verfügbarkeit" msgid "Availabilities" msgstr "Verfügbarkeiten" -#: models.py:12 models.py:98 models.py:118 models.py:136 models.py:150 -#: models.py:167 models.py:230 +#: models.py:14 models.py:105 models.py:125 models.py:143 models.py:157 +#: models.py:174 models.py:237 msgid "Name" msgstr "Name" -#: models.py:13 +#: models.py:15 msgid "Name or iteration of the event" msgstr "Name oder Iteration des Events" -#: models.py:14 -#, fuzzy -#| msgid "Short Name" +#: models.py:16 msgid "Short Form" msgstr "Kurzer Name" -#: models.py:15 +#: models.py:17 msgid "Short name of letters/numbers/dots/dashes/underscores used in URLs." msgstr "" +"Kurzname bestehend aus Buchstaben, Nummern, Punkten und Unterstrichen zur " +"Nutzung in URLs" -#: models.py:16 +#: models.py:19 +msgid "Place" +msgstr "Ort" + +#: models.py:20 +msgid "City etc. the event takes place in" +msgstr "Stadt o.ä. in der das Event stattfindet" + +#: models.py:22 +msgid "Time Zone" +msgstr "Zeitzone" + +#: models.py:22 +msgid "Time Zone where this event takes place in" +msgstr "Zeitzone in der das Event stattfindet" + +#: models.py:23 msgid "Start" msgstr "Start" -#: models.py:16 +#: models.py:23 msgid "Time the event begins" msgstr "Zeit zu der das Event beginnt" -#: models.py:17 +#: models.py:24 msgid "End" msgstr "Ende" -#: models.py:17 +#: models.py:24 msgid "Time the event ends" msgstr "Zeit zu der das Event endet" -#: models.py:18 -msgid "Place" -msgstr "Ort" - -#: models.py:19 -msgid "City etc. the event takes place in" -msgstr "Stadt o.ä. in der das Event stattfindet" - -#: models.py:20 +#: models.py:26 msgid "Active State" msgstr "Aktiver Status" -#: models.py:20 +#: models.py:26 msgid "Marks currently active events" msgstr "Markiert aktuell aktive Events" -#: models.py:22 +#: models.py:28 msgid "Base URL" msgstr "URL-Prefix" -#: models.py:22 +#: models.py:28 msgid "Prefix for wiki link construction" msgstr "Prefix für die automatische Generierung von Wiki-Links" -#: models.py:26 +#: models.py:29 +msgid "Default Slot Length" +msgstr "Standardslotlänge" + +#: models.py:30 +msgid "Default length in hours that is assumed for AKs in this event." +msgstr "Standardlänge von Slots (in Stunden) für dieses Event" + +#: models.py:32 msgid "Contact email address" msgstr "E-Mail Kontaktadresse" -#: models.py:27 +#: models.py:34 msgid "" "An email address that is displayed on every page and can be used for all " "kinds of questions" @@ -150,288 +164,292 @@ msgstr "" "Eine Mailadresse die auf jeder Seite angezeigt wird und für alle Arten von " "Fragen genutzt werden kann" -#: models.py:31 +#: models.py:38 msgid "Events" msgstr "Events" -#: models.py:45 +#: models.py:52 msgid "Nickname" msgstr "Spitzname" -#: models.py:45 +#: models.py:52 msgid "Name to identify an AK owner by" msgstr "Name durch den eine AK Leitung identifiziert wird" -#: models.py:46 +#: models.py:53 msgid "Slug" msgstr "Slug" -#: models.py:47 +#: models.py:54 msgid "Slug for URL generation" msgstr "Slug für URL-Generierung" -#: models.py:48 +#: models.py:55 msgid "Institution" msgstr "Instutution" -#: models.py:48 +#: models.py:55 msgid "Uni etc." msgstr "Universität o.ä." -#: models.py:49 models.py:176 +#: models.py:56 models.py:183 msgid "Web Link" msgstr "Internet Link" -#: models.py:49 +#: models.py:56 msgid "Link to Homepage" msgstr "Link zu Homepage oder Webseite" -#: models.py:55 +#: models.py:62 msgid "AK Owner" msgstr "AK Leitung" -#: models.py:56 +#: models.py:63 msgid "AK Owners" msgstr "AK Leitungen" -#: models.py:98 +#: models.py:105 msgid "Name of the AK Category" msgstr "Name des AK Kategorie" -#: models.py:99 models.py:119 +#: models.py:106 models.py:126 msgid "Color" msgstr "Farbe" -#: models.py:99 models.py:119 +#: models.py:106 models.py:126 msgid "Color for displaying" msgstr "Farbe für die Anzeige" -#: models.py:100 models.py:170 +#: models.py:107 models.py:177 msgid "Description" msgstr "Beschreibung" -#: models.py:101 +#: models.py:108 msgid "Short description of this AK Category" msgstr "Beschreibung der AK-Kategorie" -#: models.py:108 +#: models.py:115 msgid "AK Categories" msgstr "AK Kategorien" -#: models.py:118 +#: models.py:125 msgid "Name of the AK Track" msgstr "Name des AK Tracks" -#: models.py:125 +#: models.py:132 msgid "AK Track" msgstr "AK Track" -#: models.py:126 +#: models.py:133 msgid "AK Tracks" msgstr "AK Tracks" -#: models.py:136 +#: models.py:143 msgid "Name of the AK Tag" msgstr "Name das AK Tags" -#: models.py:139 +#: models.py:146 msgid "AK Tag" msgstr "AK Tag" -#: models.py:140 +#: models.py:147 msgid "AK Tags" msgstr "AK Tags" -#: models.py:150 +#: models.py:157 msgid "Name of the Requirement" msgstr "Name der Anforderung" -#: models.py:156 +#: models.py:163 msgid "AK Requirement" msgstr "AK Anforderung" -#: models.py:157 +#: models.py:164 msgid "AK Requirements" msgstr "AK Anforderungen" -#: models.py:167 +#: models.py:174 msgid "Name of the AK" msgstr "Name des AKs" -#: models.py:168 +#: models.py:175 msgid "Short Name" msgstr "Kurzer Name" -#: models.py:169 +#: models.py:176 msgid "Name displayed in the schedule" msgstr "Name zur Anzeige im AK Plan" -#: models.py:170 +#: models.py:177 msgid "Description of the AK" msgstr "Beschreibung des AKs" -#: models.py:172 +#: models.py:179 msgid "Owners" msgstr "Leitungen" -#: models.py:173 +#: models.py:180 msgid "Those organizing the AK" msgstr "Menschen, die den AK organisieren und halten" -#: models.py:176 +#: models.py:183 msgid "Link to wiki page" msgstr "Link zur Wiki Seite" -#: models.py:178 +#: models.py:185 msgid "Category" msgstr "Kategorie" -#: models.py:179 +#: models.py:186 msgid "Category of the AK" msgstr "Kategorie des AKs" -#: models.py:180 +#: models.py:187 msgid "Tags" msgstr "Tags" -#: models.py:180 +#: models.py:187 msgid "Tags provided by owners" msgstr "Tags, die durch die AK Leitung vergeben wurden" -#: models.py:181 +#: models.py:188 msgid "Track" msgstr "Track" -#: models.py:182 +#: models.py:189 msgid "Track the AK belongs to" msgstr "Track zu dem der AK gehört" -#: models.py:184 +#: models.py:191 msgid "Resolution Intention" msgstr "Resolutionsabsicht" -#: models.py:185 +#: models.py:192 msgid "Intends to submit a resolution" msgstr "Beabsichtigt eine Resolution einzureichen" -#: models.py:186 +#: models.py:193 msgid "Present this AK" msgstr "AK Präsentieren" -#: models.py:187 +#: models.py:194 msgid "Present results of this AK" msgstr "Die Ergebnisse dieses AKs vorstellen" -#: models.py:189 +#: models.py:196 msgid "Requirements" msgstr "Anforderungen" -#: models.py:190 +#: models.py:197 msgid "AK's Requirements" msgstr "Anforderungen des AKs" -#: models.py:192 +#: models.py:199 msgid "Conflicting AKs" msgstr "AK Konflikte" -#: models.py:193 +#: models.py:200 msgid "AKs that conflict and thus must not take place at the same time" msgstr "" "AKs, die Konflikte haben und deshalb nicht gleichzeitig stattfinden dürfen" -#: models.py:194 +#: models.py:201 msgid "Prerequisite AKs" msgstr "Vorausgesetzte AKs" -#: models.py:195 +#: models.py:202 msgid "AKs that should precede this AK in the schedule" msgstr "AKS die im AK Plan vor diesem AK stattfinden müssen" -#: models.py:197 +#: models.py:204 msgid "Internal Notes" msgstr "Interne Notizen" -#: models.py:197 +#: models.py:204 msgid "Notes to organizers" msgstr "Notizen an die Organisator*innen" -#: models.py:199 +#: models.py:206 msgid "Interest" msgstr "Interesse" -#: models.py:199 +#: models.py:206 msgid "Expected number of people" msgstr "Erwartete Personenzahl" -#: models.py:206 +#: models.py:213 msgid "AKs" msgstr "AKs" -#: models.py:230 +#: models.py:237 msgid "Name or number of the room" msgstr "Name oder Nummer des Raums" -#: models.py:231 +#: models.py:238 msgid "Building" msgstr "Gebäude" -#: models.py:232 +#: models.py:239 msgid "Name or number of the building" msgstr "Name oder Nummer des Gebäudes" -#: models.py:233 +#: models.py:240 msgid "Capacity" msgstr "Kapazität" -#: models.py:233 +#: models.py:240 msgid "Maximum number of people" msgstr "Maximale Personenzahl" -#: models.py:234 +#: models.py:241 msgid "Properties" msgstr "Eigenschaften" -#: models.py:235 +#: models.py:242 msgid "AK requirements fulfilled by the room" msgstr "AK Anforderungen, die dieser Raum erfüllt" -#: models.py:242 +#: models.py:249 msgid "Rooms" msgstr "Räume" -#: models.py:255 +#: models.py:266 msgid "AK being mapped" msgstr "AK, der zugeordnet wird" -#: models.py:257 +#: models.py:268 msgid "Room the AK will take place in" msgstr "Raum in dem der AK stattfindet" -#: models.py:258 +#: models.py:269 msgid "Slot Begin" msgstr "Beginn des Slots" -#: models.py:258 +#: models.py:269 msgid "Time and date the slot begins" msgstr "Zeit und Datum zu der der AK beginnt" -#: models.py:260 +#: models.py:271 msgid "Duration" msgstr "Dauer" -#: models.py:261 +#: models.py:272 msgid "Length in hours" msgstr "Länge in Stunden" -#: models.py:267 +#: models.py:277 +msgid "Last update" +msgstr "Letzte Aktualisierung" + +#: models.py:280 msgid "AK Slot" msgstr "AK Slot" -#: models.py:268 +#: models.py:281 msgid "AK Slots" msgstr "AK Slot" -#: models.py:282 +#: models.py:295 msgid "Not scheduled yet" msgstr "Noch nicht geplant" diff --git a/AKModel/migrations/0027_event_timezone.py b/AKModel/migrations/0027_event_timezone.py new file mode 100644 index 00000000..ab526080 --- /dev/null +++ b/AKModel/migrations/0027_event_timezone.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.6 on 2020-03-01 14:13 + +from django.db import migrations +import timezone_field.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('AKModel', '0026_akslot_updated'), + ] + + operations = [ + migrations.AddField( + model_name='event', + name='timezone', + field=timezone_field.fields.TimeZoneField(choices=[('Pacific/Apia', 'GMT-11:00 Pacific/Apia'), ('Pacific/Fakaofo', 'GMT-11:00 Pacific/Fakaofo'), ('Pacific/Midway', 'GMT-11:00 Pacific/Midway'), ('Pacific/Niue', 'GMT-11:00 Pacific/Niue'), ('Pacific/Pago_Pago', 'GMT-11:00 Pacific/Pago Pago'), ('America/Adak', 'GMT-10:00 America/Adak'), ('Pacific/Honolulu', 'GMT-10:00 Pacific/Honolulu'), ('Pacific/Rarotonga', 'GMT-10:00 Pacific/Rarotonga'), ('Pacific/Tahiti', 'GMT-10:00 Pacific/Tahiti'), ('US/Hawaii', 'GMT-10:00 US/Hawaii'), ('Pacific/Marquesas', 'GMT-09:00 Pacific/Marquesas'), ('America/Anchorage', 'GMT-09:00 America/Anchorage'), ('America/Juneau', 'GMT-09:00 America/Juneau'), ('America/Nome', 'GMT-09:00 America/Nome'), ('America/Sitka', 'GMT-09:00 America/Sitka'), ('America/Yakutat', 'GMT-09:00 America/Yakutat'), ('Pacific/Gambier', 'GMT-09:00 Pacific/Gambier'), ('US/Alaska', 'GMT-09:00 US/Alaska'), ('America/Dawson', 'GMT-08:00 America/Dawson'), ('America/Fort_Nelson', 'GMT-08:00 America/Fort Nelson'), ('America/Los_Angeles', 'GMT-08:00 America/Los Angeles'), ('America/Metlakatla', 'GMT-08:00 America/Metlakatla'), ('America/Tijuana', 'GMT-08:00 America/Tijuana'), ('America/Vancouver', 'GMT-08:00 America/Vancouver'), ('America/Whitehorse', 'GMT-08:00 America/Whitehorse'), ('Canada/Pacific', 'GMT-08:00 Canada/Pacific'), ('Pacific/Pitcairn', 'GMT-08:00 Pacific/Pitcairn'), ('US/Pacific', 'GMT-08:00 US/Pacific'), ('America/Bahia_Banderas', 'GMT-07:00 America/Bahia Banderas'), ('America/Boise', 'GMT-07:00 America/Boise'), ('America/Chihuahua', 'GMT-07:00 America/Chihuahua'), ('America/Creston', 'GMT-07:00 America/Creston'), ('America/Dawson_Creek', 'GMT-07:00 America/Dawson Creek'), ('America/Denver', 'GMT-07:00 America/Denver'), ('America/Edmonton', 'GMT-07:00 America/Edmonton'), ('America/Hermosillo', 'GMT-07:00 America/Hermosillo'), ('America/Inuvik', 'GMT-07:00 America/Inuvik'), ('America/Mazatlan', 'GMT-07:00 America/Mazatlan'), ('America/North_Dakota/Beulah', 'GMT-07:00 America/North Dakota/Beulah'), ('America/North_Dakota/New_Salem', 'GMT-07:00 America/North Dakota/New Salem'), ('America/Ojinaga', 'GMT-07:00 America/Ojinaga'), ('America/Phoenix', 'GMT-07:00 America/Phoenix'), ('America/Yellowknife', 'GMT-07:00 America/Yellowknife'), ('Canada/Mountain', 'GMT-07:00 Canada/Mountain'), ('US/Arizona', 'GMT-07:00 US/Arizona'), ('US/Mountain', 'GMT-07:00 US/Mountain'), ('America/Belize', 'GMT-06:00 America/Belize'), ('America/Cambridge_Bay', 'GMT-06:00 America/Cambridge Bay'), ('America/Cancun', 'GMT-06:00 America/Cancun'), ('America/Chicago', 'GMT-06:00 America/Chicago'), ('America/Costa_Rica', 'GMT-06:00 America/Costa Rica'), ('America/El_Salvador', 'GMT-06:00 America/El Salvador'), ('America/Guatemala', 'GMT-06:00 America/Guatemala'), ('America/Iqaluit', 'GMT-06:00 America/Iqaluit'), ('America/Kentucky/Monticello', 'GMT-06:00 America/Kentucky/Monticello'), ('America/Managua', 'GMT-06:00 America/Managua'), ('America/Matamoros', 'GMT-06:00 America/Matamoros'), ('America/Menominee', 'GMT-06:00 America/Menominee'), ('America/Merida', 'GMT-06:00 America/Merida'), ('America/Mexico_City', 'GMT-06:00 America/Mexico City'), ('America/Monterrey', 'GMT-06:00 America/Monterrey'), ('America/North_Dakota/Center', 'GMT-06:00 America/North Dakota/Center'), ('America/Pangnirtung', 'GMT-06:00 America/Pangnirtung'), ('America/Rainy_River', 'GMT-06:00 America/Rainy River'), ('America/Rankin_Inlet', 'GMT-06:00 America/Rankin Inlet'), ('America/Regina', 'GMT-06:00 America/Regina'), ('America/Resolute', 'GMT-06:00 America/Resolute'), ('America/Swift_Current', 'GMT-06:00 America/Swift Current'), ('America/Tegucigalpa', 'GMT-06:00 America/Tegucigalpa'), ('America/Winnipeg', 'GMT-06:00 America/Winnipeg'), ('Canada/Central', 'GMT-06:00 Canada/Central'), ('Pacific/Galapagos', 'GMT-06:00 Pacific/Galapagos'), ('US/Central', 'GMT-06:00 US/Central'), ('America/Atikokan', 'GMT-05:00 America/Atikokan'), ('America/Bogota', 'GMT-05:00 America/Bogota'), ('America/Cayman', 'GMT-05:00 America/Cayman'), ('America/Detroit', 'GMT-05:00 America/Detroit'), ('America/Eirunepe', 'GMT-05:00 America/Eirunepe'), ('America/Grand_Turk', 'GMT-05:00 America/Grand Turk'), ('America/Guayaquil', 'GMT-05:00 America/Guayaquil'), ('America/Havana', 'GMT-05:00 America/Havana'), ('America/Indiana/Indianapolis', 'GMT-05:00 America/Indiana/Indianapolis'), ('America/Indiana/Knox', 'GMT-05:00 America/Indiana/Knox'), ('America/Indiana/Marengo', 'GMT-05:00 America/Indiana/Marengo'), ('America/Indiana/Petersburg', 'GMT-05:00 America/Indiana/Petersburg'), ('America/Indiana/Tell_City', 'GMT-05:00 America/Indiana/Tell City'), ('America/Indiana/Vevay', 'GMT-05:00 America/Indiana/Vevay'), ('America/Indiana/Vincennes', 'GMT-05:00 America/Indiana/Vincennes'), ('America/Indiana/Winamac', 'GMT-05:00 America/Indiana/Winamac'), ('America/Jamaica', 'GMT-05:00 America/Jamaica'), ('America/Kentucky/Louisville', 'GMT-05:00 America/Kentucky/Louisville'), ('America/Lima', 'GMT-05:00 America/Lima'), ('America/Nassau', 'GMT-05:00 America/Nassau'), ('America/New_York', 'GMT-05:00 America/New York'), ('America/Nipigon', 'GMT-05:00 America/Nipigon'), ('America/Panama', 'GMT-05:00 America/Panama'), ('America/Port-au-Prince', 'GMT-05:00 America/Port-au-Prince'), ('America/Rio_Branco', 'GMT-05:00 America/Rio Branco'), ('America/Thunder_Bay', 'GMT-05:00 America/Thunder Bay'), ('America/Toronto', 'GMT-05:00 America/Toronto'), ('Canada/Eastern', 'GMT-05:00 Canada/Eastern'), ('Pacific/Easter', 'GMT-05:00 Pacific/Easter'), ('US/Eastern', 'GMT-05:00 US/Eastern'), ('America/Anguilla', 'GMT-04:00 America/Anguilla'), ('America/Antigua', 'GMT-04:00 America/Antigua'), ('America/Aruba', 'GMT-04:00 America/Aruba'), ('America/Barbados', 'GMT-04:00 America/Barbados'), ('America/Blanc-Sablon', 'GMT-04:00 America/Blanc-Sablon'), ('America/Caracas', 'GMT-04:00 America/Caracas'), ('America/Curacao', 'GMT-04:00 America/Curacao'), ('America/Dominica', 'GMT-04:00 America/Dominica'), ('America/Glace_Bay', 'GMT-04:00 America/Glace Bay'), ('America/Goose_Bay', 'GMT-04:00 America/Goose Bay'), ('America/Grenada', 'GMT-04:00 America/Grenada'), ('America/Guadeloupe', 'GMT-04:00 America/Guadeloupe'), ('America/Guyana', 'GMT-04:00 America/Guyana'), ('America/Halifax', 'GMT-04:00 America/Halifax'), ('America/Kralendijk', 'GMT-04:00 America/Kralendijk'), ('America/La_Paz', 'GMT-04:00 America/La Paz'), ('America/Lower_Princes', 'GMT-04:00 America/Lower Princes'), ('America/Manaus', 'GMT-04:00 America/Manaus'), ('America/Marigot', 'GMT-04:00 America/Marigot'), ('America/Martinique', 'GMT-04:00 America/Martinique'), ('America/Moncton', 'GMT-04:00 America/Moncton'), ('America/Montserrat', 'GMT-04:00 America/Montserrat'), ('America/Port_of_Spain', 'GMT-04:00 America/Port of Spain'), ('America/Porto_Velho', 'GMT-04:00 America/Porto Velho'), ('America/Puerto_Rico', 'GMT-04:00 America/Puerto Rico'), ('America/Santarem', 'GMT-04:00 America/Santarem'), ('America/Santo_Domingo', 'GMT-04:00 America/Santo Domingo'), ('America/St_Barthelemy', 'GMT-04:00 America/St Barthelemy'), ('America/St_Kitts', 'GMT-04:00 America/St Kitts'), ('America/St_Lucia', 'GMT-04:00 America/St Lucia'), ('America/St_Thomas', 'GMT-04:00 America/St Thomas'), ('America/St_Vincent', 'GMT-04:00 America/St Vincent'), ('America/Thule', 'GMT-04:00 America/Thule'), ('America/Tortola', 'GMT-04:00 America/Tortola'), ('Atlantic/Bermuda', 'GMT-04:00 Atlantic/Bermuda'), ('Canada/Atlantic', 'GMT-04:00 Canada/Atlantic'), ('America/St_Johns', 'GMT-03:00 America/St Johns'), ('Canada/Newfoundland', 'GMT-03:00 Canada/Newfoundland'), ('America/Argentina/Buenos_Aires', 'GMT-03:00 America/Argentina/Buenos Aires'), ('America/Argentina/Catamarca', 'GMT-03:00 America/Argentina/Catamarca'), ('America/Argentina/Cordoba', 'GMT-03:00 America/Argentina/Cordoba'), ('America/Argentina/Jujuy', 'GMT-03:00 America/Argentina/Jujuy'), ('America/Argentina/La_Rioja', 'GMT-03:00 America/Argentina/La Rioja'), ('America/Argentina/Mendoza', 'GMT-03:00 America/Argentina/Mendoza'), ('America/Argentina/Rio_Gallegos', 'GMT-03:00 America/Argentina/Rio Gallegos'), ('America/Argentina/Salta', 'GMT-03:00 America/Argentina/Salta'), ('America/Argentina/San_Juan', 'GMT-03:00 America/Argentina/San Juan'), ('America/Argentina/San_Luis', 'GMT-03:00 America/Argentina/San Luis'), ('America/Argentina/Tucuman', 'GMT-03:00 America/Argentina/Tucuman'), ('America/Argentina/Ushuaia', 'GMT-03:00 America/Argentina/Ushuaia'), ('America/Asuncion', 'GMT-03:00 America/Asuncion'), ('America/Belem', 'GMT-03:00 America/Belem'), ('America/Boa_Vista', 'GMT-03:00 America/Boa Vista'), ('America/Campo_Grande', 'GMT-03:00 America/Campo Grande'), ('America/Cayenne', 'GMT-03:00 America/Cayenne'), ('America/Cuiaba', 'GMT-03:00 America/Cuiaba'), ('America/Godthab', 'GMT-03:00 America/Godthab'), ('America/Miquelon', 'GMT-03:00 America/Miquelon'), ('America/Montevideo', 'GMT-03:00 America/Montevideo'), ('America/Paramaribo', 'GMT-03:00 America/Paramaribo'), ('America/Punta_Arenas', 'GMT-03:00 America/Punta Arenas'), ('America/Santiago', 'GMT-03:00 America/Santiago'), ('Antarctica/Palmer', 'GMT-03:00 Antarctica/Palmer'), ('Antarctica/Rothera', 'GMT-03:00 Antarctica/Rothera'), ('Atlantic/Stanley', 'GMT-03:00 Atlantic/Stanley'), ('America/Araguaina', 'GMT-02:00 America/Araguaina'), ('America/Bahia', 'GMT-02:00 America/Bahia'), ('America/Fortaleza', 'GMT-02:00 America/Fortaleza'), ('America/Maceio', 'GMT-02:00 America/Maceio'), ('America/Recife', 'GMT-02:00 America/Recife'), ('America/Sao_Paulo', 'GMT-02:00 America/Sao Paulo'), ('Atlantic/South_Georgia', 'GMT-02:00 Atlantic/South Georgia'), ('America/Noronha', 'GMT-01:00 America/Noronha'), ('America/Scoresbysund', 'GMT-01:00 America/Scoresbysund'), ('Atlantic/Azores', 'GMT-01:00 Atlantic/Azores'), ('Atlantic/Cape_Verde', 'GMT-01:00 Atlantic/Cape Verde'), ('Africa/Abidjan', 'GMT+00:00 Africa/Abidjan'), ('Africa/Accra', 'GMT+00:00 Africa/Accra'), ('Africa/Bamako', 'GMT+00:00 Africa/Bamako'), ('Africa/Banjul', 'GMT+00:00 Africa/Banjul'), ('Africa/Bissau', 'GMT+00:00 Africa/Bissau'), ('Africa/Casablanca', 'GMT+00:00 Africa/Casablanca'), ('Africa/Conakry', 'GMT+00:00 Africa/Conakry'), ('Africa/Dakar', 'GMT+00:00 Africa/Dakar'), ('Africa/El_Aaiun', 'GMT+00:00 Africa/El Aaiun'), ('Africa/Freetown', 'GMT+00:00 Africa/Freetown'), ('Africa/Lome', 'GMT+00:00 Africa/Lome'), ('Africa/Monrovia', 'GMT+00:00 Africa/Monrovia'), ('Africa/Nouakchott', 'GMT+00:00 Africa/Nouakchott'), ('Africa/Ouagadougou', 'GMT+00:00 Africa/Ouagadougou'), ('Africa/Sao_Tome', 'GMT+00:00 Africa/Sao Tome'), ('America/Danmarkshavn', 'GMT+00:00 America/Danmarkshavn'), ('Antarctica/Troll', 'GMT+00:00 Antarctica/Troll'), ('Atlantic/Canary', 'GMT+00:00 Atlantic/Canary'), ('Atlantic/Faroe', 'GMT+00:00 Atlantic/Faroe'), ('Atlantic/Madeira', 'GMT+00:00 Atlantic/Madeira'), ('Atlantic/Reykjavik', 'GMT+00:00 Atlantic/Reykjavik'), ('Atlantic/St_Helena', 'GMT+00:00 Atlantic/St Helena'), ('Europe/Dublin', 'GMT+00:00 Europe/Dublin'), ('Europe/Guernsey', 'GMT+00:00 Europe/Guernsey'), ('Europe/Isle_of_Man', 'GMT+00:00 Europe/Isle of Man'), ('Europe/Jersey', 'GMT+00:00 Europe/Jersey'), ('Europe/Lisbon', 'GMT+00:00 Europe/Lisbon'), ('Europe/London', 'GMT+00:00 Europe/London'), ('GMT', 'GMT+00:00 GMT'), ('UTC', 'GMT+00:00 UTC'), ('Africa/Algiers', 'GMT+01:00 Africa/Algiers'), ('Africa/Bangui', 'GMT+01:00 Africa/Bangui'), ('Africa/Brazzaville', 'GMT+01:00 Africa/Brazzaville'), ('Africa/Ceuta', 'GMT+01:00 Africa/Ceuta'), ('Africa/Douala', 'GMT+01:00 Africa/Douala'), ('Africa/Kinshasa', 'GMT+01:00 Africa/Kinshasa'), ('Africa/Lagos', 'GMT+01:00 Africa/Lagos'), ('Africa/Libreville', 'GMT+01:00 Africa/Libreville'), ('Africa/Luanda', 'GMT+01:00 Africa/Luanda'), ('Africa/Malabo', 'GMT+01:00 Africa/Malabo'), ('Africa/Ndjamena', 'GMT+01:00 Africa/Ndjamena'), ('Africa/Niamey', 'GMT+01:00 Africa/Niamey'), ('Africa/Porto-Novo', 'GMT+01:00 Africa/Porto-Novo'), ('Africa/Tunis', 'GMT+01:00 Africa/Tunis'), ('Arctic/Longyearbyen', 'GMT+01:00 Arctic/Longyearbyen'), ('Europe/Amsterdam', 'GMT+01:00 Europe/Amsterdam'), ('Europe/Andorra', 'GMT+01:00 Europe/Andorra'), ('Europe/Belgrade', 'GMT+01:00 Europe/Belgrade'), ('Europe/Berlin', 'GMT+01:00 Europe/Berlin'), ('Europe/Bratislava', 'GMT+01:00 Europe/Bratislava'), ('Europe/Brussels', 'GMT+01:00 Europe/Brussels'), ('Europe/Budapest', 'GMT+01:00 Europe/Budapest'), ('Europe/Busingen', 'GMT+01:00 Europe/Busingen'), ('Europe/Copenhagen', 'GMT+01:00 Europe/Copenhagen'), ('Europe/Gibraltar', 'GMT+01:00 Europe/Gibraltar'), ('Europe/Ljubljana', 'GMT+01:00 Europe/Ljubljana'), ('Europe/Luxembourg', 'GMT+01:00 Europe/Luxembourg'), ('Europe/Madrid', 'GMT+01:00 Europe/Madrid'), ('Europe/Malta', 'GMT+01:00 Europe/Malta'), ('Europe/Monaco', 'GMT+01:00 Europe/Monaco'), ('Europe/Oslo', 'GMT+01:00 Europe/Oslo'), ('Europe/Paris', 'GMT+01:00 Europe/Paris'), ('Europe/Podgorica', 'GMT+01:00 Europe/Podgorica'), ('Europe/Prague', 'GMT+01:00 Europe/Prague'), ('Europe/Rome', 'GMT+01:00 Europe/Rome'), ('Europe/San_Marino', 'GMT+01:00 Europe/San Marino'), ('Europe/Sarajevo', 'GMT+01:00 Europe/Sarajevo'), ('Europe/Skopje', 'GMT+01:00 Europe/Skopje'), ('Europe/Stockholm', 'GMT+01:00 Europe/Stockholm'), ('Europe/Tirane', 'GMT+01:00 Europe/Tirane'), ('Europe/Vaduz', 'GMT+01:00 Europe/Vaduz'), ('Europe/Vatican', 'GMT+01:00 Europe/Vatican'), ('Europe/Vienna', 'GMT+01:00 Europe/Vienna'), ('Europe/Warsaw', 'GMT+01:00 Europe/Warsaw'), ('Europe/Zagreb', 'GMT+01:00 Europe/Zagreb'), ('Europe/Zurich', 'GMT+01:00 Europe/Zurich'), ('Africa/Blantyre', 'GMT+02:00 Africa/Blantyre'), ('Africa/Bujumbura', 'GMT+02:00 Africa/Bujumbura'), ('Africa/Cairo', 'GMT+02:00 Africa/Cairo'), ('Africa/Gaborone', 'GMT+02:00 Africa/Gaborone'), ('Africa/Harare', 'GMT+02:00 Africa/Harare'), ('Africa/Johannesburg', 'GMT+02:00 Africa/Johannesburg'), ('Africa/Juba', 'GMT+02:00 Africa/Juba'), ('Africa/Khartoum', 'GMT+02:00 Africa/Khartoum'), ('Africa/Kigali', 'GMT+02:00 Africa/Kigali'), ('Africa/Lubumbashi', 'GMT+02:00 Africa/Lubumbashi'), ('Africa/Lusaka', 'GMT+02:00 Africa/Lusaka'), ('Africa/Maputo', 'GMT+02:00 Africa/Maputo'), ('Africa/Maseru', 'GMT+02:00 Africa/Maseru'), ('Africa/Mbabane', 'GMT+02:00 Africa/Mbabane'), ('Africa/Tripoli', 'GMT+02:00 Africa/Tripoli'), ('Africa/Windhoek', 'GMT+02:00 Africa/Windhoek'), ('Asia/Amman', 'GMT+02:00 Asia/Amman'), ('Asia/Beirut', 'GMT+02:00 Asia/Beirut'), ('Asia/Damascus', 'GMT+02:00 Asia/Damascus'), ('Asia/Famagusta', 'GMT+02:00 Asia/Famagusta'), ('Asia/Gaza', 'GMT+02:00 Asia/Gaza'), ('Asia/Hebron', 'GMT+02:00 Asia/Hebron'), ('Asia/Jerusalem', 'GMT+02:00 Asia/Jerusalem'), ('Asia/Nicosia', 'GMT+02:00 Asia/Nicosia'), ('Europe/Athens', 'GMT+02:00 Europe/Athens'), ('Europe/Bucharest', 'GMT+02:00 Europe/Bucharest'), ('Europe/Chisinau', 'GMT+02:00 Europe/Chisinau'), ('Europe/Helsinki', 'GMT+02:00 Europe/Helsinki'), ('Europe/Istanbul', 'GMT+02:00 Europe/Istanbul'), ('Europe/Kaliningrad', 'GMT+02:00 Europe/Kaliningrad'), ('Europe/Kiev', 'GMT+02:00 Europe/Kiev'), ('Europe/Mariehamn', 'GMT+02:00 Europe/Mariehamn'), ('Europe/Minsk', 'GMT+02:00 Europe/Minsk'), ('Europe/Riga', 'GMT+02:00 Europe/Riga'), ('Europe/Simferopol', 'GMT+02:00 Europe/Simferopol'), ('Europe/Sofia', 'GMT+02:00 Europe/Sofia'), ('Europe/Tallinn', 'GMT+02:00 Europe/Tallinn'), ('Europe/Uzhgorod', 'GMT+02:00 Europe/Uzhgorod'), ('Europe/Vilnius', 'GMT+02:00 Europe/Vilnius'), ('Europe/Zaporozhye', 'GMT+02:00 Europe/Zaporozhye'), ('Africa/Addis_Ababa', 'GMT+03:00 Africa/Addis Ababa'), ('Africa/Asmara', 'GMT+03:00 Africa/Asmara'), ('Africa/Dar_es_Salaam', 'GMT+03:00 Africa/Dar es Salaam'), ('Africa/Djibouti', 'GMT+03:00 Africa/Djibouti'), ('Africa/Kampala', 'GMT+03:00 Africa/Kampala'), ('Africa/Mogadishu', 'GMT+03:00 Africa/Mogadishu'), ('Africa/Nairobi', 'GMT+03:00 Africa/Nairobi'), ('Antarctica/Syowa', 'GMT+03:00 Antarctica/Syowa'), ('Asia/Aden', 'GMT+03:00 Asia/Aden'), ('Asia/Baghdad', 'GMT+03:00 Asia/Baghdad'), ('Asia/Bahrain', 'GMT+03:00 Asia/Bahrain'), ('Asia/Kuwait', 'GMT+03:00 Asia/Kuwait'), ('Asia/Qatar', 'GMT+03:00 Asia/Qatar'), ('Asia/Riyadh', 'GMT+03:00 Asia/Riyadh'), ('Europe/Astrakhan', 'GMT+03:00 Europe/Astrakhan'), ('Europe/Kirov', 'GMT+03:00 Europe/Kirov'), ('Europe/Moscow', 'GMT+03:00 Europe/Moscow'), ('Europe/Saratov', 'GMT+03:00 Europe/Saratov'), ('Europe/Ulyanovsk', 'GMT+03:00 Europe/Ulyanovsk'), ('Europe/Volgograd', 'GMT+03:00 Europe/Volgograd'), ('Indian/Antananarivo', 'GMT+03:00 Indian/Antananarivo'), ('Indian/Comoro', 'GMT+03:00 Indian/Comoro'), ('Indian/Mayotte', 'GMT+03:00 Indian/Mayotte'), ('Asia/Tehran', 'GMT+03:00 Asia/Tehran'), ('Asia/Aqtau', 'GMT+04:00 Asia/Aqtau'), ('Asia/Atyrau', 'GMT+04:00 Asia/Atyrau'), ('Asia/Baku', 'GMT+04:00 Asia/Baku'), ('Asia/Dubai', 'GMT+04:00 Asia/Dubai'), ('Asia/Muscat', 'GMT+04:00 Asia/Muscat'), ('Asia/Oral', 'GMT+04:00 Asia/Oral'), ('Asia/Tbilisi', 'GMT+04:00 Asia/Tbilisi'), ('Asia/Yerevan', 'GMT+04:00 Asia/Yerevan'), ('Europe/Samara', 'GMT+04:00 Europe/Samara'), ('Indian/Mahe', 'GMT+04:00 Indian/Mahe'), ('Indian/Mauritius', 'GMT+04:00 Indian/Mauritius'), ('Indian/Reunion', 'GMT+04:00 Indian/Reunion'), ('Asia/Kabul', 'GMT+04:00 Asia/Kabul'), ('Asia/Aqtobe', 'GMT+05:00 Asia/Aqtobe'), ('Asia/Ashgabat', 'GMT+05:00 Asia/Ashgabat'), ('Asia/Bishkek', 'GMT+05:00 Asia/Bishkek'), ('Asia/Dushanbe', 'GMT+05:00 Asia/Dushanbe'), ('Asia/Karachi', 'GMT+05:00 Asia/Karachi'), ('Asia/Qostanay', 'GMT+05:00 Asia/Qostanay'), ('Asia/Qyzylorda', 'GMT+05:00 Asia/Qyzylorda'), ('Asia/Samarkand', 'GMT+05:00 Asia/Samarkand'), ('Asia/Tashkent', 'GMT+05:00 Asia/Tashkent'), ('Asia/Yekaterinburg', 'GMT+05:00 Asia/Yekaterinburg'), ('Indian/Kerguelen', 'GMT+05:00 Indian/Kerguelen'), ('Indian/Maldives', 'GMT+05:00 Indian/Maldives'), ('Asia/Kolkata', 'GMT+05:00 Asia/Kolkata'), ('Asia/Kathmandu', 'GMT+05:00 Asia/Kathmandu'), ('Antarctica/Mawson', 'GMT+06:00 Antarctica/Mawson'), ('Antarctica/Vostok', 'GMT+06:00 Antarctica/Vostok'), ('Asia/Almaty', 'GMT+06:00 Asia/Almaty'), ('Asia/Barnaul', 'GMT+06:00 Asia/Barnaul'), ('Asia/Colombo', 'GMT+06:00 Asia/Colombo'), ('Asia/Dhaka', 'GMT+06:00 Asia/Dhaka'), ('Asia/Novosibirsk', 'GMT+06:00 Asia/Novosibirsk'), ('Asia/Omsk', 'GMT+06:00 Asia/Omsk'), ('Asia/Thimphu', 'GMT+06:00 Asia/Thimphu'), ('Asia/Urumqi', 'GMT+06:00 Asia/Urumqi'), ('Indian/Chagos', 'GMT+06:00 Indian/Chagos'), ('Asia/Yangon', 'GMT+06:00 Asia/Yangon'), ('Indian/Cocos', 'GMT+06:00 Indian/Cocos'), ('Antarctica/Davis', 'GMT+07:00 Antarctica/Davis'), ('Asia/Bangkok', 'GMT+07:00 Asia/Bangkok'), ('Asia/Ho_Chi_Minh', 'GMT+07:00 Asia/Ho Chi Minh'), ('Asia/Hovd', 'GMT+07:00 Asia/Hovd'), ('Asia/Jakarta', 'GMT+07:00 Asia/Jakarta'), ('Asia/Krasnoyarsk', 'GMT+07:00 Asia/Krasnoyarsk'), ('Asia/Novokuznetsk', 'GMT+07:00 Asia/Novokuznetsk'), ('Asia/Phnom_Penh', 'GMT+07:00 Asia/Phnom Penh'), ('Asia/Pontianak', 'GMT+07:00 Asia/Pontianak'), ('Asia/Tomsk', 'GMT+07:00 Asia/Tomsk'), ('Asia/Vientiane', 'GMT+07:00 Asia/Vientiane'), ('Indian/Christmas', 'GMT+07:00 Indian/Christmas'), ('Antarctica/Casey', 'GMT+08:00 Antarctica/Casey'), ('Asia/Brunei', 'GMT+08:00 Asia/Brunei'), ('Asia/Dili', 'GMT+08:00 Asia/Dili'), ('Asia/Hong_Kong', 'GMT+08:00 Asia/Hong Kong'), ('Asia/Irkutsk', 'GMT+08:00 Asia/Irkutsk'), ('Asia/Kuala_Lumpur', 'GMT+08:00 Asia/Kuala Lumpur'), ('Asia/Kuching', 'GMT+08:00 Asia/Kuching'), ('Asia/Macau', 'GMT+08:00 Asia/Macau'), ('Asia/Makassar', 'GMT+08:00 Asia/Makassar'), ('Asia/Manila', 'GMT+08:00 Asia/Manila'), ('Asia/Shanghai', 'GMT+08:00 Asia/Shanghai'), ('Asia/Singapore', 'GMT+08:00 Asia/Singapore'), ('Asia/Taipei', 'GMT+08:00 Asia/Taipei'), ('Asia/Ulaanbaatar', 'GMT+08:00 Asia/Ulaanbaatar'), ('Australia/Perth', 'GMT+08:00 Australia/Perth'), ('Australia/Eucla', 'GMT+08:00 Australia/Eucla'), ('Asia/Chita', 'GMT+09:00 Asia/Chita'), ('Asia/Choibalsan', 'GMT+09:00 Asia/Choibalsan'), ('Asia/Jayapura', 'GMT+09:00 Asia/Jayapura'), ('Asia/Khandyga', 'GMT+09:00 Asia/Khandyga'), ('Asia/Pyongyang', 'GMT+09:00 Asia/Pyongyang'), ('Asia/Seoul', 'GMT+09:00 Asia/Seoul'), ('Asia/Tokyo', 'GMT+09:00 Asia/Tokyo'), ('Asia/Yakutsk', 'GMT+09:00 Asia/Yakutsk'), ('Pacific/Palau', 'GMT+09:00 Pacific/Palau'), ('Australia/Darwin', 'GMT+09:00 Australia/Darwin'), ('Antarctica/DumontDUrville', 'GMT+10:00 Antarctica/DumontDUrville'), ('Asia/Sakhalin', 'GMT+10:00 Asia/Sakhalin'), ('Asia/Vladivostok', 'GMT+10:00 Asia/Vladivostok'), ('Australia/Brisbane', 'GMT+10:00 Australia/Brisbane'), ('Australia/Lindeman', 'GMT+10:00 Australia/Lindeman'), ('Pacific/Bougainville', 'GMT+10:00 Pacific/Bougainville'), ('Pacific/Chuuk', 'GMT+10:00 Pacific/Chuuk'), ('Pacific/Guam', 'GMT+10:00 Pacific/Guam'), ('Pacific/Port_Moresby', 'GMT+10:00 Pacific/Port Moresby'), ('Pacific/Saipan', 'GMT+10:00 Pacific/Saipan'), ('Australia/Adelaide', 'GMT+10:00 Australia/Adelaide'), ('Australia/Broken_Hill', 'GMT+10:00 Australia/Broken Hill'), ('Antarctica/Macquarie', 'GMT+11:00 Antarctica/Macquarie'), ('Asia/Magadan', 'GMT+11:00 Asia/Magadan'), ('Asia/Srednekolymsk', 'GMT+11:00 Asia/Srednekolymsk'), ('Asia/Ust-Nera', 'GMT+11:00 Asia/Ust-Nera'), ('Australia/Currie', 'GMT+11:00 Australia/Currie'), ('Australia/Hobart', 'GMT+11:00 Australia/Hobart'), ('Australia/Lord_Howe', 'GMT+11:00 Australia/Lord Howe'), ('Australia/Melbourne', 'GMT+11:00 Australia/Melbourne'), ('Australia/Sydney', 'GMT+11:00 Australia/Sydney'), ('Pacific/Efate', 'GMT+11:00 Pacific/Efate'), ('Pacific/Guadalcanal', 'GMT+11:00 Pacific/Guadalcanal'), ('Pacific/Kosrae', 'GMT+11:00 Pacific/Kosrae'), ('Pacific/Noumea', 'GMT+11:00 Pacific/Noumea'), ('Pacific/Pohnpei', 'GMT+11:00 Pacific/Pohnpei'), ('Pacific/Norfolk', 'GMT+11:00 Pacific/Norfolk'), ('Asia/Anadyr', 'GMT+12:00 Asia/Anadyr'), ('Asia/Kamchatka', 'GMT+12:00 Asia/Kamchatka'), ('Pacific/Funafuti', 'GMT+12:00 Pacific/Funafuti'), ('Pacific/Kwajalein', 'GMT+12:00 Pacific/Kwajalein'), ('Pacific/Majuro', 'GMT+12:00 Pacific/Majuro'), ('Pacific/Nauru', 'GMT+12:00 Pacific/Nauru'), ('Pacific/Tarawa', 'GMT+12:00 Pacific/Tarawa'), ('Pacific/Wake', 'GMT+12:00 Pacific/Wake'), ('Pacific/Wallis', 'GMT+12:00 Pacific/Wallis'), ('Antarctica/McMurdo', 'GMT+13:00 Antarctica/McMurdo'), ('Pacific/Auckland', 'GMT+13:00 Pacific/Auckland'), ('Pacific/Enderbury', 'GMT+13:00 Pacific/Enderbury'), ('Pacific/Fiji', 'GMT+13:00 Pacific/Fiji'), ('Pacific/Chatham', 'GMT+13:00 Pacific/Chatham'), ('Pacific/Kiritimati', 'GMT+14:00 Pacific/Kiritimati'), ('Pacific/Tongatapu', 'GMT+14:00 Pacific/Tongatapu')], default='Europe/Berlin', help_text='Time Zone where this event takes place in', verbose_name='Time Zone'), + ), + ] diff --git a/AKModel/models.py b/AKModel/models.py index c6c2ffef..d60f04a7 100644 --- a/AKModel/models.py +++ b/AKModel/models.py @@ -5,6 +5,7 @@ import itertools from django.db import models from django.utils.text import slugify from django.utils.translation import gettext_lazy as _ +from timezone_field import TimeZoneField class Event(models.Model): @@ -14,15 +15,19 @@ class Event(models.Model): help_text=_('Name or iteration of the event')) slug = models.SlugField(max_length=32, unique=True, verbose_name=_('Short Form'), help_text=_('Short name of letters/numbers/dots/dashes/underscores used in URLs.')) - start = models.DateTimeField(verbose_name=_('Start'), help_text=_('Time the event begins')) - end = models.DateTimeField(verbose_name=_('End'), help_text=_('Time the event ends')) + place = models.CharField(max_length=128, blank=True, verbose_name=_('Place'), help_text=_('City etc. the event takes place in')) + timezone = TimeZoneField(default='Europe/Berlin', display_GMT_offset=True, blank=False, + verbose_name=_('Time Zone'), help_text=_('Time Zone where this event takes place in')) + start = models.DateTimeField(verbose_name=_('Start'), help_text=_('Time the event begins')) + end = models.DateTimeField(verbose_name=_('End'), help_text=_('Time the event ends')) + active = models.BooleanField(verbose_name=_('Active State'), help_text=_('Marks currently active events')) base_url = models.URLField(verbose_name=_("Base URL"), help_text=_("Prefix for wiki link construction"), blank=True) - default_slot = models.DecimalField(max_digits=4, decimal_places=2, default=2, verbose_name='Default Slot Length', - help_text='Default length in hours that is assumed for AKs in this event.') + default_slot = models.DecimalField(max_digits=4, decimal_places=2, default=2, verbose_name=_('Default Slot Length'), + help_text=_('Default length in hours that is assumed for AKs in this event.')) contact_email = models.EmailField(verbose_name=_("Contact email address"), blank=True, help_text=_( @@ -245,11 +250,15 @@ class Room(models.Model): ordering = ['building', 'name'] unique_together = [['name', 'building']] - def __str__(self): + @property + def title(self): if self.building: return f"{self.building} {self.name}" return self.name + def __str__(self): + return self.title + class AKSlot(models.Model): """ An AK Mapping matches an AK to a room during a certain time. diff --git a/AKPlanning/settings.py b/AKPlanning/settings.py index 4d10d860..17370e86 100644 --- a/AKPlanning/settings.py +++ b/AKPlanning/settings.py @@ -45,6 +45,7 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', 'bootstrap4', 'fontawesome', + 'timezone_field', ] MIDDLEWARE = [ diff --git a/requirements.txt b/requirements.txt index cdccac9c..43afb3eb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ Django==2.2.6 django-bootstrap4==1.0.1 django-fontawesome==1.0 django-split-settings==1.0.0 +django-timezone-field==4.0 -- GitLab From 704e142e46f16b7d11112fa84da1ed95fb31759a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@cs.tu-darmstadt.de> Date: Sun, 1 Mar 2020 17:55:13 +0100 Subject: [PATCH 02/15] Use event timezones where possible Adapt admin views Adapt rendering of times of AK slots for backend and frontend --- AKModel/admin.py | 37 ++++++++++++++++++++++++++++++++++--- AKModel/models.py | 2 +- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/AKModel/admin.py b/AKModel/admin.py index 51db59e7..8d60bc7e 100644 --- a/AKModel/admin.py +++ b/AKModel/admin.py @@ -2,12 +2,23 @@ from django.contrib import admin from django.contrib.admin import SimpleListFilter from django.db.models import Count, F from django.shortcuts import render +from django.utils import timezone from django.utils.translation import gettext_lazy as _ from AKModel.availability import Availability from AKModel.models import Event, AKOwner, AKCategory, AKTrack, AKTag, AKRequirement, AK, Room, AKSlot -admin.site.register(Event) + +@admin.register(Event) +class EventAdmin(admin.ModelAdmin): + def get_form(self, request, obj=None, change=False, **kwargs): + # Use timezone of event + if obj is not None and obj.timezone: + timezone.activate(obj.timezone) + # No timezone available? Use UTC + else: + timezone.activate("UTC") + return super().get_form(request, obj, change, **kwargs) admin.site.register(AKOwner) @@ -60,6 +71,26 @@ admin.site.register(AK, AKAdmin) admin.site.register(Room) -admin.site.register(AKSlot) -admin.site.register(Availability) +@admin.register(AKSlot) +class AKSlotAdmin(admin.ModelAdmin): + def get_form(self, request, obj=None, change=False, **kwargs): + # Use timezone of associated event + if obj is not None and obj.event.timezone: + timezone.activate(obj.event.timezone) + # No timezone available? Use UTC + else: + timezone.activate("UTC") + return super().get_form(request, obj, change, **kwargs) + + +@admin.register(Availability) +class AvailabilityAdmin(admin.ModelAdmin): + def get_form(self, request, obj=None, change=False, **kwargs): + # Use timezone of associated event + if obj is not None and obj.event.timezone: + timezone.activate(obj.event.timezone) + # No timezone available? Use UTC + else: + timezone.activate("UTC") + return super().get_form(request, obj, change, **kwargs) diff --git a/AKModel/models.py b/AKModel/models.py index d60f04a7..997e85e2 100644 --- a/AKModel/models.py +++ b/AKModel/models.py @@ -293,7 +293,7 @@ class AKSlot(models.Model): """ if self.start is None: return _("Not scheduled yet") - return self.start.strftime('%a %H:%M') + return self.start.astimezone(self.event.timezone).strftime('%a %H:%M') @property def end(self): -- GitLab From 1374140f903a1a41fa9fc4fe552ff763e57f7c21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@cs.tu-darmstadt.de> Date: Sun, 1 Mar 2020 17:58:31 +0100 Subject: [PATCH 03/15] Add fullcalendar --- .../AKPlan/fullcalendar/bootstrap/LICENSE.txt | 20 + .../AKPlan/fullcalendar/bootstrap/README.md | 8 + .../AKPlan/fullcalendar/bootstrap/main.css | 36 + .../AKPlan/fullcalendar/bootstrap/main.d.ts | 12 + .../AKPlan/fullcalendar/bootstrap/main.esm.js | 83 + .../AKPlan/fullcalendar/bootstrap/main.js | 91 + .../fullcalendar/bootstrap/main.min.css | 1 + .../AKPlan/fullcalendar/bootstrap/main.min.js | 6 + .../fullcalendar/bootstrap/package.json | 33 + .../AKPlan/fullcalendar/core/LICENSE.txt | 20 + .../static/AKPlan/fullcalendar/core/README.md | 8 + .../AKPlan/fullcalendar/core/locales-all.js | 1348 +++ .../fullcalendar/core/locales-all.min.js | 1 + .../AKPlan/fullcalendar/core/locales/af.js | 30 + .../AKPlan/fullcalendar/core/locales/ar-dz.js | 31 + .../AKPlan/fullcalendar/core/locales/ar-kw.js | 31 + .../AKPlan/fullcalendar/core/locales/ar-ly.js | 31 + .../AKPlan/fullcalendar/core/locales/ar-ma.js | 31 + .../AKPlan/fullcalendar/core/locales/ar-sa.js | 31 + .../AKPlan/fullcalendar/core/locales/ar-tn.js | 31 + .../AKPlan/fullcalendar/core/locales/ar.js | 31 + .../AKPlan/fullcalendar/core/locales/bg.js | 31 + .../AKPlan/fullcalendar/core/locales/bs.js | 32 + .../AKPlan/fullcalendar/core/locales/ca.js | 30 + .../AKPlan/fullcalendar/core/locales/cs.js | 32 + .../AKPlan/fullcalendar/core/locales/da.js | 30 + .../AKPlan/fullcalendar/core/locales/de.js | 33 + .../AKPlan/fullcalendar/core/locales/el.js | 30 + .../AKPlan/fullcalendar/core/locales/en-au.js | 17 + .../AKPlan/fullcalendar/core/locales/en-gb.js | 17 + .../AKPlan/fullcalendar/core/locales/en-nz.js | 17 + .../AKPlan/fullcalendar/core/locales/es-us.js | 30 + .../AKPlan/fullcalendar/core/locales/es.js | 30 + .../AKPlan/fullcalendar/core/locales/et.js | 32 + .../AKPlan/fullcalendar/core/locales/eu.js | 30 + .../AKPlan/fullcalendar/core/locales/fa.js | 33 + .../AKPlan/fullcalendar/core/locales/fi.js | 30 + .../AKPlan/fullcalendar/core/locales/fr-ca.js | 27 + .../AKPlan/fullcalendar/core/locales/fr-ch.js | 31 + .../AKPlan/fullcalendar/core/locales/fr.js | 31 + .../AKPlan/fullcalendar/core/locales/gl.js | 30 + .../AKPlan/fullcalendar/core/locales/he.js | 27 + .../AKPlan/fullcalendar/core/locales/hi.js | 32 + .../AKPlan/fullcalendar/core/locales/hr.js | 32 + .../AKPlan/fullcalendar/core/locales/hu.js | 30 + .../AKPlan/fullcalendar/core/locales/id.js | 30 + .../AKPlan/fullcalendar/core/locales/is.js | 30 + .../AKPlan/fullcalendar/core/locales/it.js | 32 + .../AKPlan/fullcalendar/core/locales/ja.js | 28 + .../AKPlan/fullcalendar/core/locales/ka.js | 32 + .../AKPlan/fullcalendar/core/locales/kk.js | 32 + .../AKPlan/fullcalendar/core/locales/ko.js | 26 + .../AKPlan/fullcalendar/core/locales/lb.js | 30 + .../AKPlan/fullcalendar/core/locales/lt.js | 30 + .../AKPlan/fullcalendar/core/locales/lv.js | 32 + .../AKPlan/fullcalendar/core/locales/mk.js | 28 + .../AKPlan/fullcalendar/core/locales/ms.js | 32 + .../AKPlan/fullcalendar/core/locales/nb.js | 30 + .../AKPlan/fullcalendar/core/locales/nl.js | 30 + .../AKPlan/fullcalendar/core/locales/nn.js | 30 + .../AKPlan/fullcalendar/core/locales/pl.js | 30 + .../AKPlan/fullcalendar/core/locales/pt-br.js | 28 + .../AKPlan/fullcalendar/core/locales/pt.js | 30 + .../AKPlan/fullcalendar/core/locales/ro.js | 32 + .../AKPlan/fullcalendar/core/locales/ru.js | 32 + .../AKPlan/fullcalendar/core/locales/sk.js | 32 + .../AKPlan/fullcalendar/core/locales/sl.js | 30 + .../AKPlan/fullcalendar/core/locales/sq.js | 32 + .../fullcalendar/core/locales/sr-cyrl.js | 32 + .../AKPlan/fullcalendar/core/locales/sr.js | 32 + .../AKPlan/fullcalendar/core/locales/sv.js | 30 + .../AKPlan/fullcalendar/core/locales/th.js | 25 + .../AKPlan/fullcalendar/core/locales/tr.js | 30 + .../AKPlan/fullcalendar/core/locales/uk.js | 32 + .../AKPlan/fullcalendar/core/locales/vi.js | 32 + .../AKPlan/fullcalendar/core/locales/zh-cn.js | 33 + .../AKPlan/fullcalendar/core/locales/zh-tw.js | 26 + .../static/AKPlan/fullcalendar/core/main.css | 1052 ++ .../static/AKPlan/fullcalendar/core/main.d.ts | 2730 ++++++ .../AKPlan/fullcalendar/core/main.esm.js | 8558 ++++++++++++++++ .../static/AKPlan/fullcalendar/core/main.js | 8717 +++++++++++++++++ .../AKPlan/fullcalendar/core/main.min.css | 1 + .../AKPlan/fullcalendar/core/main.min.js | 6 + .../AKPlan/fullcalendar/core/package.json | 30 + .../AKPlan/fullcalendar/daygrid/LICENSE.txt | 20 + .../AKPlan/fullcalendar/daygrid/README.md | 8 + .../AKPlan/fullcalendar/daygrid/main.css | 78 + .../AKPlan/fullcalendar/daygrid/main.d.ts | 310 + .../AKPlan/fullcalendar/daygrid/main.esm.js | 1627 +++ .../AKPlan/fullcalendar/daygrid/main.js | 1641 ++++ .../AKPlan/fullcalendar/daygrid/main.min.css | 1 + .../AKPlan/fullcalendar/daygrid/main.min.js | 6 + .../AKPlan/fullcalendar/daygrid/package.json | 33 + .../fullcalendar/google-calendar/LICENSE.txt | 20 + .../fullcalendar/google-calendar/README.md | 8 + .../fullcalendar/google-calendar/main.d.ts | 20 + .../fullcalendar/google-calendar/main.esm.js | 162 + .../fullcalendar/google-calendar/main.js | 170 + .../fullcalendar/google-calendar/main.min.js | 6 + .../fullcalendar/google-calendar/package.json | 33 + .../fullcalendar/interaction/LICENSE.txt | 20 + .../AKPlan/fullcalendar/interaction/README.md | 8 + .../AKPlan/fullcalendar/interaction/main.d.ts | 323 + .../fullcalendar/interaction/main.esm.js | 2132 ++++ .../AKPlan/fullcalendar/interaction/main.js | 2143 ++++ .../fullcalendar/interaction/main.min.js | 6 + .../fullcalendar/interaction/package.json | 33 + .../AKPlan/fullcalendar/list/LICENSE.txt | 20 + .../static/AKPlan/fullcalendar/list/README.md | 8 + .../static/AKPlan/fullcalendar/list/main.css | 118 + .../static/AKPlan/fullcalendar/list/main.d.ts | 33 + .../AKPlan/fullcalendar/list/main.esm.js | 335 + .../static/AKPlan/fullcalendar/list/main.js | 343 + .../AKPlan/fullcalendar/list/main.min.css | 1 + .../AKPlan/fullcalendar/list/main.min.js | 6 + .../AKPlan/fullcalendar/list/package.json | 33 + .../AKPlan/fullcalendar/luxon/LICENSE.txt | 20 + .../AKPlan/fullcalendar/luxon/README.md | 8 + .../AKPlan/fullcalendar/luxon/main.d.ts | 14 + .../AKPlan/fullcalendar/luxon/main.esm.js | 162 + .../static/AKPlan/fullcalendar/luxon/main.js | 170 + .../AKPlan/fullcalendar/luxon/main.min.js | 6 + .../AKPlan/fullcalendar/luxon/package.json | 34 + .../fullcalendar/moment-timezone/LICENSE.txt | 20 + .../fullcalendar/moment-timezone/README.md | 8 + .../fullcalendar/moment-timezone/main.d.ts | 11 + .../fullcalendar/moment-timezone/main.esm.js | 58 + .../fullcalendar/moment-timezone/main.js | 64 + .../fullcalendar/moment-timezone/main.min.js | 6 + .../fullcalendar/moment-timezone/package.json | 35 + .../AKPlan/fullcalendar/moment/LICENSE.txt | 20 + .../AKPlan/fullcalendar/moment/README.md | 8 + .../AKPlan/fullcalendar/moment/main.d.ts | 14 + .../AKPlan/fullcalendar/moment/main.esm.js | 102 + .../static/AKPlan/fullcalendar/moment/main.js | 110 + .../AKPlan/fullcalendar/moment/main.min.js | 6 + .../AKPlan/fullcalendar/moment/package.json | 34 + .../fullcalendar/resource-common/LICENSE.md | 18 + .../fullcalendar/resource-common/README.md | 8 + .../fullcalendar/resource-common/main.d.ts | 487 + .../fullcalendar/resource-common/main.esm.js | 1562 +++ .../fullcalendar/resource-common/main.js | 1582 +++ .../fullcalendar/resource-common/main.min.js | 6 + .../fullcalendar/resource-common/package.json | 33 + .../fullcalendar/resource-daygrid/LICENSE.md | 18 + .../fullcalendar/resource-daygrid/README.md | 8 + .../fullcalendar/resource-daygrid/main.d.ts | 59 + .../fullcalendar/resource-daygrid/main.esm.js | 203 + .../fullcalendar/resource-daygrid/main.js | 213 + .../fullcalendar/resource-daygrid/main.min.js | 6 + .../resource-daygrid/package.json | 37 + .../fullcalendar/resource-timegrid/LICENSE.md | 18 + .../fullcalendar/resource-timegrid/README.md | 8 + .../fullcalendar/resource-timegrid/main.d.ts | 62 + .../resource-timegrid/main.esm.js | 211 + .../fullcalendar/resource-timegrid/main.js | 220 + .../resource-timegrid/main.min.js | 6 + .../resource-timegrid/package.json | 38 + .../fullcalendar/resource-timeline/LICENSE.md | 18 + .../fullcalendar/resource-timeline/README.md | 8 + .../fullcalendar/resource-timeline/main.css | 125 + .../fullcalendar/resource-timeline/main.d.ts | 237 + .../resource-timeline/main.esm.js | 1026 ++ .../fullcalendar/resource-timeline/main.js | 1035 ++ .../resource-timeline/main.min.css | 1 + .../resource-timeline/main.min.js | 6 + .../resource-timeline/package.json | 37 + .../AKPlan/fullcalendar/rrule/LICENSE.txt | 20 + .../AKPlan/fullcalendar/rrule/README.md | 8 + .../AKPlan/fullcalendar/rrule/main.d.ts | 9 + .../AKPlan/fullcalendar/rrule/main.esm.js | 121 + .../static/AKPlan/fullcalendar/rrule/main.js | 128 + .../AKPlan/fullcalendar/rrule/main.min.js | 6 + .../AKPlan/fullcalendar/rrule/package.json | 34 + .../AKPlan/fullcalendar/timegrid/LICENSE.txt | 20 + .../AKPlan/fullcalendar/timegrid/README.md | 8 + .../AKPlan/fullcalendar/timegrid/main.css | 309 + .../AKPlan/fullcalendar/timegrid/main.d.ts | 220 + .../AKPlan/fullcalendar/timegrid/main.esm.js | 1345 +++ .../AKPlan/fullcalendar/timegrid/main.js | 1357 +++ .../AKPlan/fullcalendar/timegrid/main.min.css | 1 + .../AKPlan/fullcalendar/timegrid/main.min.js | 6 + .../AKPlan/fullcalendar/timegrid/package.json | 36 + .../AKPlan/fullcalendar/timeline/LICENSE.md | 18 + .../AKPlan/fullcalendar/timeline/README.md | 8 + .../AKPlan/fullcalendar/timeline/main.css | 351 + .../AKPlan/fullcalendar/timeline/main.d.ts | 353 + .../AKPlan/fullcalendar/timeline/main.esm.js | 1983 ++++ .../AKPlan/fullcalendar/timeline/main.js | 1996 ++++ .../AKPlan/fullcalendar/timeline/main.min.css | 1 + .../AKPlan/fullcalendar/timeline/main.min.js | 6 + .../AKPlan/fullcalendar/timeline/package.json | 33 + 192 files changed, 50960 insertions(+) create mode 100644 AKPlan/static/AKPlan/fullcalendar/bootstrap/LICENSE.txt create mode 100644 AKPlan/static/AKPlan/fullcalendar/bootstrap/README.md create mode 100644 AKPlan/static/AKPlan/fullcalendar/bootstrap/main.css create mode 100644 AKPlan/static/AKPlan/fullcalendar/bootstrap/main.d.ts create mode 100644 AKPlan/static/AKPlan/fullcalendar/bootstrap/main.esm.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/bootstrap/main.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/bootstrap/main.min.css create mode 100644 AKPlan/static/AKPlan/fullcalendar/bootstrap/main.min.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/bootstrap/package.json create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/LICENSE.txt create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/README.md create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales-all.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales-all.min.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/af.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/ar-dz.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/ar-kw.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/ar-ly.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/ar-ma.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/ar-sa.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/ar-tn.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/ar.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/bg.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/bs.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/ca.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/cs.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/da.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/de.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/el.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/en-au.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/en-gb.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/en-nz.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/es-us.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/es.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/et.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/eu.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/fa.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/fi.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/fr-ca.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/fr-ch.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/fr.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/gl.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/he.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/hi.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/hr.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/hu.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/id.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/is.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/it.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/ja.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/ka.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/kk.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/ko.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/lb.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/lt.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/lv.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/mk.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/ms.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/nb.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/nl.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/nn.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/pl.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/pt-br.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/pt.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/ro.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/ru.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/sk.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/sl.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/sq.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/sr-cyrl.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/sr.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/sv.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/th.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/tr.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/uk.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/vi.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/zh-cn.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/locales/zh-tw.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/main.css create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/main.d.ts create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/main.esm.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/main.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/main.min.css create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/main.min.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/core/package.json create mode 100644 AKPlan/static/AKPlan/fullcalendar/daygrid/LICENSE.txt create mode 100644 AKPlan/static/AKPlan/fullcalendar/daygrid/README.md create mode 100644 AKPlan/static/AKPlan/fullcalendar/daygrid/main.css create mode 100644 AKPlan/static/AKPlan/fullcalendar/daygrid/main.d.ts create mode 100644 AKPlan/static/AKPlan/fullcalendar/daygrid/main.esm.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/daygrid/main.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/daygrid/main.min.css create mode 100644 AKPlan/static/AKPlan/fullcalendar/daygrid/main.min.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/daygrid/package.json create mode 100644 AKPlan/static/AKPlan/fullcalendar/google-calendar/LICENSE.txt create mode 100644 AKPlan/static/AKPlan/fullcalendar/google-calendar/README.md create mode 100644 AKPlan/static/AKPlan/fullcalendar/google-calendar/main.d.ts create mode 100644 AKPlan/static/AKPlan/fullcalendar/google-calendar/main.esm.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/google-calendar/main.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/google-calendar/main.min.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/google-calendar/package.json create mode 100644 AKPlan/static/AKPlan/fullcalendar/interaction/LICENSE.txt create mode 100644 AKPlan/static/AKPlan/fullcalendar/interaction/README.md create mode 100644 AKPlan/static/AKPlan/fullcalendar/interaction/main.d.ts create mode 100644 AKPlan/static/AKPlan/fullcalendar/interaction/main.esm.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/interaction/main.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/interaction/main.min.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/interaction/package.json create mode 100644 AKPlan/static/AKPlan/fullcalendar/list/LICENSE.txt create mode 100644 AKPlan/static/AKPlan/fullcalendar/list/README.md create mode 100644 AKPlan/static/AKPlan/fullcalendar/list/main.css create mode 100644 AKPlan/static/AKPlan/fullcalendar/list/main.d.ts create mode 100644 AKPlan/static/AKPlan/fullcalendar/list/main.esm.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/list/main.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/list/main.min.css create mode 100644 AKPlan/static/AKPlan/fullcalendar/list/main.min.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/list/package.json create mode 100644 AKPlan/static/AKPlan/fullcalendar/luxon/LICENSE.txt create mode 100644 AKPlan/static/AKPlan/fullcalendar/luxon/README.md create mode 100644 AKPlan/static/AKPlan/fullcalendar/luxon/main.d.ts create mode 100644 AKPlan/static/AKPlan/fullcalendar/luxon/main.esm.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/luxon/main.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/luxon/main.min.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/luxon/package.json create mode 100644 AKPlan/static/AKPlan/fullcalendar/moment-timezone/LICENSE.txt create mode 100644 AKPlan/static/AKPlan/fullcalendar/moment-timezone/README.md create mode 100644 AKPlan/static/AKPlan/fullcalendar/moment-timezone/main.d.ts create mode 100644 AKPlan/static/AKPlan/fullcalendar/moment-timezone/main.esm.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/moment-timezone/main.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/moment-timezone/main.min.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/moment-timezone/package.json create mode 100644 AKPlan/static/AKPlan/fullcalendar/moment/LICENSE.txt create mode 100644 AKPlan/static/AKPlan/fullcalendar/moment/README.md create mode 100644 AKPlan/static/AKPlan/fullcalendar/moment/main.d.ts create mode 100644 AKPlan/static/AKPlan/fullcalendar/moment/main.esm.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/moment/main.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/moment/main.min.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/moment/package.json create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-common/LICENSE.md create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-common/README.md create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-common/main.d.ts create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-common/main.esm.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-common/main.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-common/main.min.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-common/package.json create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-daygrid/LICENSE.md create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-daygrid/README.md create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-daygrid/main.d.ts create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-daygrid/main.esm.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-daygrid/main.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-daygrid/main.min.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-daygrid/package.json create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-timegrid/LICENSE.md create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-timegrid/README.md create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-timegrid/main.d.ts create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-timegrid/main.esm.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-timegrid/main.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-timegrid/main.min.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-timegrid/package.json create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-timeline/LICENSE.md create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-timeline/README.md create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.css create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.d.ts create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.esm.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.min.css create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.min.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/resource-timeline/package.json create mode 100644 AKPlan/static/AKPlan/fullcalendar/rrule/LICENSE.txt create mode 100644 AKPlan/static/AKPlan/fullcalendar/rrule/README.md create mode 100644 AKPlan/static/AKPlan/fullcalendar/rrule/main.d.ts create mode 100644 AKPlan/static/AKPlan/fullcalendar/rrule/main.esm.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/rrule/main.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/rrule/main.min.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/rrule/package.json create mode 100644 AKPlan/static/AKPlan/fullcalendar/timegrid/LICENSE.txt create mode 100644 AKPlan/static/AKPlan/fullcalendar/timegrid/README.md create mode 100644 AKPlan/static/AKPlan/fullcalendar/timegrid/main.css create mode 100644 AKPlan/static/AKPlan/fullcalendar/timegrid/main.d.ts create mode 100644 AKPlan/static/AKPlan/fullcalendar/timegrid/main.esm.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/timegrid/main.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/timegrid/main.min.css create mode 100644 AKPlan/static/AKPlan/fullcalendar/timegrid/main.min.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/timegrid/package.json create mode 100644 AKPlan/static/AKPlan/fullcalendar/timeline/LICENSE.md create mode 100644 AKPlan/static/AKPlan/fullcalendar/timeline/README.md create mode 100644 AKPlan/static/AKPlan/fullcalendar/timeline/main.css create mode 100644 AKPlan/static/AKPlan/fullcalendar/timeline/main.d.ts create mode 100644 AKPlan/static/AKPlan/fullcalendar/timeline/main.esm.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/timeline/main.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/timeline/main.min.css create mode 100644 AKPlan/static/AKPlan/fullcalendar/timeline/main.min.js create mode 100644 AKPlan/static/AKPlan/fullcalendar/timeline/package.json diff --git a/AKPlan/static/AKPlan/fullcalendar/bootstrap/LICENSE.txt b/AKPlan/static/AKPlan/fullcalendar/bootstrap/LICENSE.txt new file mode 100644 index 00000000..2149cfbe --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/bootstrap/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2019 Adam Shaw + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/AKPlan/static/AKPlan/fullcalendar/bootstrap/README.md b/AKPlan/static/AKPlan/fullcalendar/bootstrap/README.md new file mode 100644 index 00000000..1da7990c --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/bootstrap/README.md @@ -0,0 +1,8 @@ + +# FullCalendar Bootstrap Plugin + +Bootstrap 4 theming for your calendar + +[View the docs »](https://fullcalendar.io/docs/bootstrap-theme) + +This package was created from the [FullCalendar monorepo »](https://github.com/fullcalendar/fullcalendar) diff --git a/AKPlan/static/AKPlan/fullcalendar/bootstrap/main.css b/AKPlan/static/AKPlan/fullcalendar/bootstrap/main.css new file mode 100644 index 00000000..3dc71f58 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/bootstrap/main.css @@ -0,0 +1,36 @@ +.fc.fc-bootstrap a { + text-decoration: none; +} + +.fc.fc-bootstrap a[data-goto]:hover { + text-decoration: underline; +} + +.fc-bootstrap hr.fc-divider { + border-color: inherit; +} + +.fc-bootstrap .fc-today.alert { + border-radius: 0; +} + +.fc-bootstrap a.fc-event:not([href]):not([tabindex]) { + color: #fff; +} + +.fc-bootstrap .fc-popover.card { + position: absolute; +} + +/* Popover +--------------------------------------------------------------------------------------------------*/ +.fc-bootstrap .fc-popover .card-body { + padding: 0; +} + +/* TimeGrid Slats (lines that run horizontally) +--------------------------------------------------------------------------------------------------*/ +.fc-bootstrap .fc-time-grid .fc-slats table { + /* some themes have background color. see through to slats */ + background: none; +} diff --git a/AKPlan/static/AKPlan/fullcalendar/bootstrap/main.d.ts b/AKPlan/static/AKPlan/fullcalendar/bootstrap/main.d.ts new file mode 100644 index 00000000..4aa91f33 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/bootstrap/main.d.ts @@ -0,0 +1,12 @@ +// Generated by dts-bundle v0.7.3-fork.1 +// Dependencies for this module: +// ../../../../../@fullcalendar/core + +declare module '@fullcalendar/bootstrap' { + import { Theme } from '@fullcalendar/core'; + export class BootstrapTheme extends Theme { + } + const _default: import("@fullcalendar/core").PluginDef; + export default _default; +} + diff --git a/AKPlan/static/AKPlan/fullcalendar/bootstrap/main.esm.js b/AKPlan/static/AKPlan/fullcalendar/bootstrap/main.esm.js new file mode 100644 index 00000000..8a02e1b2 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/bootstrap/main.esm.js @@ -0,0 +1,83 @@ +/*! +FullCalendar Bootstrap Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +import { createPlugin, Theme } from '@fullcalendar/core'; + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} + +var BootstrapTheme = /** @class */ (function (_super) { + __extends(BootstrapTheme, _super); + function BootstrapTheme() { + return _super !== null && _super.apply(this, arguments) || this; + } + return BootstrapTheme; +}(Theme)); +BootstrapTheme.prototype.classes = { + widget: 'fc-bootstrap', + tableGrid: 'table-bordered', + tableList: 'table', + tableListHeading: 'table-active', + buttonGroup: 'btn-group', + button: 'btn btn-primary', + buttonActive: 'active', + today: 'alert alert-info', + popover: 'card card-primary', + popoverHeader: 'card-header', + popoverContent: 'card-body', + // day grid + // for left/right border color when border is inset from edges (all-day in timeGrid view) + // avoid `table` class b/c don't want margins/padding/structure. only border color. + headerRow: 'table-bordered', + dayRow: 'table-bordered', + // list view + listView: 'card card-primary' +}; +BootstrapTheme.prototype.baseIconClass = 'fa'; +BootstrapTheme.prototype.iconClasses = { + close: 'fa-times', + prev: 'fa-chevron-left', + next: 'fa-chevron-right', + prevYear: 'fa-angle-double-left', + nextYear: 'fa-angle-double-right' +}; +BootstrapTheme.prototype.iconOverrideOption = 'bootstrapFontAwesome'; +BootstrapTheme.prototype.iconOverrideCustomButtonOption = 'bootstrapFontAwesome'; +BootstrapTheme.prototype.iconOverridePrefix = 'fa-'; +var main = createPlugin({ + themeClasses: { + bootstrap: BootstrapTheme + } +}); + +export default main; +export { BootstrapTheme }; diff --git a/AKPlan/static/AKPlan/fullcalendar/bootstrap/main.js b/AKPlan/static/AKPlan/fullcalendar/bootstrap/main.js new file mode 100644 index 00000000..b063deb8 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/bootstrap/main.js @@ -0,0 +1,91 @@ +/*! +FullCalendar Bootstrap Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) : + typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) : + (global = global || self, factory(global.FullCalendarBootstrap = {}, global.FullCalendar)); +}(this, function (exports, core) { 'use strict'; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + var BootstrapTheme = /** @class */ (function (_super) { + __extends(BootstrapTheme, _super); + function BootstrapTheme() { + return _super !== null && _super.apply(this, arguments) || this; + } + return BootstrapTheme; + }(core.Theme)); + BootstrapTheme.prototype.classes = { + widget: 'fc-bootstrap', + tableGrid: 'table-bordered', + tableList: 'table', + tableListHeading: 'table-active', + buttonGroup: 'btn-group', + button: 'btn btn-primary', + buttonActive: 'active', + today: 'alert alert-info', + popover: 'card card-primary', + popoverHeader: 'card-header', + popoverContent: 'card-body', + // day grid + // for left/right border color when border is inset from edges (all-day in timeGrid view) + // avoid `table` class b/c don't want margins/padding/structure. only border color. + headerRow: 'table-bordered', + dayRow: 'table-bordered', + // list view + listView: 'card card-primary' + }; + BootstrapTheme.prototype.baseIconClass = 'fa'; + BootstrapTheme.prototype.iconClasses = { + close: 'fa-times', + prev: 'fa-chevron-left', + next: 'fa-chevron-right', + prevYear: 'fa-angle-double-left', + nextYear: 'fa-angle-double-right' + }; + BootstrapTheme.prototype.iconOverrideOption = 'bootstrapFontAwesome'; + BootstrapTheme.prototype.iconOverrideCustomButtonOption = 'bootstrapFontAwesome'; + BootstrapTheme.prototype.iconOverridePrefix = 'fa-'; + var main = core.createPlugin({ + themeClasses: { + bootstrap: BootstrapTheme + } + }); + + exports.BootstrapTheme = BootstrapTheme; + exports.default = main; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/bootstrap/main.min.css b/AKPlan/static/AKPlan/fullcalendar/bootstrap/main.min.css new file mode 100644 index 00000000..e9249b56 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/bootstrap/main.min.css @@ -0,0 +1 @@ +.fc.fc-bootstrap a{text-decoration:none}.fc.fc-bootstrap a[data-goto]:hover{text-decoration:underline}.fc-bootstrap hr.fc-divider{border-color:inherit}.fc-bootstrap .fc-today.alert{border-radius:0}.fc-bootstrap a.fc-event:not([href]):not([tabindex]){color:#fff}.fc-bootstrap .fc-popover.card{position:absolute}.fc-bootstrap .fc-popover .card-body{padding:0}.fc-bootstrap .fc-time-grid .fc-slats table{background:0 0} \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/bootstrap/main.min.js b/AKPlan/static/AKPlan/fullcalendar/bootstrap/main.min.js new file mode 100644 index 00000000..107ed48b --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/bootstrap/main.min.js @@ -0,0 +1,6 @@ +/*! +FullCalendar Bootstrap Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@fullcalendar/core")):"function"==typeof define&&define.amd?define(["exports","@fullcalendar/core"],t):t((e=e||self).FullCalendarBootstrap={},e.FullCalendar)}(this,function(e,t){"use strict";var o=function(e,t){return(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var o in t)t.hasOwnProperty(o)&&(e[o]=t[o])})(e,t)};var r=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return function(e,t){function r(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}(t,e),t}(t.Theme);r.prototype.classes={widget:"fc-bootstrap",tableGrid:"table-bordered",tableList:"table",tableListHeading:"table-active",buttonGroup:"btn-group",button:"btn btn-primary",buttonActive:"active",today:"alert alert-info",popover:"card card-primary",popoverHeader:"card-header",popoverContent:"card-body",headerRow:"table-bordered",dayRow:"table-bordered",listView:"card card-primary"},r.prototype.baseIconClass="fa",r.prototype.iconClasses={close:"fa-times",prev:"fa-chevron-left",next:"fa-chevron-right",prevYear:"fa-angle-double-left",nextYear:"fa-angle-double-right"},r.prototype.iconOverrideOption="bootstrapFontAwesome",r.prototype.iconOverrideCustomButtonOption="bootstrapFontAwesome",r.prototype.iconOverridePrefix="fa-";var a=t.createPlugin({themeClasses:{bootstrap:r}});e.BootstrapTheme=r,e.default=a,Object.defineProperty(e,"__esModule",{value:!0})}); \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/bootstrap/package.json b/AKPlan/static/AKPlan/fullcalendar/bootstrap/package.json new file mode 100644 index 00000000..3f1845b5 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/bootstrap/package.json @@ -0,0 +1,33 @@ +{ + "name": "@fullcalendar/bootstrap", + "version": "4.3.0", + "title": "FullCalendar Bootstrap Plugin", + "description": "Bootstrap 4 theming for your calendar", + "keywords": [ + "calendar", + "event", + "full-sized" + ], + "homepage": "https://fullcalendar.io/", + "docs": "https://fullcalendar.io/docs/bootstrap-theme", + "bugs": "https://fullcalendar.io/reporting-bugs", + "repository": { + "type": "git", + "url": "https://github.com/fullcalendar/fullcalendar.git", + "homepage": "https://github.com/fullcalendar/fullcalendar" + }, + "license": "MIT", + "author": { + "name": "Adam Shaw", + "email": "arshaw@arshaw.com", + "url": "http://arshaw.com/" + }, + "copyright": "2019 Adam Shaw", + "peerDependencies": { + "@fullcalendar/core": "~4.3.0" + }, + "main": "main.js", + "module": "main.esm.js", + "unpkg": "main.min.js", + "types": "main.d.ts" +} diff --git a/AKPlan/static/AKPlan/fullcalendar/core/LICENSE.txt b/AKPlan/static/AKPlan/fullcalendar/core/LICENSE.txt new file mode 100644 index 00000000..2149cfbe --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2019 Adam Shaw + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/AKPlan/static/AKPlan/fullcalendar/core/README.md b/AKPlan/static/AKPlan/fullcalendar/core/README.md new file mode 100644 index 00000000..7ed36f44 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/README.md @@ -0,0 +1,8 @@ + +# FullCalendar Core Package + +Provides core functionality, including the Calendar class + +[View the docs »](https://fullcalendar.io/docs/initialize-es6) + +This package was created from the [FullCalendar monorepo »](https://github.com/fullcalendar/fullcalendar) diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales-all.js b/AKPlan/static/AKPlan/fullcalendar/core/locales-all.js new file mode 100644 index 00000000..5c7c9fa9 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales-all.js @@ -0,0 +1,1348 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, global.FullCalendarLocalesAll = factory()); +}(this, function () { 'use strict'; + + var _m0 = { + code: "af", + week: { + dow: 1, + doy: 4 // Die week wat die 4de Januarie bevat is die eerste week van die jaar. + }, + buttonText: { + prev: "Vorige", + next: "Volgende", + today: "Vandag", + year: "Jaar", + month: "Maand", + week: "Week", + day: "Dag", + list: "Agenda" + }, + allDayHtml: "Heeldag", + eventLimitText: "Addisionele", + noEventsMessage: "Daar is geen gebeurtenisse nie" + }; + + var _m1 = { + code: "ar-dz", + week: { + dow: 0, + doy: 4 // The week that contains Jan 1st is the first week of the year. + }, + dir: 'rtl', + buttonText: { + prev: "السابق", + next: "التالي", + today: "اليوم", + month: "شهر", + week: "أسبوع", + day: "يوم", + list: "أجندة" + }, + weekLabel: "أسبوع", + allDayText: "اليوم كله", + eventLimitText: "أخرى", + noEventsMessage: "أي Ø£Øداث لعرض" + }; + + var _m2 = { + code: "ar-kw", + week: { + dow: 0, + doy: 12 // The week that contains Jan 1st is the first week of the year. + }, + dir: 'rtl', + buttonText: { + prev: "السابق", + next: "التالي", + today: "اليوم", + month: "شهر", + week: "أسبوع", + day: "يوم", + list: "أجندة" + }, + weekLabel: "أسبوع", + allDayText: "اليوم كله", + eventLimitText: "أخرى", + noEventsMessage: "أي Ø£Øداث لعرض" + }; + + var _m3 = { + code: "ar-ly", + week: { + dow: 6, + doy: 12 // The week that contains Jan 1st is the first week of the year. + }, + dir: 'rtl', + buttonText: { + prev: "السابق", + next: "التالي", + today: "اليوم", + month: "شهر", + week: "أسبوع", + day: "يوم", + list: "أجندة" + }, + weekLabel: "أسبوع", + allDayText: "اليوم كله", + eventLimitText: "أخرى", + noEventsMessage: "أي Ø£Øداث لعرض" + }; + + var _m4 = { + code: "ar-ma", + week: { + dow: 6, + doy: 12 // The week that contains Jan 1st is the first week of the year. + }, + dir: 'rtl', + buttonText: { + prev: "السابق", + next: "التالي", + today: "اليوم", + month: "شهر", + week: "أسبوع", + day: "يوم", + list: "أجندة" + }, + weekLabel: "أسبوع", + allDayText: "اليوم كله", + eventLimitText: "أخرى", + noEventsMessage: "أي Ø£Øداث لعرض" + }; + + var _m5 = { + code: "ar-sa", + week: { + dow: 0, + doy: 6 // The week that contains Jan 1st is the first week of the year. + }, + dir: 'rtl', + buttonText: { + prev: "السابق", + next: "التالي", + today: "اليوم", + month: "شهر", + week: "أسبوع", + day: "يوم", + list: "أجندة" + }, + weekLabel: "أسبوع", + allDayText: "اليوم كله", + eventLimitText: "أخرى", + noEventsMessage: "أي Ø£Øداث لعرض" + }; + + var _m6 = { + code: "ar-tn", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + dir: 'rtl', + buttonText: { + prev: "السابق", + next: "التالي", + today: "اليوم", + month: "شهر", + week: "أسبوع", + day: "يوم", + list: "أجندة" + }, + weekLabel: "أسبوع", + allDayText: "اليوم كله", + eventLimitText: "أخرى", + noEventsMessage: "أي Ø£Øداث لعرض" + }; + + var _m7 = { + code: "ar", + week: { + dow: 6, + doy: 12 // The week that contains Jan 1st is the first week of the year. + }, + dir: 'rtl', + buttonText: { + prev: "السابق", + next: "التالي", + today: "اليوم", + month: "شهر", + week: "أسبوع", + day: "يوم", + list: "أجندة" + }, + weekLabel: "أسبوع", + allDayText: "اليوم كله", + eventLimitText: "أخرى", + noEventsMessage: "أي Ø£Øداث لعرض" + }; + + var _m8 = { + code: "bg", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "назад", + next: "напред", + today: "днеÑ", + month: "МеÑец", + week: "Седмица", + day: "Ден", + list: "График" + }, + allDayText: "ЦÑл ден", + eventLimitText: function (n) { + return "+още " + n; + }, + noEventsMessage: "ÐÑма ÑÑŠÐ±Ð¸Ñ‚Ð¸Ñ Ð·Ð° показване" + }; + + var _m9 = { + code: "bs", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "ProÅ¡li", + next: "Sljedeći", + today: "Danas", + month: "Mjesec", + week: "Sedmica", + day: "Dan", + list: "Raspored" + }, + weekLabel: "Sed", + allDayText: "Cijeli dan", + eventLimitText: function (n) { + return "+ joÅ¡ " + n; + }, + noEventsMessage: "Nema dogaÄ‘aja za prikazivanje" + }; + + var _m10 = { + code: "ca", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Anterior", + next: "Següent", + today: "Avui", + month: "Mes", + week: "Setmana", + day: "Dia", + list: "Agenda" + }, + weekLabel: "Set", + allDayText: "Tot el dia", + eventLimitText: "més", + noEventsMessage: "No hi ha esdeveniments per mostrar" + }; + + var _m11 = { + code: "cs", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "DÅ™Ãve", + next: "PozdÄ›ji", + today: "NynÃ", + month: "MÄ›sÃc", + week: "Týden", + day: "Den", + list: "Agenda" + }, + weekLabel: "Týd", + allDayText: "Celý den", + eventLimitText: function (n) { + return "+dalÅ¡Ã: " + n; + }, + noEventsMessage: "Žádné akce k zobrazenÃ" + }; + + var _m12 = { + code: "da", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Forrige", + next: "Næste", + today: "I dag", + month: "MÃ¥ned", + week: "Uge", + day: "Dag", + list: "Agenda" + }, + weekLabel: "Uge", + allDayText: "Hele dagen", + eventLimitText: "flere", + noEventsMessage: "Ingen arrangementer at vise" + }; + + var _m13 = { + code: "de", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Zurück", + next: "Vor", + today: "Heute", + year: "Jahr", + month: "Monat", + week: "Woche", + day: "Tag", + list: "Terminübersicht" + }, + weekLabel: "KW", + allDayText: "Ganztägig", + eventLimitText: function (n) { + return "+ weitere " + n; + }, + noEventsMessage: "Keine Ereignisse anzuzeigen" + }; + + var _m14 = { + code: "el", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4st is the first week of the year. + }, + buttonText: { + prev: "Î ÏοηγοÏμενος", + next: "Επόμενος", + today: "ΣήμεÏα", + month: "Μήνας", + week: "Εβδομάδα", + day: "ΗμÎÏα", + list: "ΑτζÎντα" + }, + weekLabel: "Εβδ", + allDayText: "ΟλοήμεÏο", + eventLimitText: "πεÏισσότεÏα", + noEventsMessage: "Δεν υπάÏχουν γεγονότα για να εμφανιστεί" + }; + + var _m15 = { + code: "en-au", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + } + }; + + var _m16 = { + code: "en-gb", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + } + }; + + var _m17 = { + code: "en-nz", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + } + }; + + var _m18 = { + code: "es", + week: { + dow: 0, + doy: 6 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "Ant", + next: "Sig", + today: "Hoy", + month: "Mes", + week: "Semana", + day: "DÃa", + list: "Agenda" + }, + weekLabel: "Sm", + allDayHtml: "Todo<br/>el dÃa", + eventLimitText: "más", + noEventsMessage: "No hay eventos para mostrar" + }; + + var _m19 = { + code: "es", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Ant", + next: "Sig", + today: "Hoy", + month: "Mes", + week: "Semana", + day: "DÃa", + list: "Agenda" + }, + weekLabel: "Sm", + allDayHtml: "Todo<br/>el dÃa", + eventLimitText: "más", + noEventsMessage: "No hay eventos para mostrar" + }; + + var _m20 = { + code: "et", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Eelnev", + next: "Järgnev", + today: "Täna", + month: "Kuu", + week: "Nädal", + day: "Päev", + list: "Päevakord" + }, + weekLabel: "näd", + allDayText: "Kogu päev", + eventLimitText: function (n) { + return "+ veel " + n; + }, + noEventsMessage: "Kuvamiseks puuduvad sündmused" + }; + + var _m21 = { + code: "eu", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "Aur", + next: "Hur", + today: "Gaur", + month: "Hilabetea", + week: "Astea", + day: "Eguna", + list: "Agenda" + }, + weekLabel: "As", + allDayHtml: "Egun<br/>osoa", + eventLimitText: "gehiago", + noEventsMessage: "Ez dago ekitaldirik erakusteko" + }; + + var _m22 = { + code: "fa", + week: { + dow: 6, + doy: 12 // The week that contains Jan 1st is the first week of the year. + }, + dir: 'rtl', + buttonText: { + prev: "قبلی", + next: "بعدی", + today: "امروز", + month: "ماه", + week: "Ù‡Ùته", + day: "روز", + list: "برنامه" + }, + weekLabel: "Ù‡Ù", + allDayText: "تمام روز", + eventLimitText: function (n) { + return "بیش از " + n; + }, + noEventsMessage: "هیچ رویدادی به نمایش" + }; + + var _m23 = { + code: "fi", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Edellinen", + next: "Seuraava", + today: "Tänään", + month: "Kuukausi", + week: "Viikko", + day: "Päivä", + list: "Tapahtumat" + }, + weekLabel: "Vk", + allDayText: "Koko päivä", + eventLimitText: "lisää", + noEventsMessage: "Ei näytettäviä tapahtumia" + }; + + var _m24 = { + code: "fr", + buttonText: { + prev: "Précédent", + next: "Suivant", + today: "Aujourd'hui", + year: "Année", + month: "Mois", + week: "Semaine", + day: "Jour", + list: "Mon planning" + }, + weekLabel: "Sem.", + allDayHtml: "Toute la<br/>journée", + eventLimitText: "en plus", + noEventsMessage: "Aucun événement à afficher" + }; + + var _m25 = { + code: "fr-ch", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Précédent", + next: "Suivant", + today: "Courant", + year: "Année", + month: "Mois", + week: "Semaine", + day: "Jour", + list: "Mon planning" + }, + weekLabel: "Sm", + allDayHtml: "Toute la<br/>journée", + eventLimitText: "en plus", + noEventsMessage: "Aucun événement à afficher" + }; + + var _m26 = { + code: "fr", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Précédent", + next: "Suivant", + today: "Aujourd'hui", + year: "Année", + month: "Mois", + week: "Semaine", + day: "Jour", + list: "Mon planning" + }, + weekLabel: "Sem.", + allDayHtml: "Toute la<br/>journée", + eventLimitText: "en plus", + noEventsMessage: "Aucun événement à afficher" + }; + + var _m27 = { + code: "gl", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Ant", + next: "Seg", + today: "Hoxe", + month: "Mes", + week: "Semana", + day: "DÃa", + list: "Axenda" + }, + weekLabel: "Sm", + allDayHtml: "Todo<br/>o dÃa", + eventLimitText: "máis", + noEventsMessage: "Non hai eventos para amosar" + }; + + var _m28 = { + code: "he", + dir: 'rtl', + buttonText: { + prev: "הקוד×", + next: "הב×", + today: "היו×", + month: "חודש", + week: "שבוע", + day: "יו×", + list: "סדר יו×" + }, + allDayText: "כל היו×", + eventLimitText: "×חר", + noEventsMessage: "×ין ××™×¨×•×¢×™× ×œ×”×¦×’×”", + weekLabel: "שבוע" + }; + + var _m29 = { + code: "hi", + week: { + dow: 0, + doy: 6 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "पिछला", + next: "अगला", + today: "आज", + month: "महीना", + week: "सपà¥à¤¤à¤¾à¤¹", + day: "दिन", + list: "कारà¥à¤¯à¤¸à¥‚ची" + }, + weekLabel: "हफà¥à¤¤à¤¾", + allDayText: "सà¤à¥€ दिन", + eventLimitText: function (n) { + return "+अधिक " + n; + }, + noEventsMessage: "कोई घटनाओं को पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ करने के लिà¤" + }; + + var _m30 = { + code: "hr", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "PrijaÅ¡nji", + next: "Sljedeći", + today: "Danas", + month: "Mjesec", + week: "Tjedan", + day: "Dan", + list: "Raspored" + }, + weekLabel: "Tje", + allDayText: "Cijeli dan", + eventLimitText: function (n) { + return "+ joÅ¡ " + n; + }, + noEventsMessage: "Nema dogaÄ‘aja za prikaz" + }; + + var _m31 = { + code: "hu", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "vissza", + next: "elÅ‘re", + today: "ma", + month: "Hónap", + week: "Hét", + day: "Nap", + list: "Napló" + }, + weekLabel: "Hét", + allDayText: "Egész nap", + eventLimitText: "további", + noEventsMessage: "Nincs megjelenÃthetÅ‘ esemény" + }; + + var _m32 = { + code: "id", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "mundur", + next: "maju", + today: "hari ini", + month: "Bulan", + week: "Minggu", + day: "Hari", + list: "Agenda" + }, + weekLabel: "Mg", + allDayHtml: "Sehari<br/>penuh", + eventLimitText: "lebih", + noEventsMessage: "Tidak ada acara untuk ditampilkan" + }; + + var _m33 = { + code: "is", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Fyrri", + next: "Næsti", + today: "à dag", + month: "Mánuður", + week: "Vika", + day: "Dagur", + list: "Dagskrá" + }, + weekLabel: "Vika", + allDayHtml: "Allan<br/>daginn", + eventLimitText: "meira", + noEventsMessage: "Engir viðburðir til að sýna" + }; + + var _m34 = { + code: "it", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Prec", + next: "Succ", + today: "Oggi", + month: "Mese", + week: "Settimana", + day: "Giorno", + list: "Agenda" + }, + weekLabel: "Sm", + allDayHtml: "Tutto il<br/>giorno", + eventLimitText: function (n) { + return "+altri " + n; + }, + noEventsMessage: "Non ci sono eventi da visualizzare" + }; + + var _m35 = { + code: "ja", + buttonText: { + prev: "å‰", + next: "次", + today: "今日", + month: "月", + week: "週", + day: "æ—¥", + list: "予定リスト" + }, + weekLabel: "週", + allDayText: "終日", + eventLimitText: function (n) { + return "ä»– " + n + " 件"; + }, + noEventsMessage: "表示ã™ã‚‹äºˆå®šã¯ã‚ã‚Šã¾ã›ã‚“" + }; + + var _m36 = { + code: "ka", + week: { + dow: 1, + doy: 7 + }, + buttonText: { + prev: "წინáƒ", + next: "შემდეგი", + today: "დღეს", + month: "თვე", + week: "კვირáƒ", + day: "დღე", + list: "დღის წესრიგი" + }, + weekLabel: "კვ", + allDayText: "მთელი დღე", + eventLimitText: function (n) { + return "+ კიდევ " + n; + }, + noEventsMessage: "ღáƒáƒœáƒ˜áƒ¡áƒ«áƒ˜áƒ”ბები áƒáƒ áƒáƒ ის" + }; + + var _m37 = { + code: "kk", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "Ðлдыңғы", + next: "КелеÑÑ–", + today: "Бүгін", + month: "Ðй", + week: "Ðпта", + day: "Күн", + list: "Күн тәртібі" + }, + weekLabel: "Ðе", + allDayText: "Күні бойы", + eventLimitText: function (n) { + return "+ тағы " + n; + }, + noEventsMessage: "КөрÑету үшін оқиғалар жоқ" + }; + + var _m38 = { + code: "ko", + buttonText: { + prev: "ì´ì „달", + next: "다ìŒë‹¬", + today: "오늘", + month: "ì›”", + week: "주", + day: "ì¼", + list: "ì¼ì •ëª©ë¡" + }, + weekLabel: "주", + allDayText: "종ì¼", + eventLimitText: "ê°œ", + noEventsMessage: "ì¼ì •ì´ 없습니다" + }; + + var _m39 = { + code: "lb", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Zréck", + next: "Weider", + today: "Haut", + month: "Mount", + week: "Woch", + day: "Dag", + list: "Terminiwwersiicht" + }, + weekLabel: "W", + allDayText: "Ganzen Dag", + eventLimitText: "méi", + noEventsMessage: "Nee Evenementer ze affichéieren" + }; + + var _m40 = { + code: "lt", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Atgal", + next: "Pirmyn", + today: "Å iandien", + month: "MÄ—nuo", + week: "SavaitÄ—", + day: "Diena", + list: "DarbotvarkÄ—" + }, + weekLabel: "SAV", + allDayText: "VisÄ… dienÄ…", + eventLimitText: "daugiau", + noEventsMessage: "NÄ—ra įvykių rodyti" + }; + + var _m41 = { + code: "lv", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Iepr.", + next: "NÄk.", + today: "Å odien", + month: "MÄ“nesis", + week: "Nedēļa", + day: "Diena", + list: "Dienas kÄrtÄ«ba" + }, + weekLabel: "Ned.", + allDayText: "Visu dienu", + eventLimitText: function (n) { + return "+vÄ“l " + n; + }, + noEventsMessage: "Nav notikumu" + }; + + var _m42 = { + code: "mk", + buttonText: { + prev: "претходно", + next: "Ñледно", + today: "ДенеÑ", + month: "МеÑец", + week: "Ðедела", + day: "Ден", + list: "График" + }, + weekLabel: "Сед", + allDayText: "Цел ден", + eventLimitText: function (n) { + return "+повеќе " + n; + }, + noEventsMessage: "Ðема наÑтани за прикажување" + }; + + var _m43 = { + code: "ms", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "Sebelum", + next: "Selepas", + today: "hari ini", + month: "Bulan", + week: "Minggu", + day: "Hari", + list: "Agenda" + }, + weekLabel: "Mg", + allDayText: "Sepanjang hari", + eventLimitText: function (n) { + return "masih ada " + n + " acara"; + }, + noEventsMessage: "Tiada peristiwa untuk dipaparkan" + }; + + var _m44 = { + code: "nb", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Forrige", + next: "Neste", + today: "I dag", + month: "MÃ¥ned", + week: "Uke", + day: "Dag", + list: "Agenda" + }, + weekLabel: "Uke", + allDayText: "Hele dagen", + eventLimitText: "til", + noEventsMessage: "Ingen hendelser Ã¥ vise" + }; + + var _m45 = { + code: "nl", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Voorgaand", + next: "Volgende", + today: "Vandaag", + year: "Jaar", + month: "Maand", + week: "Week", + day: "Dag", + list: "Agenda" + }, + allDayText: "Hele dag", + eventLimitText: "extra", + noEventsMessage: "Geen evenementen om te laten zien" + }; + + var _m46 = { + code: "nn", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Førre", + next: "Neste", + today: "I dag", + month: "MÃ¥nad", + week: "Veke", + day: "Dag", + list: "Agenda" + }, + weekLabel: "Veke", + allDayText: "Heile dagen", + eventLimitText: "til", + noEventsMessage: "Ingen hendelser Ã¥ vise" + }; + + var _m47 = { + code: "pl", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Poprzedni", + next: "NastÄ™pny", + today: "DziÅ›", + month: "MiesiÄ…c", + week: "TydzieÅ„", + day: "DzieÅ„", + list: "Plan dnia" + }, + weekLabel: "Tydz", + allDayText: "CaÅ‚y dzieÅ„", + eventLimitText: "wiÄ™cej", + noEventsMessage: "Brak wydarzeÅ„ do wyÅ›wietlenia" + }; + + var _m48 = { + code: "pt-br", + buttonText: { + prev: "Anterior", + next: "Próximo", + today: "Hoje", + month: "Mês", + week: "Semana", + day: "Dia", + list: "Compromissos" + }, + weekLabel: "Sm", + allDayText: "dia inteiro", + eventLimitText: function (n) { + return "mais +" + n; + }, + noEventsMessage: "Não há eventos para mostrar" + }; + + var _m49 = { + code: "pt", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Anterior", + next: "Seguinte", + today: "Hoje", + month: "Mês", + week: "Semana", + day: "Dia", + list: "Agenda" + }, + weekLabel: "Sem", + allDayText: "Todo o dia", + eventLimitText: "mais", + noEventsMessage: "Não há eventos para mostrar" + }; + + var _m50 = { + code: "ro", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "precedentă", + next: "următoare", + today: "Azi", + month: "Lună", + week: "Săptămână", + day: "Zi", + list: "Agendă" + }, + weekLabel: "Săpt", + allDayText: "Toată ziua", + eventLimitText: function (n) { + return "+alte " + n; + }, + noEventsMessage: "Nu există evenimente de afiÈ™at" + }; + + var _m51 = { + code: "ru", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Пред", + next: "След", + today: "СегоднÑ", + month: "МеÑÑц", + week: "ÐеделÑ", + day: "День", + list: "ПовеÑтка днÑ" + }, + weekLabel: "Ðед", + allDayText: "ВеÑÑŒ день", + eventLimitText: function (n) { + return "+ ещё " + n; + }, + noEventsMessage: "Ðет Ñобытий Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ" + }; + + var _m52 = { + code: "sk", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Predchádzajúci", + next: "Nasledujúci", + today: "Dnes", + month: "Mesiac", + week: "Týždeň", + day: "Deň", + list: "Rozvrh" + }, + weekLabel: "Ty", + allDayText: "Celý deň", + eventLimitText: function (n) { + return "+ÄalÅ¡ie: " + n; + }, + noEventsMessage: "Žiadne akcie na zobrazenie" + }; + + var _m53 = { + code: "sl", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "PrejÅ¡nji", + next: "Naslednji", + today: "Trenutni", + month: "Mesec", + week: "Teden", + day: "Dan", + list: "Dnevni red" + }, + weekLabel: "Teden", + allDayText: "Ves dan", + eventLimitText: "veÄ", + noEventsMessage: "Ni dogodkov za prikaz" + }; + + var _m54 = { + code: "sq", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "mbrapa", + next: "Përpara", + today: "sot", + month: "Muaj", + week: "Javë", + day: "Ditë", + list: "Listë" + }, + weekLabel: "Ja", + allDayHtml: "Gjithë<br/>ditën", + eventLimitText: function (n) { + return "+më tepër " + n; + }, + noEventsMessage: "Nuk ka evente për të shfaqur" + }; + + var _m55 = { + code: "sr-cyrl", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "Претходна", + next: "Ñледећи", + today: "ДанаÑ", + month: "МеÑец", + week: "Ðедеља", + day: "Дан", + list: "Планер" + }, + weekLabel: "Сед", + allDayText: "Цео дан", + eventLimitText: function (n) { + return "+ још " + n; + }, + noEventsMessage: "Ðема догађаја за приказ" + }; + + var _m56 = { + code: "sr", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "Prethodna", + next: "SledecÌi", + today: "Danas", + month: "Mеsеc", + week: "Nеdеlja", + day: "Dan", + list: "Planеr" + }, + weekLabel: "Sed", + allDayText: "Cеo dan", + eventLimitText: function (n) { + return "+ joÅ¡ " + n; + }, + noEventsMessage: "Nеma dogaÄ‘aja za prikaz" + }; + + var _m57 = { + code: "sv", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Förra", + next: "Nästa", + today: "Idag", + month: "MÃ¥nad", + week: "Vecka", + day: "Dag", + list: "Program" + }, + weekLabel: "v.", + allDayText: "Heldag", + eventLimitText: "till", + noEventsMessage: "Inga händelser att visa" + }; + + var _m58 = { + code: "th", + buttonText: { + prev: "ย้à¸à¸™", + next: "ถัดไป", + today: "วันนี้", + month: "เดืà¸à¸™", + week: "สัปดาห์", + day: "วัน", + list: "à¹à¸œà¸™à¸‡à¸²à¸™" + }, + allDayText: "ตลà¸à¸”วัน", + eventLimitText: "เพิ่มเติม", + noEventsMessage: "ไม่มีà¸à¸´à¸ˆà¸à¸£à¸£à¸¡à¸—ี่จะà¹à¸ªà¸”ง" + }; + + var _m59 = { + code: "tr", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "geri", + next: "ileri", + today: "bugün", + month: "Ay", + week: "Hafta", + day: "Gün", + list: "Ajanda" + }, + weekLabel: "Hf", + allDayText: "Tüm gün", + eventLimitText: "daha fazla", + noEventsMessage: "Gösterilecek etkinlik yok" + }; + + var _m60 = { + code: "uk", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "Попередній", + next: "далі", + today: "Сьогодні", + month: "МіÑÑць", + week: "Тиждень", + day: "День", + list: "ПорÑдок денний" + }, + weekLabel: "Тиж", + allDayText: "УвеÑÑŒ день", + eventLimitText: function (n) { + return "+ще " + n + "..."; + }, + noEventsMessage: "Ðемає подій Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ" + }; + + var _m61 = { + code: "vi", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "TrÆ°á»›c", + next: "Tiếp", + today: "Hôm nay", + month: "Tháng", + week: "Tuần", + day: "Ngà y", + list: "Lịch biểu" + }, + weekLabel: "Tu", + allDayText: "Cả ngà y", + eventLimitText: function (n) { + return "+ thêm " + n; + }, + noEventsMessage: "Không có sá»± kiện để hiển thị" + }; + + var _m62 = { + code: "zh-cn", + week: { + // GB/T 7408-1994《数æ®å…ƒå’Œäº¤æ¢æ ¼å¼Â·ä¿¡æ¯äº¤æ¢Â·æ—¥æœŸå’Œæ—¶é—´è¡¨ç¤ºæ³•ã€‹ä¸ŽISO 8601:1988ç‰æ•ˆ + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "上月", + next: "下月", + today: "今天", + month: "月", + week: "周", + day: "æ—¥", + list: "日程" + }, + weekLabel: "周", + allDayText: "全天", + eventLimitText: function (n) { + return "å¦å¤– " + n + " 个"; + }, + noEventsMessage: "没有事件显示" + }; + + var _m63 = { + code: "zh-tw", + buttonText: { + prev: "上月", + next: "下月", + today: "今天", + month: "月", + week: "週", + day: "天", + list: "活動列表" + }, + weekLabel: "周", + allDayText: "整天", + eventLimitText: '顯示更多', + noEventsMessage: "没有任何活動" + }; + + var _rollupPluginMultiEntry_entryPoint = [ + _m0, _m1, _m2, _m3, _m4, _m5, _m6, _m7, _m8, _m9, _m10, _m11, _m12, _m13, _m14, _m15, _m16, _m17, _m18, _m19, _m20, _m21, _m22, _m23, _m24, _m25, _m26, _m27, _m28, _m29, _m30, _m31, _m32, _m33, _m34, _m35, _m36, _m37, _m38, _m39, _m40, _m41, _m42, _m43, _m44, _m45, _m46, _m47, _m48, _m49, _m50, _m51, _m52, _m53, _m54, _m55, _m56, _m57, _m58, _m59, _m60, _m61, _m62, _m63 + ]; + + return _rollupPluginMultiEntry_entryPoint; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales-all.min.js b/AKPlan/static/AKPlan/fullcalendar/core/locales-all.min.js new file mode 100644 index 00000000..810d6dea --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales-all.min.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).FullCalendarLocalesAll=t()}(this,function(){"use strict";return[{code:"af",week:{dow:1,doy:4},buttonText:{prev:"Vorige",next:"Volgende",today:"Vandag",year:"Jaar",month:"Maand",week:"Week",day:"Dag",list:"Agenda"},allDayHtml:"Heeldag",eventLimitText:"Addisionele",noEventsMessage:"Daar is geen gebeurtenisse nie"},{code:"ar-dz",week:{dow:0,doy:4},dir:"rtl",buttonText:{prev:"السابق",next:"التالي",today:"اليوم",month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},weekLabel:"أسبوع",allDayText:"اليوم كله",eventLimitText:"أخرى",noEventsMessage:"أي Ø£Øداث لعرض"},{code:"ar-kw",week:{dow:0,doy:12},dir:"rtl",buttonText:{prev:"السابق",next:"التالي",today:"اليوم",month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},weekLabel:"أسبوع",allDayText:"اليوم كله",eventLimitText:"أخرى",noEventsMessage:"أي Ø£Øداث لعرض"},{code:"ar-ly",week:{dow:6,doy:12},dir:"rtl",buttonText:{prev:"السابق",next:"التالي",today:"اليوم",month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},weekLabel:"أسبوع",allDayText:"اليوم كله",eventLimitText:"أخرى",noEventsMessage:"أي Ø£Øداث لعرض"},{code:"ar-ma",week:{dow:6,doy:12},dir:"rtl",buttonText:{prev:"السابق",next:"التالي",today:"اليوم",month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},weekLabel:"أسبوع",allDayText:"اليوم كله",eventLimitText:"أخرى",noEventsMessage:"أي Ø£Øداث لعرض"},{code:"ar-sa",week:{dow:0,doy:6},dir:"rtl",buttonText:{prev:"السابق",next:"التالي",today:"اليوم",month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},weekLabel:"أسبوع",allDayText:"اليوم كله",eventLimitText:"أخرى",noEventsMessage:"أي Ø£Øداث لعرض"},{code:"ar-tn",week:{dow:1,doy:4},dir:"rtl",buttonText:{prev:"السابق",next:"التالي",today:"اليوم",month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},weekLabel:"أسبوع",allDayText:"اليوم كله",eventLimitText:"أخرى",noEventsMessage:"أي Ø£Øداث لعرض"},{code:"ar",week:{dow:6,doy:12},dir:"rtl",buttonText:{prev:"السابق",next:"التالي",today:"اليوم",month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},weekLabel:"أسبوع",allDayText:"اليوم كله",eventLimitText:"أخرى",noEventsMessage:"أي Ø£Øداث لعرض"},{code:"bg",week:{dow:1,doy:7},buttonText:{prev:"назад",next:"напред",today:"днеÑ",month:"МеÑец",week:"Седмица",day:"Ден",list:"График"},allDayText:"ЦÑл ден",eventLimitText:function(e){return"+още "+e},noEventsMessage:"ÐÑма ÑÑŠÐ±Ð¸Ñ‚Ð¸Ñ Ð·Ð° показване"},{code:"bs",week:{dow:1,doy:7},buttonText:{prev:"ProÅ¡li",next:"Sljedeći",today:"Danas",month:"Mjesec",week:"Sedmica",day:"Dan",list:"Raspored"},weekLabel:"Sed",allDayText:"Cijeli dan",eventLimitText:function(e){return"+ joÅ¡ "+e},noEventsMessage:"Nema dogaÄ‘aja za prikazivanje"},{code:"ca",week:{dow:1,doy:4},buttonText:{prev:"Anterior",next:"Següent",today:"Avui",month:"Mes",week:"Setmana",day:"Dia",list:"Agenda"},weekLabel:"Set",allDayText:"Tot el dia",eventLimitText:"més",noEventsMessage:"No hi ha esdeveniments per mostrar"},{code:"cs",week:{dow:1,doy:4},buttonText:{prev:"DÅ™Ãve",next:"PozdÄ›ji",today:"NynÃ",month:"MÄ›sÃc",week:"Týden",day:"Den",list:"Agenda"},weekLabel:"Týd",allDayText:"Celý den",eventLimitText:function(e){return"+dalÅ¡Ã: "+e},noEventsMessage:"Žádné akce k zobrazenÃ"},{code:"da",week:{dow:1,doy:4},buttonText:{prev:"Forrige",next:"Næste",today:"I dag",month:"MÃ¥ned",week:"Uge",day:"Dag",list:"Agenda"},weekLabel:"Uge",allDayText:"Hele dagen",eventLimitText:"flere",noEventsMessage:"Ingen arrangementer at vise"},{code:"de",week:{dow:1,doy:4},buttonText:{prev:"Zurück",next:"Vor",today:"Heute",year:"Jahr",month:"Monat",week:"Woche",day:"Tag",list:"Terminübersicht"},weekLabel:"KW",allDayText:"Ganztägig",eventLimitText:function(e){return"+ weitere "+e},noEventsMessage:"Keine Ereignisse anzuzeigen"},{code:"el",week:{dow:1,doy:4},buttonText:{prev:"Î ÏοηγοÏμενος",next:"Επόμενος",today:"ΣήμεÏα",month:"Μήνας",week:"Εβδομάδα",day:"ΗμÎÏα",list:"ΑτζÎντα"},weekLabel:"Εβδ",allDayText:"ΟλοήμεÏο",eventLimitText:"πεÏισσότεÏα",noEventsMessage:"Δεν υπάÏχουν γεγονότα για να εμφανιστεί"},{code:"en-au",week:{dow:1,doy:4}},{code:"en-gb",week:{dow:1,doy:4}},{code:"en-nz",week:{dow:1,doy:4}},{code:"es",week:{dow:0,doy:6},buttonText:{prev:"Ant",next:"Sig",today:"Hoy",month:"Mes",week:"Semana",day:"DÃa",list:"Agenda"},weekLabel:"Sm",allDayHtml:"Todo<br/>el dÃa",eventLimitText:"más",noEventsMessage:"No hay eventos para mostrar"},{code:"es",week:{dow:1,doy:4},buttonText:{prev:"Ant",next:"Sig",today:"Hoy",month:"Mes",week:"Semana",day:"DÃa",list:"Agenda"},weekLabel:"Sm",allDayHtml:"Todo<br/>el dÃa",eventLimitText:"más",noEventsMessage:"No hay eventos para mostrar"},{code:"et",week:{dow:1,doy:4},buttonText:{prev:"Eelnev",next:"Järgnev",today:"Täna",month:"Kuu",week:"Nädal",day:"Päev",list:"Päevakord"},weekLabel:"näd",allDayText:"Kogu päev",eventLimitText:function(e){return"+ veel "+e},noEventsMessage:"Kuvamiseks puuduvad sündmused"},{code:"eu",week:{dow:1,doy:7},buttonText:{prev:"Aur",next:"Hur",today:"Gaur",month:"Hilabetea",week:"Astea",day:"Eguna",list:"Agenda"},weekLabel:"As",allDayHtml:"Egun<br/>osoa",eventLimitText:"gehiago",noEventsMessage:"Ez dago ekitaldirik erakusteko"},{code:"fa",week:{dow:6,doy:12},dir:"rtl",buttonText:{prev:"قبلی",next:"بعدی",today:"امروز",month:"ماه",week:"Ù‡Ùته",day:"روز",list:"برنامه"},weekLabel:"Ù‡Ù",allDayText:"تمام روز",eventLimitText:function(e){return"بیش از "+e},noEventsMessage:"هیچ رویدادی به نمایش"},{code:"fi",week:{dow:1,doy:4},buttonText:{prev:"Edellinen",next:"Seuraava",today:"Tänään",month:"Kuukausi",week:"Viikko",day:"Päivä",list:"Tapahtumat"},weekLabel:"Vk",allDayText:"Koko päivä",eventLimitText:"lisää",noEventsMessage:"Ei näytettäviä tapahtumia"},{code:"fr",buttonText:{prev:"Précédent",next:"Suivant",today:"Aujourd'hui",year:"Année",month:"Mois",week:"Semaine",day:"Jour",list:"Mon planning"},weekLabel:"Sem.",allDayHtml:"Toute la<br/>journée",eventLimitText:"en plus",noEventsMessage:"Aucun événement à afficher"},{code:"fr-ch",week:{dow:1,doy:4},buttonText:{prev:"Précédent",next:"Suivant",today:"Courant",year:"Année",month:"Mois",week:"Semaine",day:"Jour",list:"Mon planning"},weekLabel:"Sm",allDayHtml:"Toute la<br/>journée",eventLimitText:"en plus",noEventsMessage:"Aucun événement à afficher"},{code:"fr",week:{dow:1,doy:4},buttonText:{prev:"Précédent",next:"Suivant",today:"Aujourd'hui",year:"Année",month:"Mois",week:"Semaine",day:"Jour",list:"Mon planning"},weekLabel:"Sem.",allDayHtml:"Toute la<br/>journée",eventLimitText:"en plus",noEventsMessage:"Aucun événement à afficher"},{code:"gl",week:{dow:1,doy:4},buttonText:{prev:"Ant",next:"Seg",today:"Hoxe",month:"Mes",week:"Semana",day:"DÃa",list:"Axenda"},weekLabel:"Sm",allDayHtml:"Todo<br/>o dÃa",eventLimitText:"máis",noEventsMessage:"Non hai eventos para amosar"},{code:"he",dir:"rtl",buttonText:{prev:"הקוד×",next:"הב×",today:"היו×",month:"חודש",week:"שבוע",day:"יו×",list:"סדר יו×"},allDayText:"כל היו×",eventLimitText:"×חר",noEventsMessage:"×ין ××™×¨×•×¢×™× ×œ×”×¦×’×”",weekLabel:"שבוע"},{code:"hi",week:{dow:0,doy:6},buttonText:{prev:"पिछला",next:"अगला",today:"आज",month:"महीना",week:"सपà¥à¤¤à¤¾à¤¹",day:"दिन",list:"कारà¥à¤¯à¤¸à¥‚ची"},weekLabel:"हफà¥à¤¤à¤¾",allDayText:"सà¤à¥€ दिन",eventLimitText:function(e){return"+अधिक "+e},noEventsMessage:"कोई घटनाओं को पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ करने के लिà¤"},{code:"hr",week:{dow:1,doy:7},buttonText:{prev:"PrijaÅ¡nji",next:"Sljedeći",today:"Danas",month:"Mjesec",week:"Tjedan",day:"Dan",list:"Raspored"},weekLabel:"Tje",allDayText:"Cijeli dan",eventLimitText:function(e){return"+ joÅ¡ "+e},noEventsMessage:"Nema dogaÄ‘aja za prikaz"},{code:"hu",week:{dow:1,doy:4},buttonText:{prev:"vissza",next:"elÅ‘re",today:"ma",month:"Hónap",week:"Hét",day:"Nap",list:"Napló"},weekLabel:"Hét",allDayText:"Egész nap",eventLimitText:"további",noEventsMessage:"Nincs megjelenÃthetÅ‘ esemény"},{code:"id",week:{dow:1,doy:7},buttonText:{prev:"mundur",next:"maju",today:"hari ini",month:"Bulan",week:"Minggu",day:"Hari",list:"Agenda"},weekLabel:"Mg",allDayHtml:"Sehari<br/>penuh",eventLimitText:"lebih",noEventsMessage:"Tidak ada acara untuk ditampilkan"},{code:"is",week:{dow:1,doy:4},buttonText:{prev:"Fyrri",next:"Næsti",today:"à dag",month:"Mánuður",week:"Vika",day:"Dagur",list:"Dagskrá"},weekLabel:"Vika",allDayHtml:"Allan<br/>daginn",eventLimitText:"meira",noEventsMessage:"Engir viðburðir til að sýna"},{code:"it",week:{dow:1,doy:4},buttonText:{prev:"Prec",next:"Succ",today:"Oggi",month:"Mese",week:"Settimana",day:"Giorno",list:"Agenda"},weekLabel:"Sm",allDayHtml:"Tutto il<br/>giorno",eventLimitText:function(e){return"+altri "+e},noEventsMessage:"Non ci sono eventi da visualizzare"},{code:"ja",buttonText:{prev:"å‰",next:"次",today:"今日",month:"月",week:"週",day:"æ—¥",list:"予定リスト"},weekLabel:"週",allDayText:"終日",eventLimitText:function(e){return"ä»– "+e+" 件"},noEventsMessage:"表示ã™ã‚‹äºˆå®šã¯ã‚ã‚Šã¾ã›ã‚“"},{code:"ka",week:{dow:1,doy:7},buttonText:{prev:"წინáƒ",next:"შემდეგი",today:"დღეს",month:"თვე",week:"კვირáƒ",day:"დღე",list:"დღის წესრიგი"},weekLabel:"კვ",allDayText:"მთელი დღე",eventLimitText:function(e){return"+ კიდევ "+e},noEventsMessage:"ღáƒáƒœáƒ˜áƒ¡áƒ«áƒ˜áƒ”ბები áƒáƒ áƒáƒ ის"},{code:"kk",week:{dow:1,doy:7},buttonText:{prev:"Ðлдыңғы",next:"КелеÑÑ–",today:"Бүгін",month:"Ðй",week:"Ðпта",day:"Күн",list:"Күн тәртібі"},weekLabel:"Ðе",allDayText:"Күні бойы",eventLimitText:function(e){return"+ тағы "+e},noEventsMessage:"КөрÑету үшін оқиғалар жоқ"},{code:"ko",buttonText:{prev:"ì´ì „달",next:"다ìŒë‹¬",today:"오늘",month:"ì›”",week:"주",day:"ì¼",list:"ì¼ì •ëª©ë¡"},weekLabel:"주",allDayText:"종ì¼",eventLimitText:"ê°œ",noEventsMessage:"ì¼ì •ì´ 없습니다"},{code:"lb",week:{dow:1,doy:4},buttonText:{prev:"Zréck",next:"Weider",today:"Haut",month:"Mount",week:"Woch",day:"Dag",list:"Terminiwwersiicht"},weekLabel:"W",allDayText:"Ganzen Dag",eventLimitText:"méi",noEventsMessage:"Nee Evenementer ze affichéieren"},{code:"lt",week:{dow:1,doy:4},buttonText:{prev:"Atgal",next:"Pirmyn",today:"Å iandien",month:"MÄ—nuo",week:"SavaitÄ—",day:"Diena",list:"DarbotvarkÄ—"},weekLabel:"SAV",allDayText:"VisÄ… dienÄ…",eventLimitText:"daugiau",noEventsMessage:"NÄ—ra įvykių rodyti"},{code:"lv",week:{dow:1,doy:4},buttonText:{prev:"Iepr.",next:"NÄk.",today:"Å odien",month:"MÄ“nesis",week:"Nedēļa",day:"Diena",list:"Dienas kÄrtÄ«ba"},weekLabel:"Ned.",allDayText:"Visu dienu",eventLimitText:function(e){return"+vÄ“l "+e},noEventsMessage:"Nav notikumu"},{code:"mk",buttonText:{prev:"претходно",next:"Ñледно",today:"ДенеÑ",month:"МеÑец",week:"Ðедела",day:"Ден",list:"График"},weekLabel:"Сед",allDayText:"Цел ден",eventLimitText:function(e){return"+повеќе "+e},noEventsMessage:"Ðема наÑтани за прикажување"},{code:"ms",week:{dow:1,doy:7},buttonText:{prev:"Sebelum",next:"Selepas",today:"hari ini",month:"Bulan",week:"Minggu",day:"Hari",list:"Agenda"},weekLabel:"Mg",allDayText:"Sepanjang hari",eventLimitText:function(e){return"masih ada "+e+" acara"},noEventsMessage:"Tiada peristiwa untuk dipaparkan"},{code:"nb",week:{dow:1,doy:4},buttonText:{prev:"Forrige",next:"Neste",today:"I dag",month:"MÃ¥ned",week:"Uke",day:"Dag",list:"Agenda"},weekLabel:"Uke",allDayText:"Hele dagen",eventLimitText:"til",noEventsMessage:"Ingen hendelser Ã¥ vise"},{code:"nl",week:{dow:1,doy:4},buttonText:{prev:"Voorgaand",next:"Volgende",today:"Vandaag",year:"Jaar",month:"Maand",week:"Week",day:"Dag",list:"Agenda"},allDayText:"Hele dag",eventLimitText:"extra",noEventsMessage:"Geen evenementen om te laten zien"},{code:"nn",week:{dow:1,doy:4},buttonText:{prev:"Førre",next:"Neste",today:"I dag",month:"MÃ¥nad",week:"Veke",day:"Dag",list:"Agenda"},weekLabel:"Veke",allDayText:"Heile dagen",eventLimitText:"til",noEventsMessage:"Ingen hendelser Ã¥ vise"},{code:"pl",week:{dow:1,doy:4},buttonText:{prev:"Poprzedni",next:"NastÄ™pny",today:"DziÅ›",month:"MiesiÄ…c",week:"TydzieÅ„",day:"DzieÅ„",list:"Plan dnia"},weekLabel:"Tydz",allDayText:"CaÅ‚y dzieÅ„",eventLimitText:"wiÄ™cej",noEventsMessage:"Brak wydarzeÅ„ do wyÅ›wietlenia"},{code:"pt-br",buttonText:{prev:"Anterior",next:"Próximo",today:"Hoje",month:"Mês",week:"Semana",day:"Dia",list:"Compromissos"},weekLabel:"Sm",allDayText:"dia inteiro",eventLimitText:function(e){return"mais +"+e},noEventsMessage:"Não há eventos para mostrar"},{code:"pt",week:{dow:1,doy:4},buttonText:{prev:"Anterior",next:"Seguinte",today:"Hoje",month:"Mês",week:"Semana",day:"Dia",list:"Agenda"},weekLabel:"Sem",allDayText:"Todo o dia",eventLimitText:"mais",noEventsMessage:"Não há eventos para mostrar"},{code:"ro",week:{dow:1,doy:7},buttonText:{prev:"precedentă",next:"următoare",today:"Azi",month:"Lună",week:"Săptămână",day:"Zi",list:"Agendă"},weekLabel:"Săpt",allDayText:"Toată ziua",eventLimitText:function(e){return"+alte "+e},noEventsMessage:"Nu există evenimente de afiÈ™at"},{code:"ru",week:{dow:1,doy:4},buttonText:{prev:"Пред",next:"След",today:"СегоднÑ",month:"МеÑÑц",week:"ÐеделÑ",day:"День",list:"ПовеÑтка днÑ"},weekLabel:"Ðед",allDayText:"ВеÑÑŒ день",eventLimitText:function(e){return"+ ещё "+e},noEventsMessage:"Ðет Ñобытий Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ"},{code:"sk",week:{dow:1,doy:4},buttonText:{prev:"Predchádzajúci",next:"Nasledujúci",today:"Dnes",month:"Mesiac",week:"Týždeň",day:"Deň",list:"Rozvrh"},weekLabel:"Ty",allDayText:"Celý deň",eventLimitText:function(e){return"+ÄalÅ¡ie: "+e},noEventsMessage:"Žiadne akcie na zobrazenie"},{code:"sl",week:{dow:1,doy:7},buttonText:{prev:"PrejÅ¡nji",next:"Naslednji",today:"Trenutni",month:"Mesec",week:"Teden",day:"Dan",list:"Dnevni red"},weekLabel:"Teden",allDayText:"Ves dan",eventLimitText:"veÄ",noEventsMessage:"Ni dogodkov za prikaz"},{code:"sq",week:{dow:1,doy:4},buttonText:{prev:"mbrapa",next:"Përpara",today:"sot",month:"Muaj",week:"Javë",day:"Ditë",list:"Listë"},weekLabel:"Ja",allDayHtml:"Gjithë<br/>ditën",eventLimitText:function(e){return"+më tepër "+e},noEventsMessage:"Nuk ka evente për të shfaqur"},{code:"sr-cyrl",week:{dow:1,doy:7},buttonText:{prev:"Претходна",next:"Ñледећи",today:"ДанаÑ",month:"МеÑец",week:"Ðедеља",day:"Дан",list:"Планер"},weekLabel:"Сед",allDayText:"Цео дан",eventLimitText:function(e){return"+ још "+e},noEventsMessage:"Ðема догађаја за приказ"},{code:"sr",week:{dow:1,doy:7},buttonText:{prev:"Prethodna",next:"SledecÌi",today:"Danas",month:"Mеsеc",week:"Nеdеlja",day:"Dan",list:"Planеr"},weekLabel:"Sed",allDayText:"Cеo dan",eventLimitText:function(e){return"+ joÅ¡ "+e},noEventsMessage:"Nеma dogaÄ‘aja za prikaz"},{code:"sv",week:{dow:1,doy:4},buttonText:{prev:"Förra",next:"Nästa",today:"Idag",month:"MÃ¥nad",week:"Vecka",day:"Dag",list:"Program"},weekLabel:"v.",allDayText:"Heldag",eventLimitText:"till",noEventsMessage:"Inga händelser att visa"},{code:"th",buttonText:{prev:"ย้à¸à¸™",next:"ถัดไป",today:"วันนี้",month:"เดืà¸à¸™",week:"สัปดาห์",day:"วัน",list:"à¹à¸œà¸™à¸‡à¸²à¸™"},allDayText:"ตลà¸à¸”วัน",eventLimitText:"เพิ่มเติม",noEventsMessage:"ไม่มีà¸à¸´à¸ˆà¸à¸£à¸£à¸¡à¸—ี่จะà¹à¸ªà¸”ง"},{code:"tr",week:{dow:1,doy:7},buttonText:{prev:"geri",next:"ileri",today:"bugün",month:"Ay",week:"Hafta",day:"Gün",list:"Ajanda"},weekLabel:"Hf",allDayText:"Tüm gün",eventLimitText:"daha fazla",noEventsMessage:"Gösterilecek etkinlik yok"},{code:"uk",week:{dow:1,doy:7},buttonText:{prev:"Попередній",next:"далі",today:"Сьогодні",month:"МіÑÑць",week:"Тиждень",day:"День",list:"ПорÑдок денний"},weekLabel:"Тиж",allDayText:"УвеÑÑŒ день",eventLimitText:function(e){return"+ще "+e+"..."},noEventsMessage:"Ðемає подій Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ"},{code:"vi",week:{dow:1,doy:4},buttonText:{prev:"TrÆ°á»›c",next:"Tiếp",today:"Hôm nay",month:"Tháng",week:"Tuần",day:"Ngà y",list:"Lịch biểu"},weekLabel:"Tu",allDayText:"Cả ngà y",eventLimitText:function(e){return"+ thêm "+e},noEventsMessage:"Không có sá»± kiện để hiển thị"},{code:"zh-cn",week:{dow:1,doy:4},buttonText:{prev:"上月",next:"下月",today:"今天",month:"月",week:"周",day:"æ—¥",list:"日程"},weekLabel:"周",allDayText:"全天",eventLimitText:function(e){return"å¦å¤– "+e+" 个"},noEventsMessage:"没有事件显示"},{code:"zh-tw",buttonText:{prev:"上月",next:"下月",today:"今天",month:"月",week:"週",day:"天",list:"活動列表"},weekLabel:"周",allDayText:"整天",eventLimitText:"顯示更多",noEventsMessage:"没有任何活動"}]}); \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/af.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/af.js new file mode 100644 index 00000000..ee9f9f74 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/af.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.af = factory())); +}(this, function () { 'use strict'; + + var af = { + code: "af", + week: { + dow: 1, + doy: 4 // Die week wat die 4de Januarie bevat is die eerste week van die jaar. + }, + buttonText: { + prev: "Vorige", + next: "Volgende", + today: "Vandag", + year: "Jaar", + month: "Maand", + week: "Week", + day: "Dag", + list: "Agenda" + }, + allDayHtml: "Heeldag", + eventLimitText: "Addisionele", + noEventsMessage: "Daar is geen gebeurtenisse nie" + }; + + return af; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/ar-dz.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/ar-dz.js new file mode 100644 index 00000000..201eb171 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/ar-dz.js @@ -0,0 +1,31 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales['ar-dz'] = factory())); +}(this, function () { 'use strict'; + + var arDz = { + code: "ar-dz", + week: { + dow: 0, + doy: 4 // The week that contains Jan 1st is the first week of the year. + }, + dir: 'rtl', + buttonText: { + prev: "السابق", + next: "التالي", + today: "اليوم", + month: "شهر", + week: "أسبوع", + day: "يوم", + list: "أجندة" + }, + weekLabel: "أسبوع", + allDayText: "اليوم كله", + eventLimitText: "أخرى", + noEventsMessage: "أي Ø£Øداث لعرض" + }; + + return arDz; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/ar-kw.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/ar-kw.js new file mode 100644 index 00000000..94c69001 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/ar-kw.js @@ -0,0 +1,31 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales['ar-kw'] = factory())); +}(this, function () { 'use strict'; + + var arKw = { + code: "ar-kw", + week: { + dow: 0, + doy: 12 // The week that contains Jan 1st is the first week of the year. + }, + dir: 'rtl', + buttonText: { + prev: "السابق", + next: "التالي", + today: "اليوم", + month: "شهر", + week: "أسبوع", + day: "يوم", + list: "أجندة" + }, + weekLabel: "أسبوع", + allDayText: "اليوم كله", + eventLimitText: "أخرى", + noEventsMessage: "أي Ø£Øداث لعرض" + }; + + return arKw; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/ar-ly.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/ar-ly.js new file mode 100644 index 00000000..e1c8aeb0 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/ar-ly.js @@ -0,0 +1,31 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales['ar-ly'] = factory())); +}(this, function () { 'use strict'; + + var arLy = { + code: "ar-ly", + week: { + dow: 6, + doy: 12 // The week that contains Jan 1st is the first week of the year. + }, + dir: 'rtl', + buttonText: { + prev: "السابق", + next: "التالي", + today: "اليوم", + month: "شهر", + week: "أسبوع", + day: "يوم", + list: "أجندة" + }, + weekLabel: "أسبوع", + allDayText: "اليوم كله", + eventLimitText: "أخرى", + noEventsMessage: "أي Ø£Øداث لعرض" + }; + + return arLy; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/ar-ma.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/ar-ma.js new file mode 100644 index 00000000..00cc7c67 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/ar-ma.js @@ -0,0 +1,31 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales['ar-ma'] = factory())); +}(this, function () { 'use strict'; + + var arMa = { + code: "ar-ma", + week: { + dow: 6, + doy: 12 // The week that contains Jan 1st is the first week of the year. + }, + dir: 'rtl', + buttonText: { + prev: "السابق", + next: "التالي", + today: "اليوم", + month: "شهر", + week: "أسبوع", + day: "يوم", + list: "أجندة" + }, + weekLabel: "أسبوع", + allDayText: "اليوم كله", + eventLimitText: "أخرى", + noEventsMessage: "أي Ø£Øداث لعرض" + }; + + return arMa; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/ar-sa.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/ar-sa.js new file mode 100644 index 00000000..0361f6d8 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/ar-sa.js @@ -0,0 +1,31 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales['ar-sa'] = factory())); +}(this, function () { 'use strict'; + + var arSa = { + code: "ar-sa", + week: { + dow: 0, + doy: 6 // The week that contains Jan 1st is the first week of the year. + }, + dir: 'rtl', + buttonText: { + prev: "السابق", + next: "التالي", + today: "اليوم", + month: "شهر", + week: "أسبوع", + day: "يوم", + list: "أجندة" + }, + weekLabel: "أسبوع", + allDayText: "اليوم كله", + eventLimitText: "أخرى", + noEventsMessage: "أي Ø£Øداث لعرض" + }; + + return arSa; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/ar-tn.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/ar-tn.js new file mode 100644 index 00000000..57a07f8f --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/ar-tn.js @@ -0,0 +1,31 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales['ar-tn'] = factory())); +}(this, function () { 'use strict'; + + var arTn = { + code: "ar-tn", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + dir: 'rtl', + buttonText: { + prev: "السابق", + next: "التالي", + today: "اليوم", + month: "شهر", + week: "أسبوع", + day: "يوم", + list: "أجندة" + }, + weekLabel: "أسبوع", + allDayText: "اليوم كله", + eventLimitText: "أخرى", + noEventsMessage: "أي Ø£Øداث لعرض" + }; + + return arTn; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/ar.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/ar.js new file mode 100644 index 00000000..f789afd1 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/ar.js @@ -0,0 +1,31 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.ar = factory())); +}(this, function () { 'use strict'; + + var ar = { + code: "ar", + week: { + dow: 6, + doy: 12 // The week that contains Jan 1st is the first week of the year. + }, + dir: 'rtl', + buttonText: { + prev: "السابق", + next: "التالي", + today: "اليوم", + month: "شهر", + week: "أسبوع", + day: "يوم", + list: "أجندة" + }, + weekLabel: "أسبوع", + allDayText: "اليوم كله", + eventLimitText: "أخرى", + noEventsMessage: "أي Ø£Øداث لعرض" + }; + + return ar; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/bg.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/bg.js new file mode 100644 index 00000000..e7343a6c --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/bg.js @@ -0,0 +1,31 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.bg = factory())); +}(this, function () { 'use strict'; + + var bg = { + code: "bg", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "назад", + next: "напред", + today: "днеÑ", + month: "МеÑец", + week: "Седмица", + day: "Ден", + list: "График" + }, + allDayText: "ЦÑл ден", + eventLimitText: function (n) { + return "+още " + n; + }, + noEventsMessage: "ÐÑма ÑÑŠÐ±Ð¸Ñ‚Ð¸Ñ Ð·Ð° показване" + }; + + return bg; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/bs.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/bs.js new file mode 100644 index 00000000..d96b8adb --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/bs.js @@ -0,0 +1,32 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.bs = factory())); +}(this, function () { 'use strict'; + + var bs = { + code: "bs", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "ProÅ¡li", + next: "Sljedeći", + today: "Danas", + month: "Mjesec", + week: "Sedmica", + day: "Dan", + list: "Raspored" + }, + weekLabel: "Sed", + allDayText: "Cijeli dan", + eventLimitText: function (n) { + return "+ joÅ¡ " + n; + }, + noEventsMessage: "Nema dogaÄ‘aja za prikazivanje" + }; + + return bs; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/ca.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/ca.js new file mode 100644 index 00000000..d2d3e2aa --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/ca.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.ca = factory())); +}(this, function () { 'use strict'; + + var ca = { + code: "ca", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Anterior", + next: "Següent", + today: "Avui", + month: "Mes", + week: "Setmana", + day: "Dia", + list: "Agenda" + }, + weekLabel: "Set", + allDayText: "Tot el dia", + eventLimitText: "més", + noEventsMessage: "No hi ha esdeveniments per mostrar" + }; + + return ca; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/cs.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/cs.js new file mode 100644 index 00000000..2624e360 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/cs.js @@ -0,0 +1,32 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.cs = factory())); +}(this, function () { 'use strict'; + + var cs = { + code: "cs", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "DÅ™Ãve", + next: "PozdÄ›ji", + today: "NynÃ", + month: "MÄ›sÃc", + week: "Týden", + day: "Den", + list: "Agenda" + }, + weekLabel: "Týd", + allDayText: "Celý den", + eventLimitText: function (n) { + return "+dalÅ¡Ã: " + n; + }, + noEventsMessage: "Žádné akce k zobrazenÃ" + }; + + return cs; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/da.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/da.js new file mode 100644 index 00000000..73d15592 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/da.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.da = factory())); +}(this, function () { 'use strict'; + + var da = { + code: "da", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Forrige", + next: "Næste", + today: "I dag", + month: "MÃ¥ned", + week: "Uge", + day: "Dag", + list: "Agenda" + }, + weekLabel: "Uge", + allDayText: "Hele dagen", + eventLimitText: "flere", + noEventsMessage: "Ingen arrangementer at vise" + }; + + return da; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/de.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/de.js new file mode 100644 index 00000000..ab5a815a --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/de.js @@ -0,0 +1,33 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.de = factory())); +}(this, function () { 'use strict'; + + var de = { + code: "de", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Zurück", + next: "Vor", + today: "Heute", + year: "Jahr", + month: "Monat", + week: "Woche", + day: "Tag", + list: "Terminübersicht" + }, + weekLabel: "KW", + allDayText: "Ganztägig", + eventLimitText: function (n) { + return "+ weitere " + n; + }, + noEventsMessage: "Keine Ereignisse anzuzeigen" + }; + + return de; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/el.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/el.js new file mode 100644 index 00000000..9f59e365 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/el.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.el = factory())); +}(this, function () { 'use strict'; + + var el = { + code: "el", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4st is the first week of the year. + }, + buttonText: { + prev: "Î ÏοηγοÏμενος", + next: "Επόμενος", + today: "ΣήμεÏα", + month: "Μήνας", + week: "Εβδομάδα", + day: "ΗμÎÏα", + list: "ΑτζÎντα" + }, + weekLabel: "Εβδ", + allDayText: "ΟλοήμεÏο", + eventLimitText: "πεÏισσότεÏα", + noEventsMessage: "Δεν υπάÏχουν γεγονότα για να εμφανιστεί" + }; + + return el; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/en-au.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/en-au.js new file mode 100644 index 00000000..be10bfb6 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/en-au.js @@ -0,0 +1,17 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales['en-au'] = factory())); +}(this, function () { 'use strict'; + + var enAu = { + code: "en-au", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + } + }; + + return enAu; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/en-gb.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/en-gb.js new file mode 100644 index 00000000..8a4a84e6 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/en-gb.js @@ -0,0 +1,17 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales['en-gb'] = factory())); +}(this, function () { 'use strict'; + + var enGb = { + code: "en-gb", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + } + }; + + return enGb; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/en-nz.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/en-nz.js new file mode 100644 index 00000000..df56c145 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/en-nz.js @@ -0,0 +1,17 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales['en-nz'] = factory())); +}(this, function () { 'use strict'; + + var enNz = { + code: "en-nz", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + } + }; + + return enNz; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/es-us.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/es-us.js new file mode 100644 index 00000000..1efa89a4 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/es-us.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales['es-us'] = factory())); +}(this, function () { 'use strict'; + + var esUs = { + code: "es", + week: { + dow: 0, + doy: 6 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "Ant", + next: "Sig", + today: "Hoy", + month: "Mes", + week: "Semana", + day: "DÃa", + list: "Agenda" + }, + weekLabel: "Sm", + allDayHtml: "Todo<br/>el dÃa", + eventLimitText: "más", + noEventsMessage: "No hay eventos para mostrar" + }; + + return esUs; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/es.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/es.js new file mode 100644 index 00000000..bfd9af4c --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/es.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.es = factory())); +}(this, function () { 'use strict'; + + var es = { + code: "es", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Ant", + next: "Sig", + today: "Hoy", + month: "Mes", + week: "Semana", + day: "DÃa", + list: "Agenda" + }, + weekLabel: "Sm", + allDayHtml: "Todo<br/>el dÃa", + eventLimitText: "más", + noEventsMessage: "No hay eventos para mostrar" + }; + + return es; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/et.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/et.js new file mode 100644 index 00000000..c44fcaec --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/et.js @@ -0,0 +1,32 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.et = factory())); +}(this, function () { 'use strict'; + + var et = { + code: "et", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Eelnev", + next: "Järgnev", + today: "Täna", + month: "Kuu", + week: "Nädal", + day: "Päev", + list: "Päevakord" + }, + weekLabel: "näd", + allDayText: "Kogu päev", + eventLimitText: function (n) { + return "+ veel " + n; + }, + noEventsMessage: "Kuvamiseks puuduvad sündmused" + }; + + return et; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/eu.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/eu.js new file mode 100644 index 00000000..91903aaa --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/eu.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.eu = factory())); +}(this, function () { 'use strict'; + + var eu = { + code: "eu", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "Aur", + next: "Hur", + today: "Gaur", + month: "Hilabetea", + week: "Astea", + day: "Eguna", + list: "Agenda" + }, + weekLabel: "As", + allDayHtml: "Egun<br/>osoa", + eventLimitText: "gehiago", + noEventsMessage: "Ez dago ekitaldirik erakusteko" + }; + + return eu; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/fa.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/fa.js new file mode 100644 index 00000000..031fc7b3 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/fa.js @@ -0,0 +1,33 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.fa = factory())); +}(this, function () { 'use strict'; + + var fa = { + code: "fa", + week: { + dow: 6, + doy: 12 // The week that contains Jan 1st is the first week of the year. + }, + dir: 'rtl', + buttonText: { + prev: "قبلی", + next: "بعدی", + today: "امروز", + month: "ماه", + week: "Ù‡Ùته", + day: "روز", + list: "برنامه" + }, + weekLabel: "Ù‡Ù", + allDayText: "تمام روز", + eventLimitText: function (n) { + return "بیش از " + n; + }, + noEventsMessage: "هیچ رویدادی به نمایش" + }; + + return fa; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/fi.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/fi.js new file mode 100644 index 00000000..3912845c --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/fi.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.fi = factory())); +}(this, function () { 'use strict'; + + var fi = { + code: "fi", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Edellinen", + next: "Seuraava", + today: "Tänään", + month: "Kuukausi", + week: "Viikko", + day: "Päivä", + list: "Tapahtumat" + }, + weekLabel: "Vk", + allDayText: "Koko päivä", + eventLimitText: "lisää", + noEventsMessage: "Ei näytettäviä tapahtumia" + }; + + return fi; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/fr-ca.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/fr-ca.js new file mode 100644 index 00000000..d554c140 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/fr-ca.js @@ -0,0 +1,27 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales['fr-ca'] = factory())); +}(this, function () { 'use strict'; + + var frCa = { + code: "fr", + buttonText: { + prev: "Précédent", + next: "Suivant", + today: "Aujourd'hui", + year: "Année", + month: "Mois", + week: "Semaine", + day: "Jour", + list: "Mon planning" + }, + weekLabel: "Sem.", + allDayHtml: "Toute la<br/>journée", + eventLimitText: "en plus", + noEventsMessage: "Aucun événement à afficher" + }; + + return frCa; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/fr-ch.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/fr-ch.js new file mode 100644 index 00000000..358b8bf3 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/fr-ch.js @@ -0,0 +1,31 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales['fr-ch'] = factory())); +}(this, function () { 'use strict'; + + var frCh = { + code: "fr-ch", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Précédent", + next: "Suivant", + today: "Courant", + year: "Année", + month: "Mois", + week: "Semaine", + day: "Jour", + list: "Mon planning" + }, + weekLabel: "Sm", + allDayHtml: "Toute la<br/>journée", + eventLimitText: "en plus", + noEventsMessage: "Aucun événement à afficher" + }; + + return frCh; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/fr.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/fr.js new file mode 100644 index 00000000..b679ceff --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/fr.js @@ -0,0 +1,31 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.fr = factory())); +}(this, function () { 'use strict'; + + var fr = { + code: "fr", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Précédent", + next: "Suivant", + today: "Aujourd'hui", + year: "Année", + month: "Mois", + week: "Semaine", + day: "Jour", + list: "Mon planning" + }, + weekLabel: "Sem.", + allDayHtml: "Toute la<br/>journée", + eventLimitText: "en plus", + noEventsMessage: "Aucun événement à afficher" + }; + + return fr; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/gl.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/gl.js new file mode 100644 index 00000000..721a6a89 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/gl.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.gl = factory())); +}(this, function () { 'use strict'; + + var gl = { + code: "gl", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Ant", + next: "Seg", + today: "Hoxe", + month: "Mes", + week: "Semana", + day: "DÃa", + list: "Axenda" + }, + weekLabel: "Sm", + allDayHtml: "Todo<br/>o dÃa", + eventLimitText: "máis", + noEventsMessage: "Non hai eventos para amosar" + }; + + return gl; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/he.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/he.js new file mode 100644 index 00000000..3521d9e3 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/he.js @@ -0,0 +1,27 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.he = factory())); +}(this, function () { 'use strict'; + + var he = { + code: "he", + dir: 'rtl', + buttonText: { + prev: "הקוד×", + next: "הב×", + today: "היו×", + month: "חודש", + week: "שבוע", + day: "יו×", + list: "סדר יו×" + }, + allDayText: "כל היו×", + eventLimitText: "×חר", + noEventsMessage: "×ין ××™×¨×•×¢×™× ×œ×”×¦×’×”", + weekLabel: "שבוע" + }; + + return he; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/hi.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/hi.js new file mode 100644 index 00000000..15348e69 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/hi.js @@ -0,0 +1,32 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.hi = factory())); +}(this, function () { 'use strict'; + + var hi = { + code: "hi", + week: { + dow: 0, + doy: 6 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "पिछला", + next: "अगला", + today: "आज", + month: "महीना", + week: "सपà¥à¤¤à¤¾à¤¹", + day: "दिन", + list: "कारà¥à¤¯à¤¸à¥‚ची" + }, + weekLabel: "हफà¥à¤¤à¤¾", + allDayText: "सà¤à¥€ दिन", + eventLimitText: function (n) { + return "+अधिक " + n; + }, + noEventsMessage: "कोई घटनाओं को पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ करने के लिà¤" + }; + + return hi; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/hr.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/hr.js new file mode 100644 index 00000000..295b4856 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/hr.js @@ -0,0 +1,32 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.hr = factory())); +}(this, function () { 'use strict'; + + var hr = { + code: "hr", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "PrijaÅ¡nji", + next: "Sljedeći", + today: "Danas", + month: "Mjesec", + week: "Tjedan", + day: "Dan", + list: "Raspored" + }, + weekLabel: "Tje", + allDayText: "Cijeli dan", + eventLimitText: function (n) { + return "+ joÅ¡ " + n; + }, + noEventsMessage: "Nema dogaÄ‘aja za prikaz" + }; + + return hr; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/hu.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/hu.js new file mode 100644 index 00000000..2f0fe8ac --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/hu.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.hu = factory())); +}(this, function () { 'use strict'; + + var hu = { + code: "hu", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "vissza", + next: "elÅ‘re", + today: "ma", + month: "Hónap", + week: "Hét", + day: "Nap", + list: "Napló" + }, + weekLabel: "Hét", + allDayText: "Egész nap", + eventLimitText: "további", + noEventsMessage: "Nincs megjelenÃthetÅ‘ esemény" + }; + + return hu; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/id.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/id.js new file mode 100644 index 00000000..b742e80d --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/id.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.id = factory())); +}(this, function () { 'use strict'; + + var id = { + code: "id", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "mundur", + next: "maju", + today: "hari ini", + month: "Bulan", + week: "Minggu", + day: "Hari", + list: "Agenda" + }, + weekLabel: "Mg", + allDayHtml: "Sehari<br/>penuh", + eventLimitText: "lebih", + noEventsMessage: "Tidak ada acara untuk ditampilkan" + }; + + return id; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/is.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/is.js new file mode 100644 index 00000000..dd569bce --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/is.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.is = factory())); +}(this, function () { 'use strict'; + + var is = { + code: "is", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Fyrri", + next: "Næsti", + today: "à dag", + month: "Mánuður", + week: "Vika", + day: "Dagur", + list: "Dagskrá" + }, + weekLabel: "Vika", + allDayHtml: "Allan<br/>daginn", + eventLimitText: "meira", + noEventsMessage: "Engir viðburðir til að sýna" + }; + + return is; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/it.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/it.js new file mode 100644 index 00000000..39a2829e --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/it.js @@ -0,0 +1,32 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.it = factory())); +}(this, function () { 'use strict'; + + var it = { + code: "it", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Prec", + next: "Succ", + today: "Oggi", + month: "Mese", + week: "Settimana", + day: "Giorno", + list: "Agenda" + }, + weekLabel: "Sm", + allDayHtml: "Tutto il<br/>giorno", + eventLimitText: function (n) { + return "+altri " + n; + }, + noEventsMessage: "Non ci sono eventi da visualizzare" + }; + + return it; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/ja.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/ja.js new file mode 100644 index 00000000..eb4245b2 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/ja.js @@ -0,0 +1,28 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.ja = factory())); +}(this, function () { 'use strict'; + + var ja = { + code: "ja", + buttonText: { + prev: "å‰", + next: "次", + today: "今日", + month: "月", + week: "週", + day: "æ—¥", + list: "予定リスト" + }, + weekLabel: "週", + allDayText: "終日", + eventLimitText: function (n) { + return "ä»– " + n + " 件"; + }, + noEventsMessage: "表示ã™ã‚‹äºˆå®šã¯ã‚ã‚Šã¾ã›ã‚“" + }; + + return ja; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/ka.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/ka.js new file mode 100644 index 00000000..b971c033 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/ka.js @@ -0,0 +1,32 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.ka = factory())); +}(this, function () { 'use strict'; + + var ka = { + code: "ka", + week: { + dow: 1, + doy: 7 + }, + buttonText: { + prev: "წინáƒ", + next: "შემდეგი", + today: "დღეს", + month: "თვე", + week: "კვირáƒ", + day: "დღე", + list: "დღის წესრიგი" + }, + weekLabel: "კვ", + allDayText: "მთელი დღე", + eventLimitText: function (n) { + return "+ კიდევ " + n; + }, + noEventsMessage: "ღáƒáƒœáƒ˜áƒ¡áƒ«áƒ˜áƒ”ბები áƒáƒ áƒáƒ ის" + }; + + return ka; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/kk.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/kk.js new file mode 100644 index 00000000..5b19b99d --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/kk.js @@ -0,0 +1,32 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.kk = factory())); +}(this, function () { 'use strict'; + + var kk = { + code: "kk", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "Ðлдыңғы", + next: "КелеÑÑ–", + today: "Бүгін", + month: "Ðй", + week: "Ðпта", + day: "Күн", + list: "Күн тәртібі" + }, + weekLabel: "Ðе", + allDayText: "Күні бойы", + eventLimitText: function (n) { + return "+ тағы " + n; + }, + noEventsMessage: "КөрÑету үшін оқиғалар жоқ" + }; + + return kk; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/ko.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/ko.js new file mode 100644 index 00000000..ffe985d6 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/ko.js @@ -0,0 +1,26 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.ko = factory())); +}(this, function () { 'use strict'; + + var ko = { + code: "ko", + buttonText: { + prev: "ì´ì „달", + next: "다ìŒë‹¬", + today: "오늘", + month: "ì›”", + week: "주", + day: "ì¼", + list: "ì¼ì •ëª©ë¡" + }, + weekLabel: "주", + allDayText: "종ì¼", + eventLimitText: "ê°œ", + noEventsMessage: "ì¼ì •ì´ 없습니다" + }; + + return ko; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/lb.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/lb.js new file mode 100644 index 00000000..b9b17e3e --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/lb.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.lb = factory())); +}(this, function () { 'use strict'; + + var lb = { + code: "lb", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Zréck", + next: "Weider", + today: "Haut", + month: "Mount", + week: "Woch", + day: "Dag", + list: "Terminiwwersiicht" + }, + weekLabel: "W", + allDayText: "Ganzen Dag", + eventLimitText: "méi", + noEventsMessage: "Nee Evenementer ze affichéieren" + }; + + return lb; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/lt.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/lt.js new file mode 100644 index 00000000..ec641b75 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/lt.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.lt = factory())); +}(this, function () { 'use strict'; + + var lt = { + code: "lt", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Atgal", + next: "Pirmyn", + today: "Å iandien", + month: "MÄ—nuo", + week: "SavaitÄ—", + day: "Diena", + list: "DarbotvarkÄ—" + }, + weekLabel: "SAV", + allDayText: "VisÄ… dienÄ…", + eventLimitText: "daugiau", + noEventsMessage: "NÄ—ra įvykių rodyti" + }; + + return lt; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/lv.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/lv.js new file mode 100644 index 00000000..5453630d --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/lv.js @@ -0,0 +1,32 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.lv = factory())); +}(this, function () { 'use strict'; + + var lv = { + code: "lv", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Iepr.", + next: "NÄk.", + today: "Å odien", + month: "MÄ“nesis", + week: "Nedēļa", + day: "Diena", + list: "Dienas kÄrtÄ«ba" + }, + weekLabel: "Ned.", + allDayText: "Visu dienu", + eventLimitText: function (n) { + return "+vÄ“l " + n; + }, + noEventsMessage: "Nav notikumu" + }; + + return lv; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/mk.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/mk.js new file mode 100644 index 00000000..6729fa63 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/mk.js @@ -0,0 +1,28 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.mk = factory())); +}(this, function () { 'use strict'; + + var mk = { + code: "mk", + buttonText: { + prev: "претходно", + next: "Ñледно", + today: "ДенеÑ", + month: "МеÑец", + week: "Ðедела", + day: "Ден", + list: "График" + }, + weekLabel: "Сед", + allDayText: "Цел ден", + eventLimitText: function (n) { + return "+повеќе " + n; + }, + noEventsMessage: "Ðема наÑтани за прикажување" + }; + + return mk; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/ms.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/ms.js new file mode 100644 index 00000000..7205ecc7 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/ms.js @@ -0,0 +1,32 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.ms = factory())); +}(this, function () { 'use strict'; + + var ms = { + code: "ms", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "Sebelum", + next: "Selepas", + today: "hari ini", + month: "Bulan", + week: "Minggu", + day: "Hari", + list: "Agenda" + }, + weekLabel: "Mg", + allDayText: "Sepanjang hari", + eventLimitText: function (n) { + return "masih ada " + n + " acara"; + }, + noEventsMessage: "Tiada peristiwa untuk dipaparkan" + }; + + return ms; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/nb.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/nb.js new file mode 100644 index 00000000..6464461c --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/nb.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.nb = factory())); +}(this, function () { 'use strict'; + + var nb = { + code: "nb", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Forrige", + next: "Neste", + today: "I dag", + month: "MÃ¥ned", + week: "Uke", + day: "Dag", + list: "Agenda" + }, + weekLabel: "Uke", + allDayText: "Hele dagen", + eventLimitText: "til", + noEventsMessage: "Ingen hendelser Ã¥ vise" + }; + + return nb; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/nl.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/nl.js new file mode 100644 index 00000000..c91b5e55 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/nl.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.nl = factory())); +}(this, function () { 'use strict'; + + var nl = { + code: "nl", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Voorgaand", + next: "Volgende", + today: "Vandaag", + year: "Jaar", + month: "Maand", + week: "Week", + day: "Dag", + list: "Agenda" + }, + allDayText: "Hele dag", + eventLimitText: "extra", + noEventsMessage: "Geen evenementen om te laten zien" + }; + + return nl; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/nn.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/nn.js new file mode 100644 index 00000000..a5cdd162 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/nn.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.nn = factory())); +}(this, function () { 'use strict'; + + var nn = { + code: "nn", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Førre", + next: "Neste", + today: "I dag", + month: "MÃ¥nad", + week: "Veke", + day: "Dag", + list: "Agenda" + }, + weekLabel: "Veke", + allDayText: "Heile dagen", + eventLimitText: "til", + noEventsMessage: "Ingen hendelser Ã¥ vise" + }; + + return nn; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/pl.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/pl.js new file mode 100644 index 00000000..0a22e69c --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/pl.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.pl = factory())); +}(this, function () { 'use strict'; + + var pl = { + code: "pl", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Poprzedni", + next: "NastÄ™pny", + today: "DziÅ›", + month: "MiesiÄ…c", + week: "TydzieÅ„", + day: "DzieÅ„", + list: "Plan dnia" + }, + weekLabel: "Tydz", + allDayText: "CaÅ‚y dzieÅ„", + eventLimitText: "wiÄ™cej", + noEventsMessage: "Brak wydarzeÅ„ do wyÅ›wietlenia" + }; + + return pl; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/pt-br.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/pt-br.js new file mode 100644 index 00000000..0133cd6b --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/pt-br.js @@ -0,0 +1,28 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales['pt-br'] = factory())); +}(this, function () { 'use strict'; + + var ptBr = { + code: "pt-br", + buttonText: { + prev: "Anterior", + next: "Próximo", + today: "Hoje", + month: "Mês", + week: "Semana", + day: "Dia", + list: "Compromissos" + }, + weekLabel: "Sm", + allDayText: "dia inteiro", + eventLimitText: function (n) { + return "mais +" + n; + }, + noEventsMessage: "Não há eventos para mostrar" + }; + + return ptBr; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/pt.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/pt.js new file mode 100644 index 00000000..5c54d8d4 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/pt.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.pt = factory())); +}(this, function () { 'use strict'; + + var pt = { + code: "pt", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Anterior", + next: "Seguinte", + today: "Hoje", + month: "Mês", + week: "Semana", + day: "Dia", + list: "Agenda" + }, + weekLabel: "Sem", + allDayText: "Todo o dia", + eventLimitText: "mais", + noEventsMessage: "Não há eventos para mostrar" + }; + + return pt; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/ro.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/ro.js new file mode 100644 index 00000000..e8992f27 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/ro.js @@ -0,0 +1,32 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.ro = factory())); +}(this, function () { 'use strict'; + + var ro = { + code: "ro", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "precedentă", + next: "următoare", + today: "Azi", + month: "Lună", + week: "Săptămână", + day: "Zi", + list: "Agendă" + }, + weekLabel: "Săpt", + allDayText: "Toată ziua", + eventLimitText: function (n) { + return "+alte " + n; + }, + noEventsMessage: "Nu există evenimente de afiÈ™at" + }; + + return ro; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/ru.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/ru.js new file mode 100644 index 00000000..77e0308e --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/ru.js @@ -0,0 +1,32 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.ru = factory())); +}(this, function () { 'use strict'; + + var ru = { + code: "ru", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Пред", + next: "След", + today: "СегоднÑ", + month: "МеÑÑц", + week: "ÐеделÑ", + day: "День", + list: "ПовеÑтка днÑ" + }, + weekLabel: "Ðед", + allDayText: "ВеÑÑŒ день", + eventLimitText: function (n) { + return "+ ещё " + n; + }, + noEventsMessage: "Ðет Ñобытий Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ" + }; + + return ru; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/sk.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/sk.js new file mode 100644 index 00000000..3513a64a --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/sk.js @@ -0,0 +1,32 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.sk = factory())); +}(this, function () { 'use strict'; + + var sk = { + code: "sk", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Predchádzajúci", + next: "Nasledujúci", + today: "Dnes", + month: "Mesiac", + week: "Týždeň", + day: "Deň", + list: "Rozvrh" + }, + weekLabel: "Ty", + allDayText: "Celý deň", + eventLimitText: function (n) { + return "+ÄalÅ¡ie: " + n; + }, + noEventsMessage: "Žiadne akcie na zobrazenie" + }; + + return sk; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/sl.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/sl.js new file mode 100644 index 00000000..32335535 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/sl.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.sl = factory())); +}(this, function () { 'use strict'; + + var sl = { + code: "sl", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "PrejÅ¡nji", + next: "Naslednji", + today: "Trenutni", + month: "Mesec", + week: "Teden", + day: "Dan", + list: "Dnevni red" + }, + weekLabel: "Teden", + allDayText: "Ves dan", + eventLimitText: "veÄ", + noEventsMessage: "Ni dogodkov za prikaz" + }; + + return sl; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/sq.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/sq.js new file mode 100644 index 00000000..0d43a522 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/sq.js @@ -0,0 +1,32 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.sq = factory())); +}(this, function () { 'use strict'; + + var sq = { + code: "sq", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "mbrapa", + next: "Përpara", + today: "sot", + month: "Muaj", + week: "Javë", + day: "Ditë", + list: "Listë" + }, + weekLabel: "Ja", + allDayHtml: "Gjithë<br/>ditën", + eventLimitText: function (n) { + return "+më tepër " + n; + }, + noEventsMessage: "Nuk ka evente për të shfaqur" + }; + + return sq; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/sr-cyrl.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/sr-cyrl.js new file mode 100644 index 00000000..ba0d0dfa --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/sr-cyrl.js @@ -0,0 +1,32 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales['sr-cyrl'] = factory())); +}(this, function () { 'use strict'; + + var srCyrl = { + code: "sr-cyrl", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "Претходна", + next: "Ñледећи", + today: "ДанаÑ", + month: "МеÑец", + week: "Ðедеља", + day: "Дан", + list: "Планер" + }, + weekLabel: "Сед", + allDayText: "Цео дан", + eventLimitText: function (n) { + return "+ још " + n; + }, + noEventsMessage: "Ðема догађаја за приказ" + }; + + return srCyrl; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/sr.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/sr.js new file mode 100644 index 00000000..23e5c9b2 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/sr.js @@ -0,0 +1,32 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.sr = factory())); +}(this, function () { 'use strict'; + + var sr = { + code: "sr", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "Prethodna", + next: "SledecÌi", + today: "Danas", + month: "Mеsеc", + week: "Nеdеlja", + day: "Dan", + list: "Planеr" + }, + weekLabel: "Sed", + allDayText: "Cеo dan", + eventLimitText: function (n) { + return "+ joÅ¡ " + n; + }, + noEventsMessage: "Nеma dogaÄ‘aja za prikaz" + }; + + return sr; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/sv.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/sv.js new file mode 100644 index 00000000..a887060b --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/sv.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.sv = factory())); +}(this, function () { 'use strict'; + + var sv = { + code: "sv", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "Förra", + next: "Nästa", + today: "Idag", + month: "MÃ¥nad", + week: "Vecka", + day: "Dag", + list: "Program" + }, + weekLabel: "v.", + allDayText: "Heldag", + eventLimitText: "till", + noEventsMessage: "Inga händelser att visa" + }; + + return sv; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/th.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/th.js new file mode 100644 index 00000000..caa3fe9a --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/th.js @@ -0,0 +1,25 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.th = factory())); +}(this, function () { 'use strict'; + + var th = { + code: "th", + buttonText: { + prev: "ย้à¸à¸™", + next: "ถัดไป", + today: "วันนี้", + month: "เดืà¸à¸™", + week: "สัปดาห์", + day: "วัน", + list: "à¹à¸œà¸™à¸‡à¸²à¸™" + }, + allDayText: "ตลà¸à¸”วัน", + eventLimitText: "เพิ่มเติม", + noEventsMessage: "ไม่มีà¸à¸´à¸ˆà¸à¸£à¸£à¸¡à¸—ี่จะà¹à¸ªà¸”ง" + }; + + return th; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/tr.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/tr.js new file mode 100644 index 00000000..48458982 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/tr.js @@ -0,0 +1,30 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.tr = factory())); +}(this, function () { 'use strict'; + + var tr = { + code: "tr", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "geri", + next: "ileri", + today: "bugün", + month: "Ay", + week: "Hafta", + day: "Gün", + list: "Ajanda" + }, + weekLabel: "Hf", + allDayText: "Tüm gün", + eventLimitText: "daha fazla", + noEventsMessage: "Gösterilecek etkinlik yok" + }; + + return tr; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/uk.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/uk.js new file mode 100644 index 00000000..de33f250 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/uk.js @@ -0,0 +1,32 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.uk = factory())); +}(this, function () { 'use strict'; + + var uk = { + code: "uk", + week: { + dow: 1, + doy: 7 // The week that contains Jan 1st is the first week of the year. + }, + buttonText: { + prev: "Попередній", + next: "далі", + today: "Сьогодні", + month: "МіÑÑць", + week: "Тиждень", + day: "День", + list: "ПорÑдок денний" + }, + weekLabel: "Тиж", + allDayText: "УвеÑÑŒ день", + eventLimitText: function (n) { + return "+ще " + n + "..."; + }, + noEventsMessage: "Ðемає подій Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ" + }; + + return uk; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/vi.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/vi.js new file mode 100644 index 00000000..167ce11d --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/vi.js @@ -0,0 +1,32 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales.vi = factory())); +}(this, function () { 'use strict'; + + var vi = { + code: "vi", + week: { + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "TrÆ°á»›c", + next: "Tiếp", + today: "Hôm nay", + month: "Tháng", + week: "Tuần", + day: "Ngà y", + list: "Lịch biểu" + }, + weekLabel: "Tu", + allDayText: "Cả ngà y", + eventLimitText: function (n) { + return "+ thêm " + n; + }, + noEventsMessage: "Không có sá»± kiện để hiển thị" + }; + + return vi; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/zh-cn.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/zh-cn.js new file mode 100644 index 00000000..4debbb9e --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/zh-cn.js @@ -0,0 +1,33 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales['zh-cn'] = factory())); +}(this, function () { 'use strict'; + + var zhCn = { + code: "zh-cn", + week: { + // GB/T 7408-1994《数æ®å…ƒå’Œäº¤æ¢æ ¼å¼Â·ä¿¡æ¯äº¤æ¢Â·æ—¥æœŸå’Œæ—¶é—´è¡¨ç¤ºæ³•ã€‹ä¸ŽISO 8601:1988ç‰æ•ˆ + dow: 1, + doy: 4 // The week that contains Jan 4th is the first week of the year. + }, + buttonText: { + prev: "上月", + next: "下月", + today: "今天", + month: "月", + week: "周", + day: "æ—¥", + list: "日程" + }, + weekLabel: "周", + allDayText: "全天", + eventLimitText: function (n) { + return "å¦å¤– " + n + " 个"; + }, + noEventsMessage: "没有事件显示" + }; + + return zhCn; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/locales/zh-tw.js b/AKPlan/static/AKPlan/fullcalendar/core/locales/zh-tw.js new file mode 100644 index 00000000..bc14dcd4 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/locales/zh-tw.js @@ -0,0 +1,26 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, (global.FullCalendarLocales = global.FullCalendarLocales || {}, global.FullCalendarLocales['zh-tw'] = factory())); +}(this, function () { 'use strict'; + + var zhTw = { + code: "zh-tw", + buttonText: { + prev: "上月", + next: "下月", + today: "今天", + month: "月", + week: "週", + day: "天", + list: "活動列表" + }, + weekLabel: "周", + allDayText: "整天", + eventLimitText: '顯示更多', + noEventsMessage: "没有任何活動" + }; + + return zhTw; + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/main.css b/AKPlan/static/AKPlan/fullcalendar/core/main.css new file mode 100644 index 00000000..4412a185 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/main.css @@ -0,0 +1,1052 @@ +@charset "UTF-8"; +.fc { + direction: ltr; + text-align: left; +} + +.fc-rtl { + text-align: right; +} + +body .fc { + /* extra precedence to overcome jqui */ + font-size: 1em; +} + +/* Colors +--------------------------------------------------------------------------------------------------*/ +.fc-highlight { + /* when user is selecting cells */ + background: #bce8f1; + opacity: 0.3; +} + +.fc-bgevent { + /* default look for background events */ + background: #8fdf82; + opacity: 0.3; +} + +.fc-nonbusiness { + /* default look for non-business-hours areas */ + /* will inherit .fc-bgevent's styles */ + background: #d7d7d7; +} + +/* Popover +--------------------------------------------------------------------------------------------------*/ +.fc-popover { + position: absolute; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15); +} + +.fc-popover .fc-header { + /* TODO: be more consistent with fc-head/fc-body */ + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + padding: 2px 4px; +} + +.fc-rtl .fc-popover .fc-header { + flex-direction: row-reverse; +} + +.fc-popover .fc-header .fc-title { + margin: 0 2px; +} + +.fc-popover .fc-header .fc-close { + cursor: pointer; + opacity: 0.65; + font-size: 1.1em; +} + +/* Misc Reusable Components +--------------------------------------------------------------------------------------------------*/ +.fc-divider { + border-style: solid; + border-width: 1px; +} + +hr.fc-divider { + height: 0; + margin: 0; + padding: 0 0 2px; + /* height is unreliable across browsers, so use padding */ + border-width: 1px 0; +} + +.fc-bg, +.fc-bgevent-skeleton, +.fc-highlight-skeleton, +.fc-mirror-skeleton { + /* these element should always cling to top-left/right corners */ + position: absolute; + top: 0; + left: 0; + right: 0; +} + +.fc-bg { + bottom: 0; + /* strech bg to bottom edge */ +} + +.fc-bg table { + height: 100%; + /* strech bg to bottom edge */ +} + +/* Tables +--------------------------------------------------------------------------------------------------*/ +.fc table { + width: 100%; + box-sizing: border-box; + /* fix scrollbar issue in firefox */ + table-layout: fixed; + border-collapse: collapse; + border-spacing: 0; + font-size: 1em; + /* normalize cross-browser */ +} + +.fc th { + text-align: center; +} + +.fc th, +.fc td { + border-style: solid; + border-width: 1px; + padding: 0; + vertical-align: top; +} + +.fc td.fc-today { + border-style: double; + /* overcome neighboring borders */ +} + +/* Internal Nav Links +--------------------------------------------------------------------------------------------------*/ +a[data-goto] { + cursor: pointer; +} + +a[data-goto]:hover { + text-decoration: underline; +} + +/* Fake Table Rows +--------------------------------------------------------------------------------------------------*/ +.fc .fc-row { + /* extra precedence to overcome themes forcing a 1px border */ + /* no visible border by default. but make available if need be (scrollbar width compensation) */ + border-style: solid; + border-width: 0; +} + +.fc-row table { + /* don't put left/right border on anything within a fake row. + the outer tbody will worry about this */ + border-left: 0 hidden transparent; + border-right: 0 hidden transparent; + /* no bottom borders on rows */ + border-bottom: 0 hidden transparent; +} + +.fc-row:first-child table { + border-top: 0 hidden transparent; + /* no top border on first row */ +} + +/* Day Row (used within the header and the DayGrid) +--------------------------------------------------------------------------------------------------*/ +.fc-row { + position: relative; +} + +.fc-row .fc-bg { + z-index: 1; +} + +/* highlighting cells & background event skeleton */ +.fc-row .fc-bgevent-skeleton, +.fc-row .fc-highlight-skeleton { + bottom: 0; + /* stretch skeleton to bottom of row */ +} + +.fc-row .fc-bgevent-skeleton table, +.fc-row .fc-highlight-skeleton table { + height: 100%; + /* stretch skeleton to bottom of row */ +} + +.fc-row .fc-highlight-skeleton td, +.fc-row .fc-bgevent-skeleton td { + border-color: transparent; +} + +.fc-row .fc-bgevent-skeleton { + z-index: 2; +} + +.fc-row .fc-highlight-skeleton { + z-index: 3; +} + +/* +row content (which contains day/week numbers and events) as well as "mirror" (which contains +temporary rendered events). +*/ +.fc-row .fc-content-skeleton { + position: relative; + z-index: 4; + padding-bottom: 2px; + /* matches the space above the events */ +} + +.fc-row .fc-mirror-skeleton { + z-index: 5; +} + +.fc .fc-row .fc-content-skeleton table, +.fc .fc-row .fc-content-skeleton td, +.fc .fc-row .fc-mirror-skeleton td { + /* see-through to the background below */ + /* extra precedence to prevent theme-provided backgrounds */ + background: none; + /* in case <td>s are globally styled */ + border-color: transparent; +} + +.fc-row .fc-content-skeleton td, +.fc-row .fc-mirror-skeleton td { + /* don't put a border between events and/or the day number */ + border-bottom: 0; +} + +.fc-row .fc-content-skeleton tbody td, +.fc-row .fc-mirror-skeleton tbody td { + /* don't put a border between event cells */ + border-top: 0; +} + +/* Scrolling Container +--------------------------------------------------------------------------------------------------*/ +.fc-scroller { + -webkit-overflow-scrolling: touch; +} + +/* TODO: move to timegrid/daygrid */ +.fc-scroller > .fc-day-grid, +.fc-scroller > .fc-time-grid { + position: relative; + /* re-scope all positions */ + width: 100%; + /* hack to force re-sizing this inner element when scrollbars appear/disappear */ +} + +/* Global Event Styles +--------------------------------------------------------------------------------------------------*/ +.fc-event { + position: relative; + /* for resize handle and other inner positioning */ + display: block; + /* make the <a> tag block */ + font-size: 0.85em; + line-height: 1.4; + border-radius: 3px; + border: 1px solid #3788d8; +} + +.fc-event, +.fc-event-dot { + background-color: #3788d8; + /* default BACKGROUND color */ +} + +.fc-event, +.fc-event:hover { + color: #fff; + /* default TEXT color */ + text-decoration: none; + /* if <a> has an href */ +} + +.fc-event[href], +.fc-event.fc-draggable { + cursor: pointer; + /* give events with links and draggable events a hand mouse pointer */ +} + +.fc-not-allowed, +.fc-not-allowed .fc-event { + /* to override an event's custom cursor */ + cursor: not-allowed; +} + +.fc-event .fc-content { + position: relative; + z-index: 2; +} + +/* resizer (cursor AND touch devices) */ +.fc-event .fc-resizer { + position: absolute; + z-index: 4; +} + +/* resizer (touch devices) */ +.fc-event .fc-resizer { + display: none; +} + +.fc-event.fc-allow-mouse-resize .fc-resizer, +.fc-event.fc-selected .fc-resizer { + /* only show when hovering or selected (with touch) */ + display: block; +} + +/* hit area */ +.fc-event.fc-selected .fc-resizer:before { + /* 40x40 touch area */ + content: ""; + position: absolute; + z-index: 9999; + /* user of this util can scope within a lower z-index */ + top: 50%; + left: 50%; + width: 40px; + height: 40px; + margin-left: -20px; + margin-top: -20px; +} + +/* Event Selection (only for touch devices) +--------------------------------------------------------------------------------------------------*/ +.fc-event.fc-selected { + z-index: 9999 !important; + /* overcomes inline z-index */ + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); +} + +.fc-event.fc-selected:after { + content: ""; + position: absolute; + z-index: 1; + /* same z-index as fc-bg, behind text */ + /* overcome the borders */ + top: -1px; + right: -1px; + bottom: -1px; + left: -1px; + /* darkening effect */ + background: #000; + opacity: 0.25; +} + +/* Event Dragging +--------------------------------------------------------------------------------------------------*/ +.fc-event.fc-dragging.fc-selected { + box-shadow: 0 2px 7px rgba(0, 0, 0, 0.3); +} + +.fc-event.fc-dragging:not(.fc-selected) { + opacity: 0.75; +} + +/* Horizontal Events +--------------------------------------------------------------------------------------------------*/ +/* bigger touch area when selected */ +.fc-h-event.fc-selected:before { + content: ""; + position: absolute; + z-index: 3; + /* below resizers */ + top: -10px; + bottom: -10px; + left: 0; + right: 0; +} + +/* events that are continuing to/from another week. kill rounded corners and butt up against edge */ +.fc-ltr .fc-h-event.fc-not-start, +.fc-rtl .fc-h-event.fc-not-end { + margin-left: 0; + border-left-width: 0; + padding-left: 1px; + /* replace the border with padding */ + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.fc-ltr .fc-h-event.fc-not-end, +.fc-rtl .fc-h-event.fc-not-start { + margin-right: 0; + border-right-width: 0; + padding-right: 1px; + /* replace the border with padding */ + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +/* resizer (cursor AND touch devices) */ +/* left resizer */ +.fc-ltr .fc-h-event .fc-start-resizer, +.fc-rtl .fc-h-event .fc-end-resizer { + cursor: w-resize; + left: -1px; + /* overcome border */ +} + +/* right resizer */ +.fc-ltr .fc-h-event .fc-end-resizer, +.fc-rtl .fc-h-event .fc-start-resizer { + cursor: e-resize; + right: -1px; + /* overcome border */ +} + +/* resizer (mouse devices) */ +.fc-h-event.fc-allow-mouse-resize .fc-resizer { + width: 7px; + top: -1px; + /* overcome top border */ + bottom: -1px; + /* overcome bottom border */ +} + +/* resizer (touch devices) */ +.fc-h-event.fc-selected .fc-resizer { + /* 8x8 little dot */ + border-radius: 4px; + border-width: 1px; + width: 6px; + height: 6px; + border-style: solid; + border-color: inherit; + background: #fff; + /* vertically center */ + top: 50%; + margin-top: -4px; +} + +/* left resizer */ +.fc-ltr .fc-h-event.fc-selected .fc-start-resizer, +.fc-rtl .fc-h-event.fc-selected .fc-end-resizer { + margin-left: -4px; + /* centers the 8x8 dot on the left edge */ +} + +/* right resizer */ +.fc-ltr .fc-h-event.fc-selected .fc-end-resizer, +.fc-rtl .fc-h-event.fc-selected .fc-start-resizer { + margin-right: -4px; + /* centers the 8x8 dot on the right edge */ +} + +/* DayGrid events +---------------------------------------------------------------------------------------------------- +We use the full "fc-day-grid-event" class instead of using descendants because the event won't +be a descendant of the grid when it is being dragged. +*/ +.fc-day-grid-event { + margin: 1px 2px 0; + /* spacing between events and edges */ + padding: 0 1px; +} + +tr:first-child > td > .fc-day-grid-event { + margin-top: 2px; + /* a little bit more space before the first event */ +} + +.fc-mirror-skeleton tr:first-child > td > .fc-day-grid-event { + margin-top: 0; + /* except for mirror skeleton */ +} + +.fc-day-grid-event .fc-content { + /* force events to be one-line tall */ + white-space: nowrap; + overflow: hidden; +} + +.fc-day-grid-event .fc-time { + font-weight: bold; +} + +/* resizer (cursor devices) */ +/* left resizer */ +.fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer, +.fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer { + margin-left: -2px; + /* to the day cell's edge */ +} + +/* right resizer */ +.fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer, +.fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer { + margin-right: -2px; + /* to the day cell's edge */ +} + +/* Event Limiting +--------------------------------------------------------------------------------------------------*/ +/* "more" link that represents hidden events */ +a.fc-more { + margin: 1px 3px; + font-size: 0.85em; + cursor: pointer; + text-decoration: none; +} + +a.fc-more:hover { + text-decoration: underline; +} + +.fc-limited { + /* rows and cells that are hidden because of a "more" link */ + display: none; +} + +/* popover that appears when "more" link is clicked */ +.fc-day-grid .fc-row { + z-index: 1; + /* make the "more" popover one higher than this */ +} + +.fc-more-popover { + z-index: 2; + width: 220px; +} + +.fc-more-popover .fc-event-container { + padding: 10px; +} + +/* Now Indicator +--------------------------------------------------------------------------------------------------*/ +.fc-now-indicator { + position: absolute; + border: 0 solid red; +} + +/* Utilities +--------------------------------------------------------------------------------------------------*/ +.fc-unselectable { + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-touch-callout: none; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +/* +TODO: more distinction between this file and common.css +*/ +/* Colors +--------------------------------------------------------------------------------------------------*/ +.fc-unthemed th, +.fc-unthemed td, +.fc-unthemed thead, +.fc-unthemed tbody, +.fc-unthemed .fc-divider, +.fc-unthemed .fc-row, +.fc-unthemed .fc-content, +.fc-unthemed .fc-popover, +.fc-unthemed .fc-list-view, +.fc-unthemed .fc-list-heading td { + border-color: #ddd; +} + +.fc-unthemed .fc-popover { + background-color: #fff; +} + +.fc-unthemed .fc-divider, +.fc-unthemed .fc-popover .fc-header, +.fc-unthemed .fc-list-heading td { + background: #eee; +} + +.fc-unthemed td.fc-today { + background: #fcf8e3; +} + +.fc-unthemed .fc-disabled-day { + background: #d7d7d7; + opacity: 0.3; +} + +/* Icons +-------------------------------------------------------------------------------------------------- +from https://feathericons.com/ and built with IcoMoon +*/ +@font-face { + font-family: "fcicons"; + src: url("data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SBfAAAAC8AAAAYGNtYXAXVtKNAAABHAAAAFRnYXNwAAAAEAAAAXAAAAAIZ2x5ZgYydxIAAAF4AAAFNGhlYWQUJ7cIAAAGrAAAADZoaGVhB20DzAAABuQAAAAkaG10eCIABhQAAAcIAAAALGxvY2ED4AU6AAAHNAAAABhtYXhwAA8AjAAAB0wAAAAgbmFtZXsr690AAAdsAAABhnBvc3QAAwAAAAAI9AAAACAAAwPAAZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADpBgPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAADAAAAAwAAABwAAQADAAAAHAADAAEAAAAcAAQAOAAAAAoACAACAAIAAQAg6Qb//f//AAAAAAAg6QD//f//AAH/4xcEAAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAABAWIAjQKeAskAEwAAJSc3NjQnJiIHAQYUFwEWMjc2NCcCnuLiDQ0MJAz/AA0NAQAMJAwNDcni4gwjDQwM/wANIwz/AA0NDCMNAAAAAQFiAI0CngLJABMAACUBNjQnASYiBwYUHwEHBhQXFjI3AZ4BAA0N/wAMJAwNDeLiDQ0MJAyNAQAMIw0BAAwMDSMM4uINIwwNDQAAAAIA4gC3Ax4CngATACcAACUnNzY0JyYiDwEGFB8BFjI3NjQnISc3NjQnJiIPAQYUHwEWMjc2NCcB87e3DQ0MIw3VDQ3VDSMMDQ0BK7e3DQ0MJAzVDQ3VDCQMDQ3zuLcMJAwNDdUNIwzWDAwNIwy4twwkDA0N1Q0jDNYMDA0jDAAAAgDiALcDHgKeABMAJwAAJTc2NC8BJiIHBhQfAQcGFBcWMjchNzY0LwEmIgcGFB8BBwYUFxYyNwJJ1Q0N1Q0jDA0Nt7cNDQwjDf7V1Q0N1QwkDA0Nt7cNDQwkDLfWDCMN1Q0NDCQMt7gMIw0MDNYMIw3VDQ0MJAy3uAwjDQwMAAADAFUAAAOrA1UAMwBoAHcAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMhMjY1NCYjISIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAAVYRGRkR/qoRGRkRA1UFBAUOCQkVDAsZDf2rDRkLDBUJCA4FBQUFBQUOCQgVDAsZDQJVDRkLDBUJCQ4FBAVVAgECBQMCBwQECAX9qwQJAwQHAwMFAQICAgIBBQMDBwQDCQQCVQUIBAQHAgMFAgEC/oAZEhEZGRESGQAAAAADAFUAAAOrA1UAMwBoAIkAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMzFRQWMzI2PQEzMjY1NCYrATU0JiMiBh0BIyIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAgBkSEhmAERkZEYAZEhIZgBEZGREDVQUEBQ4JCRUMCxkN/asNGQsMFQkIDgUFBQUFBQ4JCBUMCxkNAlUNGQsMFQkJDgUEBVUCAQIFAwIHBAQIBf2rBAkDBAcDAwUBAgICAgEFAwMHBAMJBAJVBQgEBAcCAwUCAQL+gIASGRkSgBkSERmAEhkZEoAZERIZAAABAOIAjQMeAskAIAAAExcHBhQXFjI/ARcWMjc2NC8BNzY0JyYiDwEnJiIHBhQX4uLiDQ0MJAzi4gwkDA0N4uINDQwkDOLiDCQMDQ0CjeLiDSMMDQ3h4Q0NDCMN4uIMIw0MDOLiDAwNIwwAAAABAAAAAQAAa5n0y18PPPUACwQAAAAAANivOVsAAAAA2K85WwAAAAADqwNVAAAACAACAAAAAAAAAAEAAAPA/8AAAAQAAAAAAAOrAAEAAAAAAAAAAAAAAAAAAAALBAAAAAAAAAAAAAAAAgAAAAQAAWIEAAFiBAAA4gQAAOIEAABVBAAAVQQAAOIAAAAAAAoAFAAeAEQAagCqAOoBngJkApoAAQAAAAsAigADAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA4ArgABAAAAAAABAAcAAAABAAAAAAACAAcAYAABAAAAAAADAAcANgABAAAAAAAEAAcAdQABAAAAAAAFAAsAFQABAAAAAAAGAAcASwABAAAAAAAKABoAigADAAEECQABAA4ABwADAAEECQACAA4AZwADAAEECQADAA4APQADAAEECQAEAA4AfAADAAEECQAFABYAIAADAAEECQAGAA4AUgADAAEECQAKADQApGZjaWNvbnMAZgBjAGkAYwBvAG4Ac1ZlcnNpb24gMS4wAFYAZQByAHMAaQBvAG4AIAAxAC4AMGZjaWNvbnMAZgBjAGkAYwBvAG4Ac2ZjaWNvbnMAZgBjAGkAYwBvAG4Ac1JlZ3VsYXIAUgBlAGcAdQBsAGEAcmZjaWNvbnMAZgBjAGkAYwBvAG4Ac0ZvbnQgZ2VuZXJhdGVkIGJ5IEljb01vb24uAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") format("truetype"); + font-weight: normal; + font-style: normal; +} +.fc-icon { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: "fcicons" !important; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.fc-icon-chevron-left:before { + content: ""; +} + +.fc-icon-chevron-right:before { + content: "î¤"; +} + +.fc-icon-chevrons-left:before { + content: ""; +} + +.fc-icon-chevrons-right:before { + content: ""; +} + +.fc-icon-minus-square:before { + content: ""; +} + +.fc-icon-plus-square:before { + content: ""; +} + +.fc-icon-x:before { + content: ""; +} + +.fc-icon { + display: inline-block; + width: 1em; + height: 1em; + text-align: center; +} + +/* Buttons +-------------------------------------------------------------------------------------------------- +Lots taken from Flatly (MIT): https://bootswatch.com/4/flatly/bootstrap.css +*/ +/* reset */ +.fc-button { + border-radius: 0; + overflow: visible; + text-transform: none; + margin: 0; + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +.fc-button:focus { + outline: 1px dotted; + outline: 5px auto -webkit-focus-ring-color; +} + +.fc-button { + -webkit-appearance: button; +} + +.fc-button:not(:disabled) { + cursor: pointer; +} + +.fc-button::-moz-focus-inner { + padding: 0; + border-style: none; +} + +/* theme */ +.fc-button { + display: inline-block; + font-weight: 400; + color: #212529; + text-align: center; + vertical-align: middle; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-color: transparent; + border: 1px solid transparent; + padding: 0.4em 0.65em; + font-size: 1em; + line-height: 1.5; + border-radius: 0.25em; +} + +.fc-button:hover { + color: #212529; + text-decoration: none; +} + +.fc-button:focus { + outline: 0; + -webkit-box-shadow: 0 0 0 0.2rem rgba(44, 62, 80, 0.25); + box-shadow: 0 0 0 0.2rem rgba(44, 62, 80, 0.25); +} + +.fc-button:disabled { + opacity: 0.65; +} + +/* "primary" coloring */ +.fc-button-primary { + color: #fff; + background-color: #2C3E50; + border-color: #2C3E50; +} + +.fc-button-primary:hover { + color: #fff; + background-color: #1e2b37; + border-color: #1a252f; +} + +.fc-button-primary:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(76, 91, 106, 0.5); + box-shadow: 0 0 0 0.2rem rgba(76, 91, 106, 0.5); +} + +.fc-button-primary:disabled { + color: #fff; + background-color: #2C3E50; + border-color: #2C3E50; +} + +.fc-button-primary:not(:disabled):active, +.fc-button-primary:not(:disabled).fc-button-active { + color: #fff; + background-color: #1a252f; + border-color: #151e27; +} + +.fc-button-primary:not(:disabled):active:focus, +.fc-button-primary:not(:disabled).fc-button-active:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(76, 91, 106, 0.5); + box-shadow: 0 0 0 0.2rem rgba(76, 91, 106, 0.5); +} + +/* icons within buttons */ +.fc-button .fc-icon { + vertical-align: middle; + font-size: 1.5em; +} + +/* Buttons Groups +--------------------------------------------------------------------------------------------------*/ +.fc-button-group { + position: relative; + display: -webkit-inline-box; + display: -ms-inline-flexbox; + display: inline-flex; + vertical-align: middle; +} + +.fc-button-group > .fc-button { + position: relative; + -webkit-box-flex: 1; + -ms-flex: 1 1 auto; + flex: 1 1 auto; +} + +.fc-button-group > .fc-button:hover { + z-index: 1; +} + +.fc-button-group > .fc-button:focus, +.fc-button-group > .fc-button:active, +.fc-button-group > .fc-button.fc-button-active { + z-index: 1; +} + +.fc-button-group > .fc-button:not(:first-child) { + margin-left: -1px; +} + +.fc-button-group > .fc-button:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.fc-button-group > .fc-button:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +/* Popover +--------------------------------------------------------------------------------------------------*/ +.fc-unthemed .fc-popover { + border-width: 1px; + border-style: solid; +} + +/* List View +--------------------------------------------------------------------------------------------------*/ +.fc-unthemed .fc-list-item:hover td { + background-color: #f5f5f5; +} + +/* Toolbar +--------------------------------------------------------------------------------------------------*/ +.fc-toolbar { + display: flex; + justify-content: space-between; + align-items: center; +} + +.fc-toolbar.fc-header-toolbar { + margin-bottom: 1.5em; +} + +.fc-toolbar.fc-footer-toolbar { + margin-top: 1.5em; +} + +/* inner content */ +.fc-toolbar > * > :not(:first-child) { + margin-left: 0.75em; +} + +.fc-toolbar h2 { + font-size: 1.75em; + margin: 0; +} + +/* View Structure +--------------------------------------------------------------------------------------------------*/ +.fc-view-container { + position: relative; +} + +/* undo twitter bootstrap's box-sizing rules. normalizes positioning techniques */ +/* don't do this for the toolbar because we'll want bootstrap to style those buttons as some pt */ +.fc-view-container *, +.fc-view-container *:before, +.fc-view-container *:after { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} + +.fc-view, +.fc-view > table { + /* so dragged elements can be above the view's main element */ + position: relative; + z-index: 1; +} + +@media print { + .fc { + max-width: 100% !important; + } + + /* Global Event Restyling + --------------------------------------------------------------------------------------------------*/ + .fc-event { + background: #fff !important; + color: #000 !important; + page-break-inside: avoid; + } + + .fc-event .fc-resizer { + display: none; + } + + /* Table & Day-Row Restyling + --------------------------------------------------------------------------------------------------*/ + .fc th, +.fc td, +.fc hr, +.fc thead, +.fc tbody, +.fc-row { + border-color: #ccc !important; + background: #fff !important; + } + + /* kill the overlaid, absolutely-positioned components */ + /* common... */ + .fc-bg, +.fc-bgevent-skeleton, +.fc-highlight-skeleton, +.fc-mirror-skeleton, +.fc-bgevent-container, +.fc-business-container, +.fc-highlight-container, +.fc-mirror-container { + display: none; + } + + /* don't force a min-height on rows (for DayGrid) */ + .fc tbody .fc-row { + height: auto !important; + /* undo height that JS set in distributeHeight */ + min-height: 0 !important; + /* undo the min-height from each view's specific stylesheet */ + } + + .fc tbody .fc-row .fc-content-skeleton { + position: static; + /* undo .fc-rigid */ + padding-bottom: 0 !important; + /* use a more border-friendly method for this... */ + } + + .fc tbody .fc-row .fc-content-skeleton tbody tr:last-child td { + /* only works in newer browsers */ + padding-bottom: 1em; + /* ...gives space within the skeleton. also ensures min height in a way */ + } + + .fc tbody .fc-row .fc-content-skeleton table { + /* provides a min-height for the row, but only effective for IE, which exaggerates this value, + making it look more like 3em. for other browers, it will already be this tall */ + height: 1em; + } + + /* Undo month-view event limiting. Display all events and hide the "more" links + --------------------------------------------------------------------------------------------------*/ + .fc-more-cell, +.fc-more { + display: none !important; + } + + .fc tr.fc-limited { + display: table-row !important; + } + + .fc td.fc-limited { + display: table-cell !important; + } + + .fc-popover { + display: none; + /* never display the "more.." popover in print mode */ + } + + /* TimeGrid Restyling + --------------------------------------------------------------------------------------------------*/ + /* undo the min-height 100% trick used to fill the container's height */ + .fc-time-grid { + min-height: 0 !important; + } + + /* don't display the side axis at all ("all-day" and time cells) */ + .fc-timeGrid-view .fc-axis { + display: none; + } + + /* don't display the horizontal lines */ + .fc-slats, +.fc-time-grid hr { + /* this hr is used when height is underused and needs to be filled */ + display: none !important; + /* important overrides inline declaration */ + } + + /* let the container that holds the events be naturally positioned and create real height */ + .fc-time-grid .fc-content-skeleton { + position: static; + } + + /* in case there are no events, we still want some height */ + .fc-time-grid .fc-content-skeleton table { + height: 4em; + } + + /* kill the horizontal spacing made by the event container. event margins will be done below */ + .fc-time-grid .fc-event-container { + margin: 0 !important; + } + + /* TimeGrid *Event* Restyling + --------------------------------------------------------------------------------------------------*/ + /* naturally position events, vertically stacking them */ + .fc-time-grid .fc-event { + position: static !important; + margin: 3px 2px !important; + } + + /* for events that continue to a future day, give the bottom border back */ + .fc-time-grid .fc-event.fc-not-end { + border-bottom-width: 1px !important; + } + + /* indicate the event continues via "..." text */ + .fc-time-grid .fc-event.fc-not-end:after { + content: "..."; + } + + /* for events that are continuations from previous days, give the top border back */ + .fc-time-grid .fc-event.fc-not-start { + border-top-width: 1px !important; + } + + /* indicate the event is a continuation via "..." text */ + .fc-time-grid .fc-event.fc-not-start:before { + content: "..."; + } + + /* time */ + /* undo a previous declaration and let the time text span to a second line */ + .fc-time-grid .fc-event .fc-time { + white-space: normal !important; + } + + /* hide the the time that is normally displayed... */ + .fc-time-grid .fc-event .fc-time span { + display: none; + } + + /* ...replace it with a more verbose version (includes AM/PM) stored in an html attribute */ + .fc-time-grid .fc-event .fc-time:after { + content: attr(data-full); + } + + /* Vertical Scroller & Containers + --------------------------------------------------------------------------------------------------*/ + /* kill the scrollbars and allow natural height */ + .fc-scroller, +.fc-day-grid-container, +.fc-time-grid-container { + /* */ + overflow: visible !important; + height: auto !important; + } + + /* kill the horizontal border/padding used to compensate for scrollbars */ + .fc-row { + border: 0 !important; + margin: 0 !important; + } + + /* Button Controls + --------------------------------------------------------------------------------------------------*/ + .fc-button-group, +.fc button { + display: none; + /* don't display any button-related controls */ + } +} diff --git a/AKPlan/static/AKPlan/fullcalendar/core/main.d.ts b/AKPlan/static/AKPlan/fullcalendar/core/main.d.ts new file mode 100644 index 00000000..cfd23435 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/main.d.ts @@ -0,0 +1,2730 @@ +// Generated by dts-bundle v0.7.3-fork.1 +// Dependencies for this module: +// ../../../../../@fullcalendar/core + +declare module '@fullcalendar/core' { + export const version = "<%= version %>"; + export { OptionsInput } from '@fullcalendar/core/types/input-types'; + export { EventInput, EventDef, EventDefHash, EventInstance, EventInstanceHash, parseEventDef, createEventInstance, EventTuple } from '@fullcalendar/core/structs/event'; + export { BusinessHoursInput, parseBusinessHours } from '@fullcalendar/core/structs/business-hours'; + export { applyAll, debounce, padStart, isInt, capitaliseFirstLetter, parseFieldSpecs, compareByFieldSpecs, compareByFieldSpec, flexibleCompare, computeVisibleDayRange, refineProps, matchCellWidths, uncompensateScroll, compensateScroll, subtractInnerElHeight, isMultiDayRange, distributeHeight, undistributeHeight, preventSelection, allowSelection, preventContextMenu, allowContextMenu, compareNumbers, enableCursor, disableCursor, diffDates } from '@fullcalendar/core/util/misc'; + export { htmlEscape, cssToStr } from '@fullcalendar/core/util/html'; + export { removeExact, isArraysEqual } from '@fullcalendar/core/util/array'; + export { memoize, memoizeOutput } from '@fullcalendar/core/util/memoize'; + export { memoizeRendering, MemoizedRendering } from '@fullcalendar/core/component/memoized-rendering'; + export { intersectRects, Rect, pointInsideRect, constrainPoint, getRectCenter, diffPoints, Point, translateRect } from '@fullcalendar/core/util/geom'; + export { mapHash, filterHash, isPropsEqual } from '@fullcalendar/core/util/object'; + export { findElements, findChildren, htmlToElement, createElement, insertAfterElement, prependToElement, removeElement, appendToElement, applyStyle, applyStyleProp, elementMatches, elementClosest, forceClassName } from '@fullcalendar/core/util/dom-manip'; + export { EventStore, filterEventStoreDefs, createEmptyEventStore, mergeEventStores, getRelevantEvents, eventTupleToStore } from '@fullcalendar/core/structs/event-store'; + export { EventUiHash, EventUi, processScopedUiProps, combineEventUis } from '@fullcalendar/core/component/event-ui'; + export { default as Splitter, SplittableProps } from '@fullcalendar/core/component/event-splitting'; + export { buildGotoAnchorHtml, getAllDayHtml, getDayClasses } from '@fullcalendar/core/component/date-rendering'; + export { preventDefault, listenBySelector, whenTransitionDone } from '@fullcalendar/core/util/dom-event'; + export { computeInnerRect, computeEdges, computeHeightAndMargins, getClippingParents, computeClippingRect, computeRect } from '@fullcalendar/core/util/dom-geom'; + export { unpromisify } from '@fullcalendar/core/util/promise'; + export { default as EmitterMixin, EmitterInterface } from '@fullcalendar/core/common/EmitterMixin'; + export { DateRange, rangeContainsMarker, intersectRanges, rangesEqual, rangesIntersect, rangeContainsRange } from '@fullcalendar/core/datelib/date-range'; + export { default as Mixin } from '@fullcalendar/core/common/Mixin'; + export { default as PositionCache } from '@fullcalendar/core/common/PositionCache'; + export { default as ScrollComponent, ScrollbarWidths } from '@fullcalendar/core/common/ScrollComponent'; + export { ScrollController, ElementScrollController, WindowScrollController } from '@fullcalendar/core/common/scroll-controller'; + export { default as Theme } from '@fullcalendar/core/theme/Theme'; + export { default as Component, ComponentContext } from '@fullcalendar/core/component/Component'; + export { default as DateComponent, Seg, EventSegUiInteractionState } from '@fullcalendar/core/component/DateComponent'; + export { default as Calendar, DatePointTransform, DateSpanTransform, DateSelectionApi } from '@fullcalendar/core/Calendar'; + export { default as View, ViewProps } from '@fullcalendar/core/View'; + export { default as FgEventRenderer, buildSegCompareObj } from '@fullcalendar/core/component/renderers/FgEventRenderer'; + export { default as FillRenderer } from '@fullcalendar/core/component/renderers/FillRenderer'; + export { default as DateProfileGenerator, DateProfile } from '@fullcalendar/core/DateProfileGenerator'; + export { ViewDef } from '@fullcalendar/core/structs/view-def'; + export { ViewSpec } from '@fullcalendar/core/structs/view-spec'; + export { DateSpan, DateSpanApi, DatePointApi, isDateSpansEqual } from '@fullcalendar/core/structs/date-span'; + export { DateMarker, addDays, startOfDay, addMs, addWeeks, diffWeeks, diffWholeWeeks, diffWholeDays, diffDayAndTime, diffDays, isValidDate } from '@fullcalendar/core/datelib/marker'; + export { Duration, createDuration, isSingleDay, multiplyDuration, addDurations, asRoughMinutes, asRoughSeconds, asRoughMs, wholeDivideDurations, greatestDurationDenominator } from '@fullcalendar/core/datelib/duration'; + export { DateEnv, DateMarkerMeta } from '@fullcalendar/core/datelib/env'; + export { DateFormatter, createFormatter, VerboseFormattingArg, formatIsoTimeString } from '@fullcalendar/core/datelib/formatting'; + export { NamedTimeZoneImpl } from '@fullcalendar/core/datelib/timezone'; + export { parse as parseMarker } from '@fullcalendar/core/datelib/parsing'; + export { EventSourceDef, EventSource, EventSourceHash } from '@fullcalendar/core/structs/event-source'; + export { Interaction, InteractionSettings, interactionSettingsToStore, interactionSettingsStore, InteractionSettingsStore } from '@fullcalendar/core/interactions/interaction'; + export { PointerDragEvent } from '@fullcalendar/core/interactions/pointer'; + export { Hit } from '@fullcalendar/core/interactions/hit'; + export { dateSelectionJoinTransformer } from '@fullcalendar/core/interactions/date-selecting'; + export { eventDragMutationMassager, EventDropTransformers } from '@fullcalendar/core/interactions/event-dragging'; + export { EventResizeJoinTransforms } from '@fullcalendar/core/interactions/event-resizing'; + export { default as ElementDragging } from '@fullcalendar/core/interactions/ElementDragging'; + export { formatDate, formatRange } from '@fullcalendar/core/formatting-api'; + export { globalDefaults, config } from '@fullcalendar/core/options'; + export { RecurringType, ParsedRecurring } from '@fullcalendar/core/structs/recurring-event'; + export { DragMetaInput, DragMeta, parseDragMeta } from '@fullcalendar/core/structs/drag-meta'; + export { createPlugin, PluginDef, PluginDefInput, ViewPropsTransformer, ViewContainerModifier } from '@fullcalendar/core/plugin-system'; + export { reducerFunc, Action, CalendarState } from '@fullcalendar/core/reducers/types'; + export { CalendarComponentProps } from '@fullcalendar/core/CalendarComponent'; + export { default as DayHeader } from '@fullcalendar/core/common/DayHeader'; + export { computeFallbackHeaderFormat, renderDateCell } from '@fullcalendar/core/common/table-utils'; + export { default as DaySeries } from '@fullcalendar/core/common/DaySeries'; + export { EventInteractionState } from '@fullcalendar/core/interactions/event-interaction-state'; + export { EventRenderRange, sliceEventStore, hasBgRendering, getElSeg } from '@fullcalendar/core/component/event-rendering'; + export { default as DayTable, DayTableSeg, DayTableCell } from '@fullcalendar/core/common/DayTable'; + export { default as Slicer, SlicedProps } from '@fullcalendar/core/common/slicing-utils'; + export { EventMutation, applyMutationToEventStore } from '@fullcalendar/core/structs/event-mutation'; + export { Constraint, ConstraintInput, AllowFunc, isPropsValid, isInteractionValid } from '@fullcalendar/core/validation'; + export { default as EventApi } from '@fullcalendar/core/api/EventApi'; + export { default as requestJson } from '@fullcalendar/core/util/requestJson'; +} + +declare module '@fullcalendar/core/types/input-types' { + import View from '@fullcalendar/core/View'; + import { EventSourceInput, EventInputTransformer } from '@fullcalendar/core/structs/event-source'; + import { Duration, DurationInput } from '@fullcalendar/core/datelib/duration'; + import { DateInput } from '@fullcalendar/core/datelib/env'; + import { FormatterInput } from '@fullcalendar/core/datelib/formatting'; + import { DateRangeInput } from '@fullcalendar/core/datelib/date-range'; + import { BusinessHoursInput } from '@fullcalendar/core/structs/business-hours'; + import EventApi from '@fullcalendar/core/api/EventApi'; + import { AllowFunc, ConstraintInput, OverlapFunc } from '@fullcalendar/core/validation'; + import { PluginDef } from '@fullcalendar/core/plugin-system'; + import { LocaleSingularArg, RawLocale } from '@fullcalendar/core/datelib/locale'; + export interface ToolbarInput { + left?: string; + center?: string; + right?: string; + } + export interface CustomButtonInput { + text: string; + icon?: string; + themeIcon?: string; + bootstrapFontAwesome?: string; + click(element: HTMLElement): void; + } + export interface ButtonIconsInput { + prev?: string; + next?: string; + prevYear?: string; + nextYear?: string; + } + export interface ButtonTextCompoundInput { + prev?: string; + next?: string; + prevYear?: string; + nextYear?: string; + today?: string; + month?: string; + week?: string; + day?: string; + [viewId: string]: string | undefined; + } + export interface EventSegment { + event: EventApi; + start: Date; + end: Date; + isStart: boolean; + isEnd: boolean; + } + export interface CellInfo { + date: Date; + dayEl: HTMLElement; + moreEl: HTMLElement; + segs: EventSegment[]; + hiddenSegs: EventSegment[]; + } + export interface DropInfo { + start: Date; + end: Date; + } + export type EventHandlerName = '_init' | 'selectAllow' | 'eventAllow' | 'eventDataTransform' | 'datesRender' | 'datesDestroy' | 'dayRender' | 'windowResize' | 'dateClick' | 'eventClick' | 'eventMouseEnter' | 'eventMouseLeave' | 'select' | 'unselect' | 'loading' | 'eventRender' | 'eventPositioned' | '_eventsPositioned' | 'eventDestroy' | 'eventDragStart' | 'eventDragStop' | 'eventDrop' | '_destroyed' | 'drop' | 'eventResizeStart' | 'eventResizeStop' | 'eventResize' | 'eventReceive' | 'eventLeave' | 'viewSkeletonRender' | 'viewSkeletonDestroy' | '_noEventDrop' | '_noEventResize' | 'eventLimitClick' | 'resourceRender'; + export type EventHandlerArgs<T extends EventHandlerName> = Parameters<Extract<OptionsInput[T], (...args: any[]) => any>>; + export type EventHandlerArg<T extends EventHandlerName> = EventHandlerArgs<T>[0]; + export interface OptionsInputBase { + header?: boolean | ToolbarInput; + footer?: boolean | ToolbarInput; + customButtons?: { + [name: string]: CustomButtonInput; + }; + buttonIcons?: boolean | ButtonIconsInput; + themeSystem?: 'standard' | string; + bootstrapFontAwesome?: boolean | ButtonIconsInput; + firstDay?: number; + dir?: 'ltr' | 'rtl' | 'auto'; + weekends?: boolean; + hiddenDays?: number[]; + fixedWeekCount?: boolean; + weekNumbers?: boolean; + weekNumbersWithinDays?: boolean; + weekNumberCalculation?: 'local' | 'ISO' | ((m: Date) => number); + businessHours?: BusinessHoursInput; + showNonCurrentDates?: boolean; + height?: number | 'auto' | 'parent' | (() => number); + contentHeight?: number | 'auto' | (() => number); + aspectRatio?: number; + handleWindowResize?: boolean; + windowResizeDelay?: number; + eventLimit?: boolean | number; + eventLimitClick?: 'popover' | 'week' | 'day' | 'timeGridWeek' | 'timeGridDay' | string | ((arg: { + date: Date; + allDay: boolean; + dayEl: HTMLElement; + moreEl: HTMLElement; + segs: any[]; + hiddenSegs: any[]; + jsEvent: MouseEvent; + view: View; + }) => void); + timeZone?: string | boolean; + now?: DateInput | (() => DateInput); + defaultView?: string; + allDaySlot?: boolean; + allDayText?: string; + slotDuration?: DurationInput; + slotLabelFormat?: FormatterInput; + slotLabelInterval?: DurationInput; + snapDuration?: DurationInput; + scrollTime?: DurationInput; + minTime?: DurationInput; + maxTime?: DurationInput; + slotEventOverlap?: boolean; + listDayFormat?: FormatterInput | boolean; + listDayAltFormat?: FormatterInput | boolean; + noEventsMessage?: string; + defaultDate?: DateInput; + nowIndicator?: boolean; + visibleRange?: ((currentDate: Date) => DateRangeInput) | DateRangeInput; + validRange?: DateRangeInput; + dateIncrement?: DurationInput; + dateAlignment?: string; + duration?: DurationInput; + dayCount?: number; + locales?: RawLocale[]; + locale?: LocaleSingularArg; + eventTimeFormat?: FormatterInput; + columnHeader?: boolean; + columnHeaderFormat?: FormatterInput; + columnHeaderText?: string | ((date: DateInput) => string); + columnHeaderHtml?: string | ((date: DateInput) => string); + titleFormat?: FormatterInput; + weekLabel?: string; + displayEventTime?: boolean; + displayEventEnd?: boolean; + eventLimitText?: string | ((eventCnt: number) => string); + dayPopoverFormat?: FormatterInput; + navLinks?: boolean; + navLinkDayClick?: string | ((date: Date, jsEvent: Event) => void); + navLinkWeekClick?: string | ((weekStart: any, jsEvent: Event) => void); + selectable?: boolean; + selectMirror?: boolean; + unselectAuto?: boolean; + unselectCancel?: string; + defaultAllDayEventDuration?: DurationInput; + defaultTimedEventDuration?: DurationInput; + cmdFormatter?: string; + defaultRangeSeparator?: string; + selectConstraint?: ConstraintInput; + selectOverlap?: boolean | OverlapFunc; + selectAllow?: AllowFunc; + editable?: boolean; + eventStartEditable?: boolean; + eventDurationEditable?: boolean; + eventConstraint?: ConstraintInput; + eventOverlap?: boolean | OverlapFunc; + eventAllow?: AllowFunc; + eventClassName?: string[] | string; + eventClassNames?: string[] | string; + eventBackgroundColor?: string; + eventBorderColor?: string; + eventTextColor?: string; + eventColor?: string; + events?: EventSourceInput; + eventSources?: EventSourceInput[]; + allDayDefault?: boolean; + startParam?: string; + endParam?: string; + lazyFetching?: boolean; + nextDayThreshold?: DurationInput; + eventOrder?: string | Array<((a: EventApi, b: EventApi) => number) | (string | ((a: EventApi, b: EventApi) => number))>; + rerenderDelay?: number | null; + dragRevertDuration?: number; + dragScroll?: boolean; + longPressDelay?: number; + eventLongPressDelay?: number; + droppable?: boolean; + dropAccept?: string | ((draggable: any) => boolean); + eventDataTransform?: EventInputTransformer; + allDayMaintainDuration?: boolean; + eventResizableFromStart?: boolean; + timeGridEventMinHeight?: number; + allDayHtml?: string; + eventDragMinDistance?: number; + eventSourceFailure?: any; + eventSourceSuccess?: any; + forceEventDuration?: boolean; + progressiveEventRendering?: boolean; + selectLongPressDelay?: number; + selectMinDistance?: number; + timeZoneParam?: string; + titleRangeSeparator?: string; + datesRender?(arg: { + view: View; + el: HTMLElement; + }): void; + datesDestroy?(arg: { + view: View; + el: HTMLElement; + }): void; + dayRender?(arg: { + view: View; + date: Date; + allDay?: boolean; + el: HTMLElement; + }): void; + windowResize?(view: View): void; + dateClick?(arg: { + date: Date; + dateStr: string; + allDay: boolean; + resource?: any; + dayEl: HTMLElement; + jsEvent: MouseEvent; + view: View; + }): void; + eventClick?(arg: { + el: HTMLElement; + event: EventApi; + jsEvent: MouseEvent; + view: View; + }): boolean | void; + eventMouseEnter?(arg: { + el: HTMLElement; + event: EventApi; + jsEvent: MouseEvent; + view: View; + }): void; + eventMouseLeave?(arg: { + el: HTMLElement; + event: EventApi; + jsEvent: MouseEvent; + view: View; + }): void; + select?(arg: { + start: Date; + end: Date; + startStr: string; + endStr: string; + allDay: boolean; + resource?: any; + jsEvent: MouseEvent; + view: View; + }): void; + unselect?(arg: { + view: View; + jsEvent: Event; + }): void; + loading?(isLoading: boolean): void; + eventRender?(arg: { + isMirror: boolean; + isStart: boolean; + isEnd: boolean; + event: EventApi; + el: HTMLElement; + view: View; + }): void; + eventPositioned?(arg: { + isMirror: boolean; + isStart: boolean; + isEnd: boolean; + event: EventApi; + el: HTMLElement; + view: View; + }): void; + _eventsPositioned?(arg: { + view: View; + }): void; + eventDestroy?(arg: { + isMirror: boolean; + event: EventApi; + el: HTMLElement; + view: View; + }): void; + eventDragStart?(arg: { + event: EventApi; + el: HTMLElement; + jsEvent: MouseEvent; + view: View; + }): void; + eventDragStop?(arg: { + event: EventApi; + el: HTMLElement; + jsEvent: MouseEvent; + view: View; + }): void; + eventDrop?(arg: { + el: HTMLElement; + event: EventApi; + oldEvent: EventApi; + delta: Duration; + revert: () => void; + jsEvent: Event; + view: View; + }): void; + eventResizeStart?(arg: { + el: HTMLElement; + event: EventApi; + jsEvent: MouseEvent; + view: View; + }): void; + eventResizeStop?(arg: { + el: HTMLElement; + event: EventApi; + jsEvent: MouseEvent; + view: View; + }): void; + eventResize?(arg: { + el: HTMLElement; + startDelta: Duration; + endDelta: Duration; + prevEvent: EventApi; + event: EventApi; + revert: () => void; + jsEvent: Event; + view: View; + }): void; + drop?(arg: { + date: Date; + dateStr: string; + allDay: boolean; + draggedEl: HTMLElement; + jsEvent: MouseEvent; + view: View; + }): void; + eventReceive?(arg: { + event: EventApi; + draggedEl: HTMLElement; + view: View; + }): void; + eventLeave?(arg: { + draggedEl: HTMLElement; + event: EventApi; + view: View; + }): void; + viewSkeletonRender?(arg: { + el: HTMLElement; + view: View; + }): void; + viewSkeletonDestroy?(arg: { + el: HTMLElement; + view: View; + }): void; + _destroyed?(): void; + _init?(): void; + _noEventDrop?(): void; + _noEventResize?(): void; + resourceRender?(arg: { + resource: any; + el: HTMLElement; + view: View; + }): void; + } + export interface ViewOptionsInput extends OptionsInputBase { + type?: string; + buttonText?: string; + } + export interface OptionsInput extends OptionsInputBase { + buttonText?: ButtonTextCompoundInput; + views?: { + [viewId: string]: ViewOptionsInput; + }; + plugins?: (PluginDef | string)[]; + } +} + +declare module '@fullcalendar/core/structs/event' { + import { DateInput } from '@fullcalendar/core/datelib/env'; + import Calendar from '@fullcalendar/core/Calendar'; + import { DateRange } from '@fullcalendar/core/datelib/date-range'; + import { Duration } from '@fullcalendar/core/datelib/duration'; + import { UnscopedEventUiInput, EventUi } from '@fullcalendar/core/component/event-ui'; + export type EventRenderingChoice = '' | 'background' | 'inverse-background' | 'none'; + export interface EventNonDateInput extends UnscopedEventUiInput { + id?: string | number; + groupId?: string | number; + title?: string; + url?: string; + rendering?: EventRenderingChoice; + extendedProps?: object; + [extendedProp: string]: any; + } + export interface EventDateInput { + start?: DateInput; + end?: DateInput; + date?: DateInput; + allDay?: boolean; + } + export type EventInput = EventNonDateInput & EventDateInput; + export interface EventDef { + defId: string; + sourceId: string; + publicId: string; + groupId: string; + allDay: boolean; + hasEnd: boolean; + recurringDef: { + typeId: number; + typeData: any; + duration: Duration | null; + } | null; + title: string; + url: string; + rendering: EventRenderingChoice; + ui: EventUi; + extendedProps: any; + } + export interface EventInstance { + instanceId: string; + defId: string; + range: DateRange; + forcedStartTzo: number | null; + forcedEndTzo: number | null; + } + export interface EventTuple { + def: EventDef; + instance: EventInstance | null; + } + export type EventInstanceHash = { + [instanceId: string]: EventInstance; + }; + export type EventDefHash = { + [defId: string]: EventDef; + }; + export const NON_DATE_PROPS: { + id: StringConstructor; + groupId: StringConstructor; + title: StringConstructor; + url: StringConstructor; + rendering: StringConstructor; + extendedProps: any; + }; + export const DATE_PROPS: { + start: any; + date: any; + end: any; + allDay: any; + }; + export function parseEvent(raw: EventInput, sourceId: string, calendar: Calendar, allowOpenRange?: boolean): EventTuple | null; + export function parseEventDef(raw: EventNonDateInput, sourceId: string, allDay: boolean, hasEnd: boolean, calendar: Calendar): EventDef; + export type eventDefParserFunc = (def: EventDef, props: any, leftovers: any) => void; + export function createEventInstance(defId: string, range: DateRange, forcedStartTzo?: number, forcedEndTzo?: number): EventInstance; +} + +declare module '@fullcalendar/core/structs/business-hours' { + import Calendar from '@fullcalendar/core/Calendar'; + import { EventInput } from '@fullcalendar/core/structs/event'; + import { EventStore } from '@fullcalendar/core/structs/event-store'; + export type BusinessHoursInput = boolean | EventInput | EventInput[]; + export function parseBusinessHours(input: BusinessHoursInput, calendar: Calendar): EventStore; +} + +declare module '@fullcalendar/core/util/misc' { + import { DateMarker } from '@fullcalendar/core/datelib/marker'; + import { Duration } from '@fullcalendar/core/datelib/duration'; + import { DateEnv } from '@fullcalendar/core/datelib/env'; + import { DateRange, OpenDateRange } from '@fullcalendar/core/datelib/date-range'; + export function compensateScroll(rowEl: HTMLElement, scrollbarWidths: any): void; + export function uncompensateScroll(rowEl: HTMLElement): void; + export function disableCursor(): void; + export function enableCursor(): void; + export function distributeHeight(els: HTMLElement[], availableHeight: any, shouldRedistribute: any): void; + export function undistributeHeight(els: HTMLElement[]): void; + export function matchCellWidths(els: HTMLElement[]): number; + export function subtractInnerElHeight(outerEl: HTMLElement, innerEl: HTMLElement): number; + export function preventSelection(el: HTMLElement): void; + export function allowSelection(el: HTMLElement): void; + export function preventContextMenu(el: HTMLElement): void; + export function allowContextMenu(el: HTMLElement): void; + export function parseFieldSpecs(input: any): any[]; + export function compareByFieldSpecs(obj0: any, obj1: any, fieldSpecs: any): any; + export function compareByFieldSpec(obj0: any, obj1: any, fieldSpec: any): any; + export function flexibleCompare(a: any, b: any): number; + export function capitaliseFirstLetter(str: any): any; + export function padStart(val: any, len: any): string; + export function compareNumbers(a: any, b: any): number; + export function isInt(n: any): boolean; + export function applyAll(functions: any, thisObj: any, args: any): any; + export function firstDefined(...args: any[]): any; + export function debounce(func: any, wait: any): () => any; + export type GenericHash = { + [key: string]: any; + }; + export function refineProps(rawProps: GenericHash, processors: GenericHash, defaults?: GenericHash, leftoverProps?: GenericHash): GenericHash; + export function computeAlignedDayRange(timedRange: DateRange): DateRange; + export function computeVisibleDayRange(timedRange: OpenDateRange, nextDayThreshold?: Duration): OpenDateRange; + export function isMultiDayRange(range: DateRange): boolean; + export function diffDates(date0: DateMarker, date1: DateMarker, dateEnv: DateEnv, largeUnit?: string): Duration; +} + +declare module '@fullcalendar/core/util/html' { + export function htmlEscape(s: any): string; + export function cssToStr(cssProps: any): string; + export function attrsToStr(attrs: any): string; + export type ClassNameInput = string | string[]; + export function parseClassName(raw: ClassNameInput): string[]; +} + +declare module '@fullcalendar/core/util/array' { + export function removeMatching(array: any, testFunc: any): number; + export function removeExact(array: any, exactVal: any): number; + export function isArraysEqual(a0: any, a1: any): boolean; +} + +declare module '@fullcalendar/core/util/memoize' { + export function memoize<T>(workerFunc: T): T; + export function memoizeOutput<T>(workerFunc: T, equalityFunc: (output0: any, output1: any) => boolean): T; +} + +declare module '@fullcalendar/core/component/memoized-rendering' { + export interface MemoizedRendering<ArgsType extends any[]> { + (...args: ArgsType): void; + unrender: () => void; + dependents: MemoizedRendering<any>[]; + } + export function memoizeRendering<ArgsType extends any[]>(renderFunc: (...args: ArgsType) => void, unrenderFunc?: (...args: ArgsType) => void, dependencies?: MemoizedRendering<any>[]): MemoizedRendering<ArgsType>; +} + +declare module '@fullcalendar/core/util/geom' { + export interface Point { + left: number; + top: number; + } + export interface Rect { + left: number; + right: number; + top: number; + bottom: number; + } + export function pointInsideRect(point: Point, rect: Rect): boolean; + export function intersectRects(rect1: Rect, rect2: Rect): Rect | false; + export function translateRect(rect: Rect, deltaX: number, deltaY: number): Rect; + export function constrainPoint(point: Point, rect: Rect): Point; + export function getRectCenter(rect: Rect): Point; + export function diffPoints(point1: Point, point2: Point): Point; +} + +declare module '@fullcalendar/core/util/object' { + export function mergeProps(propObjs: any, complexProps?: any): any; + export function filterHash(hash: any, func: any): {}; + export function mapHash<InputItem, OutputItem>(hash: { + [key: string]: InputItem; + }, func: (input: InputItem, key: string) => OutputItem): { + [key: string]: OutputItem; + }; + export function arrayToHash(a: any): { + [key: string]: true; + }; + export function hashValuesToArray(obj: any): any[]; + export function isPropsEqual(obj0: any, obj1: any): boolean; +} + +declare module '@fullcalendar/core/util/dom-manip' { + export function createElement(tagName: string, attrs: object | null, content?: ElementContent): HTMLElement; + export function htmlToElement(html: string): HTMLElement; + export function htmlToElements(html: string): HTMLElement[]; + export type ElementContent = string | Node | Node[] | NodeList; + export function appendToElement(el: HTMLElement, content: ElementContent): void; + export function prependToElement(parent: HTMLElement, content: ElementContent): void; + export function insertAfterElement(refEl: HTMLElement, content: ElementContent): void; + export function removeElement(el: HTMLElement): void; + export function elementClosest(el: HTMLElement, selector: string): HTMLElement; + export function elementMatches(el: HTMLElement, selector: string): HTMLElement; + export function findElements(container: HTMLElement[] | HTMLElement | NodeListOf<HTMLElement>, selector: string): HTMLElement[]; + export function findChildren(parent: HTMLElement[] | HTMLElement, selector?: string): HTMLElement[]; + export function forceClassName(el: HTMLElement, className: string, bool: any): void; + export function applyStyle(el: HTMLElement, props: object): void; + export function applyStyleProp(el: HTMLElement, name: string, val: any): void; +} + +declare module '@fullcalendar/core/structs/event-store' { + import { EventInput, EventDef, EventDefHash, EventInstanceHash, EventTuple } from '@fullcalendar/core/structs/event'; + import { EventSource } from '@fullcalendar/core/structs/event-source'; + import Calendar from '@fullcalendar/core/Calendar'; + import { DateRange } from '@fullcalendar/core/datelib/date-range'; + export interface EventStore { + defs: EventDefHash; + instances: EventInstanceHash; + } + export function parseEvents(rawEvents: EventInput[], sourceId: string, calendar: Calendar, allowOpenRange?: boolean): EventStore; + export function eventTupleToStore(tuple: EventTuple, eventStore?: EventStore): EventStore; + export function expandRecurring(eventStore: EventStore, framingRange: DateRange, calendar: Calendar): EventStore; + export function getRelevantEvents(eventStore: EventStore, instanceId: string): EventStore; + export function transformRawEvents(rawEvents: any, eventSource: EventSource, calendar: Calendar): any; + export function createEmptyEventStore(): EventStore; + export function mergeEventStores(store0: EventStore, store1: EventStore): EventStore; + export function filterEventStoreDefs(eventStore: EventStore, filterFunc: (eventDef: EventDef) => boolean): EventStore; +} + +declare module '@fullcalendar/core/component/event-ui' { + import { Constraint, AllowFunc, ConstraintInput } from '@fullcalendar/core/validation'; + import { parseClassName } from '@fullcalendar/core/util/html'; + import Calendar from '@fullcalendar/core/Calendar'; + export interface UnscopedEventUiInput { + editable?: boolean; + startEditable?: boolean; + durationEditable?: boolean; + constraint?: ConstraintInput; + overlap?: boolean; + allow?: AllowFunc; + className?: string[] | string; + classNames?: string[] | string; + backgroundColor?: string; + borderColor?: string; + textColor?: string; + color?: string; + } + export interface EventUi { + startEditable: boolean | null; + durationEditable: boolean | null; + constraints: Constraint[]; + overlap: boolean | null; + allows: AllowFunc[]; + backgroundColor: string; + borderColor: string; + textColor: string; + classNames: string[]; + } + export type EventUiHash = { + [defId: string]: EventUi; + }; + export const UNSCOPED_EVENT_UI_PROPS: { + editable: BooleanConstructor; + startEditable: BooleanConstructor; + durationEditable: BooleanConstructor; + constraint: any; + overlap: any; + allow: any; + className: typeof parseClassName; + classNames: typeof parseClassName; + color: StringConstructor; + backgroundColor: StringConstructor; + borderColor: StringConstructor; + textColor: StringConstructor; + }; + export function processUnscopedUiProps(rawProps: UnscopedEventUiInput, calendar: Calendar, leftovers?: any): EventUi; + export function processScopedUiProps(prefix: string, rawScoped: any, calendar: Calendar, leftovers?: any): EventUi; + export function combineEventUis(uis: EventUi[]): EventUi; +} + +declare module '@fullcalendar/core/component/event-splitting' { + import { EventStore } from '@fullcalendar/core/structs/event-store'; + import { EventDef } from '@fullcalendar/core/structs/event'; + import { EventInteractionState } from '@fullcalendar/core/interactions/event-interaction-state'; + import { EventUiHash, EventUi } from '@fullcalendar/core/component/event-ui'; + import { DateSpan } from '@fullcalendar/core/structs/date-span'; + export interface SplittableProps { + businessHours: EventStore | null; + dateSelection: DateSpan | null; + eventStore: EventStore; + eventUiBases: EventUiHash; + eventSelection: string; + eventDrag: EventInteractionState | null; + eventResize: EventInteractionState | null; + } + export { Splitter as default, Splitter }; + abstract class Splitter<PropsType extends SplittableProps = SplittableProps> { + abstract getKeyInfo(props: PropsType): { + [key: string]: { + ui?: EventUi; + businessHours?: EventStore; + }; + }; + abstract getKeysForDateSpan(dateSpan: DateSpan): string[]; + abstract getKeysForEventDef(eventDef: EventDef): string[]; + splitProps(props: PropsType): { + [key: string]: SplittableProps; + }; + } +} + +declare module '@fullcalendar/core/component/date-rendering' { + import { DateMarker } from '@fullcalendar/core/datelib/marker'; + import Component, { ComponentContext } from '@fullcalendar/core/component/Component'; + import { DateProfile } from '@fullcalendar/core/DateProfileGenerator'; + export function buildGotoAnchorHtml(component: Component<any>, gotoOptions: any, attrs: any, innerHtml?: any): string; + export function getAllDayHtml(component: Component<any>): any; + export function getDayClasses(date: DateMarker, dateProfile: DateProfile, context: ComponentContext, noThemeHighlight?: any): any[]; +} + +declare module '@fullcalendar/core/util/dom-event' { + export function preventDefault(ev: any): void; + export function listenBySelector(container: HTMLElement, eventType: string, selector: string, handler: (ev: Event, matchedTarget: HTMLElement) => void): () => void; + export function listenToHoverBySelector(container: HTMLElement, selector: string, onMouseEnter: (ev: Event, matchedTarget: HTMLElement) => void, onMouseLeave: (ev: Event, matchedTarget: HTMLElement) => void): () => void; + export function whenTransitionDone(el: HTMLElement, callback: (ev: Event) => void): void; +} + +declare module '@fullcalendar/core/util/dom-geom' { + import { Rect } from '@fullcalendar/core/util/geom'; + export interface EdgeInfo { + borderLeft: number; + borderRight: number; + borderTop: number; + borderBottom: number; + scrollbarLeft: number; + scrollbarRight: number; + scrollbarBottom: number; + paddingLeft?: number; + paddingRight?: number; + paddingTop?: number; + paddingBottom?: number; + } + export function computeEdges(el: any, getPadding?: boolean): EdgeInfo; + export function computeInnerRect(el: any, goWithinPadding?: boolean): { + left: number; + right: number; + top: number; + bottom: number; + }; + export function computeRect(el: any): Rect; + export function computeHeightAndMargins(el: HTMLElement): number; + export function computeVMargins(el: HTMLElement): number; + export function getClippingParents(el: HTMLElement): HTMLElement[]; + export function computeClippingRect(el: HTMLElement): Rect; +} + +declare module '@fullcalendar/core/util/promise' { + export function unpromisify(func: any, success: any, failure?: any): void; +} + +declare module '@fullcalendar/core/common/EmitterMixin' { + import Mixin from '@fullcalendar/core/common/Mixin'; + export interface EmitterInterface { + on(types: any, handler: any): any; + one(types: any, handler: any): any; + off(types: any, handler: any): any; + trigger(type: any, ...args: any[]): any; + triggerWith(type: any, context: any, args: any): any; + hasHandlers(type: any): any; + } + export { EmitterMixin as default, EmitterMixin }; + class EmitterMixin extends Mixin implements EmitterInterface { + _handlers: any; + _oneHandlers: any; + on(type: any, handler: any): this; + one(type: any, handler: any): this; + off(type: any, handler?: any): this; + trigger(type: any, ...args: any[]): this; + triggerWith(type: any, context: any, args: any): this; + hasHandlers(type: any): any; + } +} + +declare module '@fullcalendar/core/datelib/date-range' { + import { DateMarker } from '@fullcalendar/core/datelib/marker'; + import { DateEnv, DateInput } from '@fullcalendar/core/datelib/env'; + export interface DateRangeInput { + start?: DateInput; + end?: DateInput; + } + export interface OpenDateRange { + start: DateMarker | null; + end: DateMarker | null; + } + export interface DateRange { + start: DateMarker; + end: DateMarker; + } + export function parseRange(input: DateRangeInput, dateEnv: DateEnv): OpenDateRange; + export function invertRanges(ranges: DateRange[], constraintRange: DateRange): DateRange[]; + export function intersectRanges(range0: OpenDateRange, range1: OpenDateRange): OpenDateRange; + export function rangesEqual(range0: OpenDateRange, range1: OpenDateRange): boolean; + export function rangesIntersect(range0: OpenDateRange, range1: OpenDateRange): boolean; + export function rangeContainsRange(outerRange: OpenDateRange, innerRange: OpenDateRange): boolean; + export function rangeContainsMarker(range: OpenDateRange, date: DateMarker | number): boolean; + export function constrainMarkerToRange(date: DateMarker, range: DateRange): DateMarker; +} + +declare module '@fullcalendar/core/common/Mixin' { + export { Mixin as default, Mixin }; + class Mixin { + static mixInto(destClass: any): void; + static mixIntoObj(destObj: any): void; + static mixOver(destClass: any): void; + } +} + +declare module '@fullcalendar/core/common/PositionCache' { + export { PositionCache as default, PositionCache }; + class PositionCache { + originClientRect: ClientRect; + els: HTMLElement[]; + originEl: HTMLElement; + isHorizontal: boolean; + isVertical: boolean; + lefts: any; + rights: any; + tops: any; + bottoms: any; + constructor(originEl: HTMLElement, els: HTMLElement[], isHorizontal: boolean, isVertical: boolean); + build(): void; + buildElHorizontals(originClientLeft: number): void; + buildElVerticals(originClientTop: number): void; + leftToIndex(leftPosition: number): any; + topToIndex(topPosition: number): any; + getWidth(leftIndex: number): number; + getHeight(topIndex: number): number; + } +} + +declare module '@fullcalendar/core/common/ScrollComponent' { + import { ElementScrollController } from '@fullcalendar/core/common/scroll-controller'; + export interface ScrollbarWidths { + left: number; + right: number; + bottom: number; + } + export { ScrollComponent as default, ScrollComponent }; + class ScrollComponent extends ElementScrollController { + overflowX: string; + overflowY: string; + constructor(overflowX: string, overflowY: string); + clear(): void; + destroy(): void; + applyOverflow(): void; + lockOverflow(scrollbarWidths: ScrollbarWidths): void; + setHeight(height: number | string): void; + getScrollbarWidths(): ScrollbarWidths; + } +} + +declare module '@fullcalendar/core/common/scroll-controller' { + export abstract class ScrollController { + abstract getScrollTop(): number; + abstract getScrollLeft(): number; + abstract setScrollTop(top: number): void; + abstract setScrollLeft(left: number): void; + abstract getClientWidth(): number; + abstract getClientHeight(): number; + abstract getScrollWidth(): number; + abstract getScrollHeight(): number; + getMaxScrollTop(): number; + getMaxScrollLeft(): number; + canScrollVertically(): boolean; + canScrollHorizontally(): boolean; + canScrollUp(): boolean; + canScrollDown(): boolean; + canScrollLeft(): boolean; + canScrollRight(): boolean; + } + export class ElementScrollController extends ScrollController { + el: HTMLElement; + constructor(el: HTMLElement); + getScrollTop(): number; + getScrollLeft(): number; + setScrollTop(top: number): void; + setScrollLeft(left: number): void; + getScrollWidth(): number; + getScrollHeight(): number; + getClientHeight(): number; + getClientWidth(): number; + } + export class WindowScrollController extends ScrollController { + getScrollTop(): number; + getScrollLeft(): number; + setScrollTop(n: number): void; + setScrollLeft(n: number): void; + getScrollWidth(): number; + getScrollHeight(): number; + getClientHeight(): number; + getClientWidth(): number; + } +} + +declare module '@fullcalendar/core/theme/Theme' { + export { Theme as default, Theme }; + class Theme { + calendarOptions: any; + classes: any; + iconClasses: any; + baseIconClass: string; + iconOverrideOption: any; + iconOverrideCustomButtonOption: any; + iconOverridePrefix: string; + constructor(calendarOptions: any); + processIconOverride(): void; + setIconOverride(iconOverrideHash: any): void; + applyIconOverridePrefix(className: any): any; + getClass(key: any): any; + getIconClass(buttonName: any): string; + getCustomButtonIconClass(customButtonProps: any): string; + } + export type ThemeClass = { + new (calendarOptions: any): Theme; + }; +} + +declare module '@fullcalendar/core/component/Component' { + import Calendar from '@fullcalendar/core/Calendar'; + import View from '@fullcalendar/core/View'; + import Theme from '@fullcalendar/core/theme/Theme'; + import { DateEnv } from '@fullcalendar/core/datelib/env'; + export interface ComponentContext { + options: any; + dateEnv: DateEnv; + theme: Theme; + calendar: Calendar; + view: View; + } + export type EqualityFuncHash = { + [propName: string]: (obj0: any, obj1: any) => boolean; + }; + export { Component as default, Component }; + class Component<PropsType> { + equalityFuncs: EqualityFuncHash; + uid: string; + props: PropsType | null; + context: ComponentContext; + dateEnv: DateEnv; + theme: Theme; + view: View; + calendar: Calendar; + isRtl: boolean; + constructor(context: ComponentContext, isView?: boolean); + static addEqualityFuncs(newFuncs: EqualityFuncHash): void; + opt(name: any): any; + receiveProps(props: PropsType): void; + protected render(props: PropsType): void; + destroy(): void; + } +} + +declare module '@fullcalendar/core/component/DateComponent' { + import Component, { ComponentContext } from '@fullcalendar/core/component/Component'; + import { EventRenderRange } from '@fullcalendar/core/component/event-rendering'; + import { DateSpan } from '@fullcalendar/core/structs/date-span'; + import { EventInstanceHash } from '@fullcalendar/core/structs/event'; + import { Hit } from '@fullcalendar/core/interactions/hit'; + import FgEventRenderer from '@fullcalendar/core/component/renderers/FgEventRenderer'; + import FillRenderer from '@fullcalendar/core/component/renderers/FillRenderer'; + import { EventInteractionState } from '@fullcalendar/core/interactions/event-interaction-state'; + import { EventHandlerName, EventHandlerArgs } from '@fullcalendar/core/types/input-types'; + export type DateComponentHash = { + [uid: string]: DateComponent<any>; + }; + export interface Seg { + component?: DateComponent<any>; + isStart: boolean; + isEnd: boolean; + eventRange?: EventRenderRange; + el?: HTMLElement; + [otherProp: string]: any; + } + export interface EventSegUiInteractionState { + affectedInstances: EventInstanceHash; + segs: Seg[]; + isEvent: boolean; + sourceSeg: any; + } + export { DateComponent as default, DateComponent }; + class DateComponent<PropsType> extends Component<PropsType> { + fgSegSelector: string; + bgSegSelector: string; + largeUnit: any; + eventRenderer: FgEventRenderer; + mirrorRenderer: FgEventRenderer; + fillRenderer: FillRenderer; + el: HTMLElement; + constructor(context: ComponentContext, el: HTMLElement, isView?: boolean); + destroy(): void; + buildPositionCaches(): void; + queryHit(positionLeft: number, positionTop: number, elWidth: number, elHeight: number): Hit | null; + isInteractionValid(interaction: EventInteractionState): boolean; + isDateSelectionValid(selection: DateSpan): boolean; + publiclyTrigger<T extends EventHandlerName>(name: T, args?: EventHandlerArgs<T>): any; + publiclyTriggerAfterSizing<T extends EventHandlerName>(name: T, args: EventHandlerArgs<T>): void; + hasPublicHandlers<T extends EventHandlerName>(name: T): boolean; + triggerRenderedSegs(segs: Seg[], isMirrors: boolean): void; + triggerWillRemoveSegs(segs: Seg[], isMirrors: boolean): void; + isValidSegDownEl(el: HTMLElement): boolean; + isValidDateDownEl(el: HTMLElement): boolean; + isPopover(): boolean; + isInPopover(el: HTMLElement): boolean; + } +} + +declare module '@fullcalendar/core/Calendar' { + import { EmitterInterface } from '@fullcalendar/core/common/EmitterMixin'; + import OptionsManager from '@fullcalendar/core/OptionsManager'; + import View from '@fullcalendar/core/View'; + import Theme from '@fullcalendar/core/theme/Theme'; + import { OptionsInput, EventHandlerName, EventHandlerArgs } from '@fullcalendar/core/types/input-types'; + import { RawLocaleMap } from '@fullcalendar/core/datelib/locale'; + import { DateEnv, DateInput } from '@fullcalendar/core/datelib/env'; + import { DateMarker } from '@fullcalendar/core/datelib/marker'; + import { Duration, DurationInput } from '@fullcalendar/core/datelib/duration'; + import { DateSpan, DateSpanApi, DatePointApi } from '@fullcalendar/core/structs/date-span'; + import { DateRangeInput } from '@fullcalendar/core/datelib/date-range'; + import DateProfileGenerator from '@fullcalendar/core/DateProfileGenerator'; + import { EventSourceInput } from '@fullcalendar/core/structs/event-source'; + import { EventInput } from '@fullcalendar/core/structs/event'; + import { CalendarState, Action } from '@fullcalendar/core/reducers/types'; + import EventSourceApi from '@fullcalendar/core/api/EventSourceApi'; + import EventApi from '@fullcalendar/core/api/EventApi'; + import { EventStore } from '@fullcalendar/core/structs/event-store'; + import { EventUiHash, EventUi } from '@fullcalendar/core/component/event-ui'; + import { ViewSpecHash, ViewSpec } from '@fullcalendar/core/structs/view-spec'; + import { PluginSystem } from '@fullcalendar/core/plugin-system'; + import CalendarComponent from '@fullcalendar/core/CalendarComponent'; + import DateComponent from '@fullcalendar/core/component/DateComponent'; + import { PointerDragEvent } from '@fullcalendar/core/interactions/pointer'; + import { InteractionSettingsInput, Interaction } from '@fullcalendar/core/interactions/interaction'; + export interface DateClickApi extends DatePointApi { + dayEl: HTMLElement; + jsEvent: UIEvent; + view: View; + } + export interface DateSelectionApi extends DateSpanApi { + jsEvent: UIEvent; + view: View; + } + export type DatePointTransform = (dateSpan: DateSpan, calendar: Calendar) => any; + export type DateSpanTransform = (dateSpan: DateSpan, calendar: Calendar) => any; + export type CalendarInteraction = { + destroy(): any; + }; + export type CalendarInteractionClass = { + new (calendar: Calendar): CalendarInteraction; + }; + export type OptionChangeHandler = (propValue: any, calendar: Calendar, deepEqual: any) => void; + export type OptionChangeHandlerMap = { + [propName: string]: OptionChangeHandler; + }; + export { Calendar as default, Calendar }; + class Calendar { + static on: EmitterInterface['on']; + static off: EmitterInterface['off']; + static trigger: EmitterInterface['trigger']; + on: EmitterInterface['on']; + one: EmitterInterface['one']; + off: EmitterInterface['off']; + trigger: EmitterInterface['trigger']; + triggerWith: EmitterInterface['triggerWith']; + hasHandlers: EmitterInterface['hasHandlers']; + eventUiBases: EventUiHash; + selectionConfig: EventUi; + optionsManager: OptionsManager; + viewSpecs: ViewSpecHash; + dateProfileGenerators: { + [viewName: string]: DateProfileGenerator; + }; + theme: Theme; + dateEnv: DateEnv; + availableRawLocales: RawLocaleMap; + pluginSystem: PluginSystem; + defaultAllDayEventDuration: Duration; + defaultTimedEventDuration: Duration; + calendarInteractions: CalendarInteraction[]; + interactionsStore: { + [componentUid: string]: Interaction[]; + }; + removeNavLinkListener: any; + windowResizeProxy: any; + isHandlingWindowResize: boolean; + state: CalendarState; + actionQueue: any[]; + isReducing: boolean; + needsRerender: boolean; + needsFullRerender: boolean; + isRendering: boolean; + renderingPauseDepth: number; + renderableEventStore: EventStore; + buildDelayedRerender: typeof buildDelayedRerender; + delayedRerender: any; + afterSizingTriggers: any; + isViewUpdated: boolean; + isDatesUpdated: boolean; + isEventsUpdated: boolean; + el: HTMLElement; + component: CalendarComponent; + constructor(el: HTMLElement, overrides?: OptionsInput); + addPluginInputs(pluginInputs: any): void; + readonly view: View; + render(): void; + destroy(): void; + bindHandlers(): void; + unbindHandlers(): void; + hydrate(): void; + buildInitialState(): CalendarState; + reduce(state: CalendarState, action: Action, calendar: Calendar): CalendarState; + requestRerender(needsFull?: boolean): void; + tryRerender(): void; + batchRendering(func: any): void; + executeRender(): void; + renderComponent(needsFull: any): void; + setOption(name: string, val: any): void; + getOption(name: string): any; + opt(name: string): any; + viewOpt(name: string): any; + viewOpts(): any; + mutateOptions(updates: any, removals: string[], isDynamic?: boolean, deepEqual?: any): void; + handleOptions(options: any): void; + getAvailableLocaleCodes(): string[]; + _buildSelectionConfig(rawOpts: any): EventUi; + _buildEventUiSingleBase(rawOpts: any): EventUi; + hasPublicHandlers<T extends EventHandlerName>(name: T): boolean; + publiclyTrigger<T extends EventHandlerName>(name: T, args?: EventHandlerArgs<T>): any; + publiclyTriggerAfterSizing<T extends EventHandlerName>(name: T, args: EventHandlerArgs<T>): void; + releaseAfterSizingTriggers(): void; + isValidViewType(viewType: string): boolean; + changeView(viewType: string, dateOrRange?: DateRangeInput | DateInput): void; + zoomTo(dateMarker: DateMarker, viewType?: string): void; + getUnitViewSpec(unit: string): ViewSpec | null; + getInitialDate(): Date; + prev(): void; + next(): void; + prevYear(): void; + nextYear(): void; + today(): void; + gotoDate(zonedDateInput: any): void; + incrementDate(deltaInput: any): void; + getDate(): Date; + formatDate(d: DateInput, formatter: any): string; + formatRange(d0: DateInput, d1: DateInput, settings: any): any; + formatIso(d: DateInput, omitTime?: boolean): string; + windowResize(ev: Event): void; + updateSize(): void; + registerInteractiveComponent(component: DateComponent<any>, settingsInput: InteractionSettingsInput): void; + unregisterInteractiveComponent(component: DateComponent<any>): void; + select(dateOrObj: DateInput | any, endDate?: DateInput): void; + unselect(pev?: PointerDragEvent): void; + triggerDateSelect(selection: DateSpan, pev?: PointerDragEvent): void; + triggerDateUnselect(pev?: PointerDragEvent): void; + triggerDateClick(dateSpan: DateSpan, dayEl: HTMLElement, view: View, ev: UIEvent): void; + buildDatePointApi(dateSpan: DateSpan): import("@fullcalendar/core/structs/date-span").DatePointApi; + buildDateSpanApi(dateSpan: DateSpan): import("@fullcalendar/core/structs/date-span").DateSpanApi; + getNow(): DateMarker; + getDefaultEventEnd(allDay: boolean, marker: DateMarker): DateMarker; + addEvent(eventInput: EventInput, sourceInput?: EventSourceApi | string | number): EventApi | null; + getEventById(id: string): EventApi | null; + getEvents(): EventApi[]; + removeAllEvents(): void; + rerenderEvents(): void; + getEventSources(): EventSourceApi[]; + getEventSourceById(id: string | number): EventSourceApi | null; + addEventSource(sourceInput: EventSourceInput): EventSourceApi; + removeAllEventSources(): void; + refetchEvents(): void; + scrollToTime(timeInput: DurationInput): void; + } + function buildDelayedRerender(this: Calendar, wait: any): any; + export {}; +} + +declare module '@fullcalendar/core/View' { + import DateProfileGenerator, { DateProfile } from '@fullcalendar/core/DateProfileGenerator'; + import { DateMarker } from '@fullcalendar/core/datelib/marker'; + import { Duration } from '@fullcalendar/core/datelib/duration'; + import { EmitterInterface } from '@fullcalendar/core/common/EmitterMixin'; + import { ViewSpec } from '@fullcalendar/core/structs/view-spec'; + import { ComponentContext } from '@fullcalendar/core/component/Component'; + import DateComponent from '@fullcalendar/core/component/DateComponent'; + import { EventStore } from '@fullcalendar/core/structs/event-store'; + import { EventUiHash, EventUi } from '@fullcalendar/core/component/event-ui'; + import { EventRenderRange } from '@fullcalendar/core/component/event-rendering'; + import { DateSpan } from '@fullcalendar/core/structs/date-span'; + import { EventInteractionState } from '@fullcalendar/core/interactions/event-interaction-state'; + import { EventDef } from '@fullcalendar/core/structs/event'; + export interface ViewProps { + dateProfile: DateProfile; + businessHours: EventStore; + eventStore: EventStore; + eventUiBases: EventUiHash; + dateSelection: DateSpan | null; + eventSelection: string; + eventDrag: EventInteractionState | null; + eventResize: EventInteractionState | null; + } + export { View as default, View }; + abstract class View extends DateComponent<ViewProps> { + usesMinMaxTime: boolean; + dateProfileGeneratorClass: any; + on: EmitterInterface['on']; + one: EmitterInterface['one']; + off: EmitterInterface['off']; + trigger: EmitterInterface['trigger']; + triggerWith: EmitterInterface['triggerWith']; + hasHandlers: EmitterInterface['hasHandlers']; + viewSpec: ViewSpec; + dateProfileGenerator: DateProfileGenerator; + type: string; + title: string; + queuedScroll: any; + eventOrderSpecs: any; + nextDayThreshold: Duration; + isNowIndicatorRendered: boolean; + initialNowDate: DateMarker; + initialNowQueriedMs: number; + nowIndicatorTimeoutID: any; + nowIndicatorIntervalID: any; + constructor(context: ComponentContext, viewSpec: ViewSpec, dateProfileGenerator: DateProfileGenerator, parentEl: HTMLElement); + initialize(): void; + readonly activeStart: Date; + readonly activeEnd: Date; + readonly currentStart: Date; + readonly currentEnd: Date; + render(props: ViewProps): void; + destroy(): void; + updateSize(isResize: boolean, viewHeight: number, isAuto: boolean): void; + updateBaseSize(isResize: boolean, viewHeight: number, isAuto: boolean): void; + renderDatesWrap(dateProfile: DateProfile): void; + unrenderDatesWrap(): void; + renderDates(dateProfile: DateProfile): void; + unrenderDates(): void; + renderBusinessHours(businessHours: EventStore): void; + unrenderBusinessHours(): void; + renderDateSelectionWrap(selection: DateSpan): void; + unrenderDateSelectionWrap(selection: DateSpan): void; + renderDateSelection(selection: DateSpan): void; + unrenderDateSelection(selection: DateSpan): void; + renderEvents(eventStore: EventStore): void; + unrenderEvents(): void; + sliceEvents(eventStore: EventStore, allDay: boolean): EventRenderRange[]; + computeEventDraggable(eventDef: EventDef, eventUi: EventUi): boolean; + computeEventStartResizable(eventDef: EventDef, eventUi: EventUi): any; + computeEventEndResizable(eventDef: EventDef, eventUi: EventUi): boolean; + renderEventSelectionWrap(instanceId: string): void; + unrenderEventSelectionWrap(instanceId: string): void; + renderEventSelection(instanceId: string): void; + unrenderEventSelection(instanceId: string): void; + renderEventDragWrap(state: EventInteractionState): void; + unrenderEventDragWrap(state: EventInteractionState): void; + renderEventDrag(state: EventInteractionState): void; + unrenderEventDrag(state: EventInteractionState): void; + renderEventResizeWrap(state: EventInteractionState): void; + unrenderEventResizeWrap(state: EventInteractionState): void; + renderEventResize(state: EventInteractionState): void; + unrenderEventResize(state: EventInteractionState): void; + startNowIndicator(dateProfile: DateProfile): void; + updateNowIndicator(): void; + stopNowIndicator(): void; + getNowIndicatorUnit(dateProfile: DateProfile): void; + renderNowIndicator(date: any): void; + unrenderNowIndicator(): void; + addScroll(scroll: any): void; + popScroll(isResize: boolean): void; + applyQueuedScroll(isResize: boolean): void; + queryScroll(): any; + applyScroll(scroll: any, isResize: boolean): void; + computeDateScroll(duration: Duration): {}; + queryDateScroll(): {}; + applyDateScroll(scroll: any): void; + scrollToDuration(duration: Duration): void; + } +} + +declare module '@fullcalendar/core/component/renderers/FgEventRenderer' { + import { DateMarker } from '@fullcalendar/core/datelib/marker'; + import { DateFormatter } from '@fullcalendar/core/datelib/formatting'; + import { EventUi } from '@fullcalendar/core/component/event-ui'; + import { EventRenderRange } from '@fullcalendar/core/component/event-rendering'; + import { Seg } from '@fullcalendar/core/component/DateComponent'; + import { ComponentContext } from '@fullcalendar/core/component/Component'; + export { FgEventRenderer as default, FgEventRenderer }; + abstract class FgEventRenderer { + context: ComponentContext; + eventTimeFormat: DateFormatter; + displayEventTime: boolean; + displayEventEnd: boolean; + segs: Seg[]; + isSizeDirty: boolean; + constructor(context: ComponentContext); + renderSegs(segs: Seg[], mirrorInfo?: any): void; + unrender(_segs: Seg[], mirrorInfo?: any): void; + abstract renderSegHtml(seg: Seg, mirrorInfo: any): string; + abstract attachSegs(segs: Seg[], mirrorInfo: any): any; + abstract detachSegs(segs: Seg[]): any; + rangeUpdated(): void; + renderSegEls(segs: Seg[], mirrorInfo: any): Seg[]; + getSegClasses(seg: Seg, isDraggable: any, isResizable: any, mirrorInfo: any): string[]; + getTimeText(eventRange: EventRenderRange, formatter?: any, displayEnd?: any): any; + _getTimeText(start: DateMarker, end: DateMarker, allDay: any, formatter?: any, displayEnd?: any, forcedStartTzo?: number, forcedEndTzo?: number): any; + computeEventTimeFormat(): any; + computeDisplayEventTime(): boolean; + computeDisplayEventEnd(): boolean; + getSkinCss(ui: EventUi): { + 'background-color': string; + 'border-color': string; + color: string; + }; + sortEventSegs(segs: any): Seg[]; + computeSizes(force: boolean): void; + assignSizes(force: boolean): void; + computeSegSizes(segs: Seg[]): void; + assignSegSizes(segs: Seg[]): void; + hideByHash(hash: any): void; + showByHash(hash: any): void; + selectByInstanceId(instanceId: string): void; + unselectByInstanceId(instanceId: string): void; + } + export function buildSegCompareObj(seg: Seg): any; +} + +declare module '@fullcalendar/core/component/renderers/FillRenderer' { + import { Seg } from '@fullcalendar/core/component/DateComponent'; + import { ComponentContext } from '@fullcalendar/core/component/Component'; + export { FillRenderer as default, FillRenderer }; + abstract class FillRenderer { + context: ComponentContext; + fillSegTag: string; + containerElsByType: any; + segsByType: any; + dirtySizeFlags: any; + constructor(context: ComponentContext); + getSegsByType(type: string): any; + renderSegs(type: any, segs: Seg[]): void; + unrender(type: any): void; + renderSegEls(type: any, segs: Seg[]): Seg[]; + renderSegHtml(type: any, seg: Seg): string; + abstract attachSegs(type: any, segs: Seg[]): HTMLElement[] | void; + detachSegs(type: any, segs: Seg[]): void; + computeSizes(force: boolean): void; + assignSizes(force: boolean): void; + computeSegSizes(segs: Seg[]): void; + assignSegSizes(segs: Seg[]): void; + } +} + +declare module '@fullcalendar/core/DateProfileGenerator' { + import { DateMarker } from '@fullcalendar/core/datelib/marker'; + import { Duration } from '@fullcalendar/core/datelib/duration'; + import { DateRange, OpenDateRange } from '@fullcalendar/core/datelib/date-range'; + import { ViewSpec } from '@fullcalendar/core/structs/view-spec'; + import { DateEnv } from '@fullcalendar/core/datelib/env'; + import Calendar from '@fullcalendar/core/Calendar'; + export interface DateProfile { + currentRange: DateRange; + currentRangeUnit: string; + isRangeAllDay: boolean; + validRange: OpenDateRange; + activeRange: DateRange; + renderRange: DateRange; + minTime: Duration; + maxTime: Duration; + isValid: boolean; + dateIncrement: Duration; + } + export { DateProfileGenerator as default, DateProfileGenerator }; + class DateProfileGenerator { + viewSpec: ViewSpec; + options: any; + dateEnv: DateEnv; + calendar: Calendar; + isHiddenDayHash: boolean[]; + constructor(viewSpec: ViewSpec, calendar: Calendar); + buildPrev(currentDateProfile: DateProfile, currentDate: DateMarker): DateProfile; + buildNext(currentDateProfile: DateProfile, currentDate: DateMarker): DateProfile; + build(currentDate: DateMarker, direction?: any, forceToValid?: boolean): DateProfile; + buildValidRange(): OpenDateRange; + buildCurrentRangeInfo(date: DateMarker, direction: any): { + duration: any; + unit: any; + range: any; + }; + getFallbackDuration(): Duration; + adjustActiveRange(range: DateRange, minTime: Duration, maxTime: Duration): { + start: Date; + end: Date; + }; + buildRangeFromDuration(date: DateMarker, direction: any, duration: Duration, unit: any): any; + buildRangeFromDayCount(date: DateMarker, direction: any, dayCount: any): { + start: Date; + end: Date; + }; + buildCustomVisibleRange(date: DateMarker): OpenDateRange; + buildRenderRange(currentRange: DateRange, currentRangeUnit: any, isRangeAllDay: any): DateRange; + buildDateIncrement(fallback: any): Duration; + getRangeOption(name: any, ...otherArgs: any[]): OpenDateRange; + initHiddenDays(): void; + trimHiddenDays(range: DateRange): DateRange | null; + isHiddenDay(day: any): boolean; + skipHiddenDays(date: DateMarker, inc?: number, isExclusive?: boolean): Date; + } + export function isDateProfilesEqual(p0: DateProfile, p1: DateProfile): boolean; +} + +declare module '@fullcalendar/core/structs/view-def' { + import { ViewClass, ViewConfigHash } from '@fullcalendar/core/structs/view-config'; + export interface ViewDef { + type: string; + class: ViewClass; + overrides: any; + defaults: any; + } + export type ViewDefHash = { + [viewType: string]: ViewDef; + }; + export function compileViewDefs(defaultConfigs: ViewConfigHash, overrideConfigs: ViewConfigHash): ViewDefHash; +} + +declare module '@fullcalendar/core/structs/view-spec' { + import { Duration } from '@fullcalendar/core/datelib/duration'; + import OptionsManager from '@fullcalendar/core/OptionsManager'; + import { ViewConfigInputHash, ViewClass } from '@fullcalendar/core/structs/view-config'; + export interface ViewSpec { + type: string; + class: ViewClass; + duration: Duration; + durationUnit: string; + singleUnit: string; + options: any; + buttonTextOverride: string; + buttonTextDefault: string; + } + export type ViewSpecHash = { + [viewType: string]: ViewSpec; + }; + export function buildViewSpecs(defaultInputs: ViewConfigInputHash, optionsManager: OptionsManager): ViewSpecHash; +} + +declare module '@fullcalendar/core/structs/date-span' { + import { DateRange, OpenDateRange } from '@fullcalendar/core/datelib/date-range'; + import { DateInput, DateEnv } from '@fullcalendar/core/datelib/env'; + import { Duration } from '@fullcalendar/core/datelib/duration'; + import { EventRenderRange } from '@fullcalendar/core/component/event-rendering'; + import { EventUiHash } from '@fullcalendar/core/component/event-ui'; + import Calendar from '@fullcalendar/core/Calendar'; + export interface OpenDateSpanInput { + start?: DateInput; + end?: DateInput; + allDay?: boolean; + [otherProp: string]: any; + } + export interface DateSpanInput extends OpenDateSpanInput { + start: DateInput; + end: DateInput; + } + export interface OpenDateSpan { + range: OpenDateRange; + allDay: boolean; + [otherProp: string]: any; + } + export interface DateSpan extends OpenDateSpan { + range: DateRange; + } + export interface DateSpanApi { + start: Date; + end: Date; + startStr: string; + endStr: string; + allDay: boolean; + } + export interface DatePointApi { + date: Date; + dateStr: string; + allDay: boolean; + } + export function parseDateSpan(raw: DateSpanInput, dateEnv: DateEnv, defaultDuration?: Duration): DateSpan | null; + export function parseOpenDateSpan(raw: OpenDateSpanInput, dateEnv: DateEnv): OpenDateSpan | null; + export function isDateSpansEqual(span0: DateSpan, span1: DateSpan): boolean; + export function buildDateSpanApi(span: DateSpan, dateEnv: DateEnv): DateSpanApi; + export function buildDatePointApi(span: DateSpan, dateEnv: DateEnv): DatePointApi; + export function fabricateEventRange(dateSpan: DateSpan, eventUiBases: EventUiHash, calendar: Calendar): EventRenderRange; +} + +declare module '@fullcalendar/core/datelib/marker' { + import { Duration } from '@fullcalendar/core/datelib/duration'; + export type DateMarker = Date; + export const DAY_IDS: string[]; + export function addWeeks(m: DateMarker, n: number): Date; + export function addDays(m: DateMarker, n: number): Date; + export function addMs(m: DateMarker, n: number): Date; + export function diffWeeks(m0: any, m1: any): number; + export function diffDays(m0: any, m1: any): number; + export function diffHours(m0: any, m1: any): number; + export function diffMinutes(m0: any, m1: any): number; + export function diffSeconds(m0: any, m1: any): number; + export function diffDayAndTime(m0: DateMarker, m1: DateMarker): Duration; + export function diffWholeWeeks(m0: DateMarker, m1: DateMarker): number; + export function diffWholeDays(m0: DateMarker, m1: DateMarker): number; + export function startOfDay(m: DateMarker): DateMarker; + export function startOfHour(m: DateMarker): Date; + export function startOfMinute(m: DateMarker): Date; + export function startOfSecond(m: DateMarker): Date; + export function weekOfYear(marker: any, dow: any, doy: any): number; + export function dateToLocalArray(date: any): any[]; + export function arrayToLocalDate(a: any): Date; + export function dateToUtcArray(date: any): any[]; + export function arrayToUtcDate(a: any): Date; + export function isValidDate(m: DateMarker): boolean; + export function timeAsMs(m: DateMarker): number; +} + +declare module '@fullcalendar/core/datelib/duration' { + export type DurationInput = DurationObjectInput | string | number; + export interface DurationObjectInput { + years?: number; + year?: number; + months?: number; + month?: number; + weeks?: number; + week?: number; + days?: number; + day?: number; + hours?: number; + hour?: number; + minutes?: number; + minute?: number; + seconds?: number; + second?: number; + milliseconds?: number; + millisecond?: number; + ms?: number; + } + export interface Duration { + years: number; + months: number; + days: number; + milliseconds: number; + } + export function createDuration(input: DurationInput, unit?: string): Duration | null; + export function getWeeksFromInput(obj: DurationObjectInput): number; + export function durationsEqual(d0: Duration, d1: Duration): boolean; + export function isSingleDay(dur: Duration): boolean; + export function addDurations(d0: Duration, d1: Duration): { + years: number; + months: number; + days: number; + milliseconds: number; + }; + export function subtractDurations(d1: Duration, d0: Duration): Duration; + export function multiplyDuration(d: Duration, n: number): { + years: number; + months: number; + days: number; + milliseconds: number; + }; + export function asRoughYears(dur: Duration): number; + export function asRoughMonths(dur: Duration): number; + export function asRoughDays(dur: Duration): number; + export function asRoughHours(dur: Duration): number; + export function asRoughMinutes(dur: Duration): number; + export function asRoughSeconds(dur: Duration): number; + export function asRoughMs(dur: Duration): number; + export function wholeDivideDurations(numerator: Duration, denominator: Duration): number; + export function greatestDurationDenominator(dur: Duration, dontReturnWeeks?: boolean): { + unit: string; + value: number; + }; +} + +declare module '@fullcalendar/core/datelib/env' { + import { DateMarker } from '@fullcalendar/core/datelib/marker'; + import { CalendarSystem } from '@fullcalendar/core/datelib/calendar-system'; + import { Locale } from '@fullcalendar/core/datelib/locale'; + import { NamedTimeZoneImpl, NamedTimeZoneImplClass } from '@fullcalendar/core/datelib/timezone'; + import { Duration } from '@fullcalendar/core/datelib/duration'; + import { DateFormatter } from '@fullcalendar/core/datelib/formatting'; + import { CmdFormatterFunc } from '@fullcalendar/core/datelib/formatting-cmd'; + export interface DateEnvSettings { + timeZone: string; + namedTimeZoneImpl?: NamedTimeZoneImplClass; + calendarSystem: string; + locale: Locale; + weekNumberCalculation?: any; + firstDay?: any; + weekLabel?: string; + cmdFormatter?: CmdFormatterFunc; + } + export type DateInput = Date | string | number | number[]; + export interface DateMarkerMeta { + marker: DateMarker; + isTimeUnspecified: boolean; + forcedTzo: number | null; + } + export class DateEnv { + timeZone: string; + namedTimeZoneImpl: NamedTimeZoneImpl; + canComputeOffset: boolean; + calendarSystem: CalendarSystem; + locale: Locale; + weekDow: number; + weekDoy: number; + weekNumberFunc: any; + weekLabel: string; + cmdFormatter?: CmdFormatterFunc; + constructor(settings: DateEnvSettings); + createMarker(input: DateInput): DateMarker; + createNowMarker(): DateMarker; + createMarkerMeta(input: DateInput): DateMarkerMeta; + parse(s: string): { + marker: Date; + isTimeUnspecified: boolean; + forcedTzo: any; + }; + getYear(marker: DateMarker): number; + getMonth(marker: DateMarker): number; + add(marker: DateMarker, dur: Duration): DateMarker; + subtract(marker: DateMarker, dur: Duration): DateMarker; + addYears(marker: DateMarker, n: number): Date; + addMonths(marker: DateMarker, n: number): Date; + diffWholeYears(m0: DateMarker, m1: DateMarker): number; + diffWholeMonths(m0: DateMarker, m1: DateMarker): number; + greatestWholeUnit(m0: DateMarker, m1: DateMarker): { + unit: string; + value: number; + }; + countDurationsBetween(m0: DateMarker, m1: DateMarker, d: Duration): number; + startOf(m: DateMarker, unit: string): Date; + startOfYear(m: DateMarker): DateMarker; + startOfMonth(m: DateMarker): DateMarker; + startOfWeek(m: DateMarker): DateMarker; + computeWeekNumber(marker: DateMarker): number; + format(marker: DateMarker, formatter: DateFormatter, dateOptions?: { + forcedTzo?: number; + }): any; + formatRange(start: DateMarker, end: DateMarker, formatter: DateFormatter, dateOptions?: { + forcedStartTzo?: number; + forcedEndTzo?: number; + isEndExclusive?: boolean; + }): any; + formatIso(marker: DateMarker, extraOptions?: any): string; + timestampToMarker(ms: number): Date; + offsetForMarker(m: DateMarker): number; + toDate(m: DateMarker, forcedTzo?: number): Date; + } +} + +declare module '@fullcalendar/core/datelib/formatting' { + import { DateMarker } from '@fullcalendar/core/datelib/marker'; + import { CalendarSystem } from '@fullcalendar/core/datelib/calendar-system'; + import { Locale } from '@fullcalendar/core/datelib/locale'; + import { CmdFormatterFunc } from '@fullcalendar/core/datelib/formatting-cmd'; + import { FuncFormatterFunc } from '@fullcalendar/core/datelib/formatting-func'; + export interface ZonedMarker { + marker: DateMarker; + timeZoneOffset: number; + } + export interface ExpandedZonedMarker extends ZonedMarker { + array: number[]; + year: number; + month: number; + day: number; + hour: number; + minute: number; + second: number; + millisecond: number; + } + export interface VerboseFormattingArg { + date: ExpandedZonedMarker; + start: ExpandedZonedMarker; + end?: ExpandedZonedMarker; + timeZone: string; + localeCodes: string[]; + separator: string; + } + export interface DateFormattingContext { + timeZone: string; + locale: Locale; + calendarSystem: CalendarSystem; + computeWeekNumber: (d: DateMarker) => number; + weekLabel: string; + cmdFormatter?: CmdFormatterFunc; + } + export interface DateFormatter { + format(date: ZonedMarker, context: DateFormattingContext): any; + formatRange(start: ZonedMarker, end: ZonedMarker, context: DateFormattingContext): any; + } + export type FormatterInput = object | string | FuncFormatterFunc; + export function createFormatter(input: FormatterInput, defaultSeparator?: string): DateFormatter; + export function buildIsoString(marker: DateMarker, timeZoneOffset?: number, stripZeroTime?: boolean): string; + export function formatIsoTimeString(marker: DateMarker): string; + export function formatTimeZoneOffset(minutes: number, doIso?: boolean): string; + export function createVerboseFormattingArg(start: ZonedMarker, end: ZonedMarker, context: DateFormattingContext, separator?: string): VerboseFormattingArg; +} + +declare module '@fullcalendar/core/datelib/timezone' { + export abstract class NamedTimeZoneImpl { + timeZoneName: string; + constructor(timeZoneName: string); + abstract offsetForArray(a: number[]): number; + abstract timestampToArray(ms: number): number[]; + } + export type NamedTimeZoneImplClass = { + new (timeZoneName: string): NamedTimeZoneImpl; + }; +} + +declare module '@fullcalendar/core/datelib/parsing' { + export function parse(str: any): { + marker: Date; + isTimeUnspecified: boolean; + timeZoneOffset: any; + }; +} + +declare module '@fullcalendar/core/structs/event-source' { + import { EventInput } from '@fullcalendar/core/structs/event'; + import Calendar from '@fullcalendar/core/Calendar'; + import { DateRange } from '@fullcalendar/core/datelib/date-range'; + import { EventSourceFunc } from '@fullcalendar/core/event-sources/func-event-source'; + import { EventUi } from '@fullcalendar/core/component/event-ui'; + import { ConstraintInput, AllowFunc } from '@fullcalendar/core/validation'; + export type EventSourceError = { + message: string; + response?: any; + [otherProp: string]: any; + }; + export type EventInputTransformer = (eventInput: EventInput) => EventInput | null; + export type EventSourceSuccessResponseHandler = (rawData: any, response: any) => EventInput[] | void; + export type EventSourceErrorResponseHandler = (error: EventSourceError) => void; + export interface ExtendedEventSourceInput { + id?: string | number; + allDayDefault?: boolean; + eventDataTransform?: EventInputTransformer; + events?: EventInput[] | EventSourceFunc; + url?: string; + method?: string; + extraParams?: object | (() => object); + startParam?: string; + endParam?: string; + timeZoneParam?: string; + success?: EventSourceSuccessResponseHandler; + failure?: EventSourceErrorResponseHandler; + editable?: boolean; + startEditable?: boolean; + durationEditable?: boolean; + constraint?: ConstraintInput; + overlap?: boolean; + allow?: AllowFunc; + className?: string[] | string; + classNames?: string[] | string; + backgroundColor?: string; + borderColor?: string; + textColor?: string; + color?: string; + [otherProp: string]: any; + } + export type EventSourceInput = ExtendedEventSourceInput | // object in extended form + EventSourceFunc | // just a function + string; + export interface EventSource { + _raw: any; + sourceId: string; + sourceDefId: number; + meta: any; + publicId: string; + isFetching: boolean; + latestFetchId: string; + fetchRange: DateRange | null; + allDayDefault: boolean | null; + eventDataTransform: EventInputTransformer; + ui: EventUi; + success: EventSourceSuccessResponseHandler | null; + failure: EventSourceErrorResponseHandler | null; + extendedProps: any; + } + export type EventSourceHash = { + [sourceId: string]: EventSource; + }; + export type EventSourceFetcher = (arg: { + eventSource: EventSource; + calendar: Calendar; + range: DateRange; + }, success: (res: { + rawEvents: EventInput[]; + xhr?: XMLHttpRequest; + }) => void, failure: (error: EventSourceError) => void) => (void | PromiseLike<EventInput[]>); + export interface EventSourceDef { + ignoreRange?: boolean; + parseMeta: (raw: EventSourceInput) => object | null; + fetch: EventSourceFetcher; + } + export function doesSourceNeedRange(eventSource: EventSource, calendar: Calendar): boolean; + export function parseEventSource(raw: EventSourceInput, calendar: Calendar): EventSource | null; +} + +declare module '@fullcalendar/core/interactions/interaction' { + import DateComponent from '@fullcalendar/core/component/DateComponent'; + export abstract class Interaction { + component: DateComponent<any>; + constructor(settings: InteractionSettings); + destroy(): void; + } + export type InteractionClass = { + new (settings: InteractionSettings): Interaction; + }; + export interface InteractionSettingsInput { + el: HTMLElement; + useEventCenter?: boolean; + } + export interface InteractionSettings { + component: DateComponent<any>; + el: HTMLElement; + useEventCenter: boolean; + } + export type InteractionSettingsStore = { + [componenUid: string]: InteractionSettings; + }; + export function parseInteractionSettings(component: DateComponent<any>, input: InteractionSettingsInput): InteractionSettings; + export function interactionSettingsToStore(settings: InteractionSettings): { + [x: string]: InteractionSettings; + }; + export let interactionSettingsStore: InteractionSettingsStore; +} + +declare module '@fullcalendar/core/interactions/pointer' { + export interface PointerDragEvent { + origEvent: UIEvent; + isTouch: boolean; + subjectEl: EventTarget; + pageX: number; + pageY: number; + deltaX: number; + deltaY: number; + } +} + +declare module '@fullcalendar/core/interactions/hit' { + import DateComponent from '@fullcalendar/core/component/DateComponent'; + import { DateSpan } from '@fullcalendar/core/structs/date-span'; + import { Rect } from '@fullcalendar/core/util/geom'; + export interface Hit { + component: DateComponent<any>; + dateSpan: DateSpan; + dayEl: HTMLElement; + rect: Rect; + layer: number; + } +} + +declare module '@fullcalendar/core/interactions/date-selecting' { + import { Hit } from '@fullcalendar/core/interactions/hit'; + export type dateSelectionJoinTransformer = (hit0: Hit, hit1: Hit) => any; +} + +declare module '@fullcalendar/core/interactions/event-dragging' { + import Calendar from '@fullcalendar/core/Calendar'; + import { EventMutation } from '@fullcalendar/core/structs/event-mutation'; + import { Hit } from '@fullcalendar/core/interactions/hit'; + import { EventDef } from '@fullcalendar/core/structs/event'; + import { EventUi } from '@fullcalendar/core/component/event-ui'; + import { View } from '@fullcalendar/core'; + export type eventDragMutationMassager = (mutation: EventMutation, hit0: Hit, hit1: Hit) => void; + export type EventDropTransformers = (mutation: EventMutation, calendar: Calendar) => any; + export type eventIsDraggableTransformer = (val: boolean, eventDef: EventDef, eventUi: EventUi, view: View) => boolean; +} + +declare module '@fullcalendar/core/interactions/event-resizing' { + import { Hit } from '@fullcalendar/core/interactions/hit'; + export type EventResizeJoinTransforms = (hit0: Hit, hit1: Hit) => false | object; +} + +declare module '@fullcalendar/core/interactions/ElementDragging' { + import EmitterMixin from '@fullcalendar/core/common/EmitterMixin'; + export { ElementDragging as default, ElementDragging }; + abstract class ElementDragging { + emitter: EmitterMixin; + constructor(el: HTMLElement); + destroy(): void; + abstract setIgnoreMove(bool: boolean): void; + setMirrorIsVisible(bool: boolean): void; + setMirrorNeedsRevert(bool: boolean): void; + setAutoScrollEnabled(bool: boolean): void; + } + export type ElementDraggingClass = { + new (el: HTMLElement): ElementDragging; + }; +} + +declare module '@fullcalendar/core/formatting-api' { + import { DateInput } from '@fullcalendar/core/datelib/env'; + export function formatDate(dateInput: DateInput, settings?: {}): any; + export function formatRange(startInput: DateInput, endInput: DateInput, settings: any): any; +} + +declare module '@fullcalendar/core/options' { + import { PluginDef } from '@fullcalendar/core/plugin-system'; + export const config: any; + export const globalDefaults: { + defaultRangeSeparator: string; + titleRangeSeparator: string; + defaultTimedEventDuration: string; + defaultAllDayEventDuration: { + day: number; + }; + forceEventDuration: boolean; + nextDayThreshold: string; + columnHeader: boolean; + defaultView: string; + aspectRatio: number; + header: { + left: string; + center: string; + right: string; + }; + weekends: boolean; + weekNumbers: boolean; + weekNumberCalculation: string; + editable: boolean; + scrollTime: string; + minTime: string; + maxTime: string; + showNonCurrentDates: boolean; + lazyFetching: boolean; + startParam: string; + endParam: string; + timeZoneParam: string; + timeZone: string; + locales: any[]; + locale: string; + timeGridEventMinHeight: number; + themeSystem: string; + dragRevertDuration: number; + dragScroll: boolean; + allDayMaintainDuration: boolean; + unselectAuto: boolean; + dropAccept: string; + eventOrder: string; + eventLimit: boolean; + eventLimitClick: string; + dayPopoverFormat: { + month: string; + day: string; + year: string; + }; + handleWindowResize: boolean; + windowResizeDelay: number; + longPressDelay: number; + eventDragMinDistance: number; + }; + export const rtlDefaults: { + header: { + left: string; + center: string; + right: string; + }; + buttonIcons: { + prev: string; + next: string; + prevYear: string; + nextYear: string; + }; + }; + export function mergeOptions(optionObjs: any): any; + export function refinePluginDefs(pluginInputs: any[]): PluginDef[]; +} + +declare module '@fullcalendar/core/structs/recurring-event' { + import { EventInput, EventDef } from '@fullcalendar/core/structs/event'; + import { DateRange } from '@fullcalendar/core/datelib/date-range'; + import { DateEnv } from '@fullcalendar/core/datelib/env'; + import { Duration } from '@fullcalendar/core/datelib/duration'; + import { DateMarker } from '@fullcalendar/core/datelib/marker'; + export interface ParsedRecurring { + typeData: any; + allDayGuess: boolean | null; + duration: Duration | null; + } + export interface RecurringType { + parse: (rawEvent: EventInput, leftoverProps: any, dateEnv: DateEnv) => ParsedRecurring | null; + expand: (typeData: any, framingRange: DateRange, dateEnv: DateEnv) => DateMarker[]; + } + export function parseRecurring(eventInput: EventInput, allDayDefault: boolean | null, dateEnv: DateEnv, recurringTypes: RecurringType[], leftovers: any): { + allDay: any; + duration: Duration; + typeData: any; + typeId: number; + }; + export function expandRecurringRanges(eventDef: EventDef, duration: Duration, framingRange: DateRange, dateEnv: DateEnv, recurringTypes: RecurringType[]): DateMarker[]; +} + +declare module '@fullcalendar/core/structs/drag-meta' { + import { Duration, DurationInput } from '@fullcalendar/core/datelib/duration'; + import { EventNonDateInput } from '@fullcalendar/core/structs/event'; + export interface DragMetaInput extends EventNonDateInput { + startTime?: DurationInput; + duration?: DurationInput; + create?: boolean; + sourceId?: string; + } + export interface DragMeta { + startTime: Duration | null; + duration: Duration | null; + create: boolean; + sourceId: string; + leftoverProps: object; + } + export function parseDragMeta(raw: DragMetaInput): DragMeta; +} + +declare module '@fullcalendar/core/plugin-system' { + import { reducerFunc } from '@fullcalendar/core/reducers/types'; + import { eventDefParserFunc } from '@fullcalendar/core/structs/event'; + import { eventDefMutationApplier } from '@fullcalendar/core/structs/event-mutation'; + import Calendar, { DatePointTransform, DateSpanTransform, CalendarInteractionClass, OptionChangeHandlerMap } from '@fullcalendar/core/Calendar'; + import { ViewConfigInputHash } from '@fullcalendar/core/structs/view-config'; + import { ViewSpec } from '@fullcalendar/core/structs/view-spec'; + import View, { ViewProps } from '@fullcalendar/core/View'; + import { CalendarComponentProps } from '@fullcalendar/core/CalendarComponent'; + import { isPropsValidTester } from '@fullcalendar/core/validation'; + import { eventDragMutationMassager, eventIsDraggableTransformer, EventDropTransformers } from '@fullcalendar/core/interactions/event-dragging'; + import { dateSelectionJoinTransformer } from '@fullcalendar/core/interactions/date-selecting'; + import { EventResizeJoinTransforms } from '@fullcalendar/core/interactions/event-resizing'; + import { ExternalDefTransform } from '@fullcalendar/core/interactions/external-element-dragging'; + import { InteractionClass } from '@fullcalendar/core/interactions/interaction'; + import { ThemeClass } from '@fullcalendar/core/theme/Theme'; + import { EventSourceDef } from '@fullcalendar/core/structs/event-source'; + import { CmdFormatterFunc } from '@fullcalendar/core/datelib/formatting-cmd'; + import { RecurringType } from '@fullcalendar/core/structs/recurring-event'; + import { NamedTimeZoneImplClass } from '@fullcalendar/core/datelib/timezone'; + import { ElementDraggingClass } from '@fullcalendar/core/interactions/ElementDragging'; + export interface PluginDefInput { + deps?: PluginDef[]; + reducers?: reducerFunc[]; + eventDefParsers?: eventDefParserFunc[]; + isDraggableTransformers?: eventIsDraggableTransformer[]; + eventDragMutationMassagers?: eventDragMutationMassager[]; + eventDefMutationAppliers?: eventDefMutationApplier[]; + dateSelectionTransformers?: dateSelectionJoinTransformer[]; + datePointTransforms?: DatePointTransform[]; + dateSpanTransforms?: DateSpanTransform[]; + views?: ViewConfigInputHash; + viewPropsTransformers?: ViewPropsTransformerClass[]; + isPropsValid?: isPropsValidTester; + externalDefTransforms?: ExternalDefTransform[]; + eventResizeJoinTransforms?: EventResizeJoinTransforms[]; + viewContainerModifiers?: ViewContainerModifier[]; + eventDropTransformers?: EventDropTransformers[]; + componentInteractions?: InteractionClass[]; + calendarInteractions?: CalendarInteractionClass[]; + themeClasses?: { + [themeSystemName: string]: ThemeClass; + }; + eventSourceDefs?: EventSourceDef[]; + cmdFormatter?: CmdFormatterFunc; + recurringTypes?: RecurringType[]; + namedTimeZonedImpl?: NamedTimeZoneImplClass; + defaultView?: string; + elementDraggingImpl?: ElementDraggingClass; + optionChangeHandlers?: OptionChangeHandlerMap; + } + export interface PluginHooks { + reducers: reducerFunc[]; + eventDefParsers: eventDefParserFunc[]; + isDraggableTransformers: eventIsDraggableTransformer[]; + eventDragMutationMassagers: eventDragMutationMassager[]; + eventDefMutationAppliers: eventDefMutationApplier[]; + dateSelectionTransformers: dateSelectionJoinTransformer[]; + datePointTransforms: DatePointTransform[]; + dateSpanTransforms: DateSpanTransform[]; + views: ViewConfigInputHash; + viewPropsTransformers: ViewPropsTransformerClass[]; + isPropsValid: isPropsValidTester | null; + externalDefTransforms: ExternalDefTransform[]; + eventResizeJoinTransforms: EventResizeJoinTransforms[]; + viewContainerModifiers: ViewContainerModifier[]; + eventDropTransformers: EventDropTransformers[]; + componentInteractions: InteractionClass[]; + calendarInteractions: CalendarInteractionClass[]; + themeClasses: { + [themeSystemName: string]: ThemeClass; + }; + eventSourceDefs: EventSourceDef[]; + cmdFormatter?: CmdFormatterFunc; + recurringTypes: RecurringType[]; + namedTimeZonedImpl?: NamedTimeZoneImplClass; + defaultView: string; + elementDraggingImpl?: ElementDraggingClass; + optionChangeHandlers: OptionChangeHandlerMap; + } + export interface PluginDef extends PluginHooks { + id: string; + deps: PluginDef[]; + } + export type ViewPropsTransformerClass = new () => ViewPropsTransformer; + export interface ViewPropsTransformer { + transform(viewProps: ViewProps, viewSpec: ViewSpec, calendarProps: CalendarComponentProps, view: View): any; + } + export type ViewContainerModifier = (contentEl: HTMLElement, calendar: Calendar) => void; + export function createPlugin(input: PluginDefInput): PluginDef; + export class PluginSystem { + hooks: PluginHooks; + addedHash: { + [pluginId: string]: true; + }; + constructor(); + add(plugin: PluginDef): void; + } +} + +declare module '@fullcalendar/core/reducers/types' { + import { EventInput, EventInstanceHash } from '@fullcalendar/core/structs/event'; + import { DateRange } from '@fullcalendar/core/datelib/date-range'; + import { EventStore } from '@fullcalendar/core/structs/event-store'; + import { EventMutation } from '@fullcalendar/core/structs/event-mutation'; + import { EventSource, EventSourceHash, EventSourceError } from '@fullcalendar/core/structs/event-source'; + import { DateProfile } from '@fullcalendar/core/DateProfileGenerator'; + import { EventInteractionState } from '@fullcalendar/core/interactions/event-interaction-state'; + import { DateSpan } from '@fullcalendar/core/structs/date-span'; + import { DateEnv } from '@fullcalendar/core/datelib/env'; + import Calendar from '@fullcalendar/core/Calendar'; + import { DateMarker } from '@fullcalendar/core/datelib/marker'; + export interface CalendarState { + eventSources: EventSourceHash; + eventSourceLoadingLevel: number; + loadingLevel: number; + viewType: string; + currentDate: DateMarker; + dateProfile: DateProfile | null; + eventStore: EventStore; + dateSelection: DateSpan | null; + eventSelection: string; + eventDrag: EventInteractionState | null; + eventResize: EventInteractionState | null; + } + export type reducerFunc = (state: CalendarState, action: Action, calendar: Calendar) => CalendarState; + export type Action = { + type: 'INIT'; + } | // wont it create another rerender? + { + type: 'PREV'; + } | { + type: 'NEXT'; + } | { + type: 'SET_DATE'; + dateMarker: DateMarker; + } | { + type: 'SET_VIEW_TYPE'; + viewType: string; + dateMarker?: DateMarker; + } | { + type: 'SELECT_DATES'; + selection: DateSpan; + } | { + type: 'UNSELECT_DATES'; + } | { + type: 'SELECT_EVENT'; + eventInstanceId: string; + } | { + type: 'UNSELECT_EVENT'; + } | { + type: 'SET_EVENT_DRAG'; + state: EventInteractionState; + } | { + type: 'UNSET_EVENT_DRAG'; + } | { + type: 'SET_EVENT_RESIZE'; + state: EventInteractionState; + } | { + type: 'UNSET_EVENT_RESIZE'; + } | { + type: 'ADD_EVENT_SOURCES'; + sources: EventSource[]; + } | { + type: 'REMOVE_EVENT_SOURCE'; + sourceId: string; + } | { + type: 'REMOVE_ALL_EVENT_SOURCES'; + } | { + type: 'FETCH_EVENT_SOURCES'; + sourceIds?: string[]; + } | // if no sourceIds, fetch all + { + type: 'CHANGE_TIMEZONE'; + oldDateEnv: DateEnv; + } | { + type: 'RECEIVE_EVENTS'; + sourceId: string; + fetchId: string; + fetchRange: DateRange | null; + rawEvents: EventInput[]; + } | { + type: 'RECEIVE_EVENT_ERROR'; + sourceId: string; + fetchId: string; + fetchRange: DateRange | null; + error: EventSourceError; + } | // need all these? + { + type: 'ADD_EVENTS'; + eventStore: EventStore; + } | { + type: 'MERGE_EVENTS'; + eventStore: EventStore; + } | { + type: 'MUTATE_EVENTS'; + instanceId: string; + mutation: EventMutation; + fromApi?: boolean; + } | { + type: 'REMOVE_EVENT_DEF'; + defId: string; + } | { + type: 'REMOVE_EVENT_INSTANCES'; + instances: EventInstanceHash; + } | { + type: 'REMOVE_ALL_EVENTS'; + } | { + type: 'RESET_EVENTS'; + }; +} + +declare module '@fullcalendar/core/CalendarComponent' { + import Component, { ComponentContext } from '@fullcalendar/core/component/Component'; + import { ViewSpec } from '@fullcalendar/core/structs/view-spec'; + import View from '@fullcalendar/core/View'; + import Toolbar from '@fullcalendar/core/Toolbar'; + import DateProfileGenerator, { DateProfile } from '@fullcalendar/core/DateProfileGenerator'; + import { EventStore } from '@fullcalendar/core/structs/event-store'; + import { EventUiHash } from '@fullcalendar/core/component/event-ui'; + import { BusinessHoursInput } from '@fullcalendar/core/structs/business-hours'; + import { DateMarker } from '@fullcalendar/core/datelib/marker'; + import { CalendarState } from '@fullcalendar/core/reducers/types'; + export interface CalendarComponentProps extends CalendarState { + viewSpec: ViewSpec; + dateProfileGenerator: DateProfileGenerator; + eventUiBases: EventUiHash; + } + export { CalendarComponent as default, CalendarComponent }; + class CalendarComponent extends Component<CalendarComponentProps> { + view: View; + header: Toolbar; + footer: Toolbar; + computeTitle: (dateProfile: any, viewOptions: any) => string; + parseBusinessHours: (input: BusinessHoursInput) => EventStore; + el: HTMLElement; + contentEl: HTMLElement; + isHeightAuto: boolean; + viewHeight: number; + constructor(context: ComponentContext, el: HTMLElement); + destroy(): void; + toggleElClassNames(bool: boolean): void; + render(props: CalendarComponentProps): void; + renderToolbars(viewSpec: ViewSpec, dateProfile: DateProfile, currentDate: DateMarker, dateProfileGenerator: DateProfileGenerator, title: string): void; + renderView(props: CalendarComponentProps, title: string): void; + updateSize(isResize?: boolean): void; + computeHeightVars(): void; + queryToolbarsHeight(): number; + freezeHeight(): void; + thawHeight(): void; + } +} + +declare module '@fullcalendar/core/common/DayHeader' { + import Component, { ComponentContext } from '@fullcalendar/core/component/Component'; + import { DateMarker } from '@fullcalendar/core/datelib/marker'; + import { DateProfile } from '@fullcalendar/core/DateProfileGenerator'; + export interface DayTableHeaderProps { + dates: DateMarker[]; + dateProfile: DateProfile; + datesRepDistinctDays: boolean; + renderIntroHtml?: () => string; + } + export { DayHeader as default, DayHeader }; + class DayHeader extends Component<DayTableHeaderProps> { + el: HTMLElement; + thead: HTMLElement; + constructor(context: ComponentContext, parentEl: HTMLElement); + destroy(): void; + render(props: DayTableHeaderProps): void; + } +} + +declare module '@fullcalendar/core/common/table-utils' { + import { DateMarker } from '@fullcalendar/core/datelib/marker'; + import { DateProfile } from '@fullcalendar/core/DateProfileGenerator'; + import { ComponentContext } from '@fullcalendar/core/component/Component'; + export function computeFallbackHeaderFormat(datesRepDistinctDays: boolean, dayCnt: number): { + weekday: string; + month?: undefined; + day?: undefined; + omitCommas?: undefined; + } | { + weekday: string; + month: string; + day: string; + omitCommas: boolean; + }; + export function renderDateCell(dateMarker: DateMarker, dateProfile: DateProfile, datesRepDistinctDays: any, colCnt: any, colHeadFormat: any, context: ComponentContext, colspan?: any, otherAttrs?: any): string; +} + +declare module '@fullcalendar/core/common/DaySeries' { + import DateProfileGenerator from '@fullcalendar/core/DateProfileGenerator'; + import { DateMarker } from '@fullcalendar/core/datelib/marker'; + import { DateRange } from '@fullcalendar/core/datelib/date-range'; + export interface DaySeriesSeg { + firstIndex: number; + lastIndex: number; + isStart: boolean; + isEnd: boolean; + } + export { DaySeries as default, DaySeries }; + class DaySeries { + cnt: number; + dates: DateMarker[]; + indices: number[]; + constructor(range: DateRange, dateProfileGenerator: DateProfileGenerator); + sliceRange(range: DateRange): DaySeriesSeg | null; + } +} + +declare module '@fullcalendar/core/interactions/event-interaction-state' { + import { EventStore } from '@fullcalendar/core/structs/event-store'; + import { Seg } from '@fullcalendar/core/component/DateComponent'; + export interface EventInteractionState { + affectedEvents: EventStore; + mutatedEvents: EventStore; + isEvent: boolean; + origSeg: Seg | null; + } +} + +declare module '@fullcalendar/core/component/event-rendering' { + import { EventDef, EventTuple, EventDefHash } from '@fullcalendar/core/structs/event'; + import { EventStore } from '@fullcalendar/core/structs/event-store'; + import { DateRange } from '@fullcalendar/core/datelib/date-range'; + import { Duration } from '@fullcalendar/core/datelib/duration'; + import { Seg } from '@fullcalendar/core/component/DateComponent'; + import View from '@fullcalendar/core/View'; + import { EventUi, EventUiHash } from '@fullcalendar/core/component/event-ui'; + export interface EventRenderRange extends EventTuple { + ui: EventUi; + range: DateRange; + isStart: boolean; + isEnd: boolean; + } + export function sliceEventStore(eventStore: EventStore, eventUiBases: EventUiHash, framingRange: DateRange, nextDayThreshold?: Duration): { + bg: EventRenderRange[]; + fg: EventRenderRange[]; + }; + export function hasBgRendering(def: EventDef): boolean; + export function filterSegsViaEls(view: View, segs: Seg[], isMirror: boolean): Seg[]; + export function getElSeg(el: HTMLElement): Seg | null; + export function compileEventUis(eventDefs: EventDefHash, eventUiBases: EventUiHash): { + [key: string]: EventUi; + }; + export function compileEventUi(eventDef: EventDef, eventUiBases: EventUiHash): EventUi; +} + +declare module '@fullcalendar/core/common/DayTable' { + import DaySeries from '@fullcalendar/core/common/DaySeries'; + import { DateRange } from '@fullcalendar/core/datelib/date-range'; + import { DateMarker } from '@fullcalendar/core/datelib/marker'; + import { Seg } from '@fullcalendar/core/component/DateComponent'; + export interface DayTableSeg extends Seg { + row: number; + firstCol: number; + lastCol: number; + } + export interface DayTableCell { + date: DateMarker; + htmlAttrs?: string; + } + export { DayTable as default, DayTable }; + class DayTable { + rowCnt: number; + colCnt: number; + cells: DayTableCell[][]; + headerDates: DateMarker[]; + constructor(daySeries: DaySeries, breakOnWeeks: boolean); + sliceRange(range: DateRange): DayTableSeg[]; + } +} + +declare module '@fullcalendar/core/common/slicing-utils' { + import { DateRange } from '@fullcalendar/core/datelib/date-range'; + import { EventStore } from '@fullcalendar/core/structs/event-store'; + import { EventUiHash } from '@fullcalendar/core/component/event-ui'; + import { DateProfile } from '@fullcalendar/core/DateProfileGenerator'; + import DateComponent, { Seg, EventSegUiInteractionState } from '@fullcalendar/core/component/DateComponent'; + import { DateSpan } from '@fullcalendar/core/structs/date-span'; + import { EventInteractionState } from '@fullcalendar/core/interactions/event-interaction-state'; + import { Duration } from '@fullcalendar/core/datelib/duration'; + import { DateMarker } from '@fullcalendar/core/datelib/marker'; + export interface SliceableProps { + dateSelection: DateSpan; + businessHours: EventStore; + eventStore: EventStore; + eventDrag: EventInteractionState | null; + eventResize: EventInteractionState | null; + eventSelection: string; + eventUiBases: EventUiHash; + } + export interface SlicedProps<SegType extends Seg> { + dateSelectionSegs: SegType[]; + businessHourSegs: SegType[]; + fgEventSegs: SegType[]; + bgEventSegs: SegType[]; + eventDrag: EventSegUiInteractionState | null; + eventResize: EventSegUiInteractionState | null; + eventSelection: string; + } + export { Slicer as default, Slicer }; + abstract class Slicer<SegType extends Seg, ExtraArgs extends any[] = []> { + abstract sliceRange(dateRange: DateRange, ...extraArgs: ExtraArgs): SegType[]; + sliceProps(props: SliceableProps, dateProfile: DateProfile, nextDayThreshold: Duration | null, component: DateComponent<any>, // TODO: kill + ...extraArgs: ExtraArgs): SlicedProps<SegType>; + sliceNowDate(// does not memoize + date: DateMarker, component: DateComponent<any>, // TODO: kill + ...extraArgs: ExtraArgs): SegType[]; + } +} + +declare module '@fullcalendar/core/structs/event-mutation' { + import { Duration } from '@fullcalendar/core/datelib/duration'; + import { EventStore } from '@fullcalendar/core/structs/event-store'; + import { EventDef } from '@fullcalendar/core/structs/event'; + import Calendar from '@fullcalendar/core/Calendar'; + import { EventUiHash } from '@fullcalendar/core/component/event-ui'; + export interface EventMutation { + datesDelta?: Duration; + startDelta?: Duration; + endDelta?: Duration; + standardProps?: any; + extendedProps?: any; + } + export function applyMutationToEventStore(eventStore: EventStore, eventConfigBase: EventUiHash, mutation: EventMutation, calendar: Calendar): EventStore; + export type eventDefMutationApplier = (eventDef: EventDef, mutation: EventMutation, calendar: Calendar) => void; +} + +declare module '@fullcalendar/core/validation' { + import { EventStore } from '@fullcalendar/core/structs/event-store'; + import Calendar from '@fullcalendar/core/Calendar'; + import { DateSpan, DateSpanApi } from '@fullcalendar/core/structs/date-span'; + import EventApi from '@fullcalendar/core/api/EventApi'; + import { EventInput } from '@fullcalendar/core/structs/event'; + import { EventInteractionState } from '@fullcalendar/core/interactions/event-interaction-state'; + import { SplittableProps } from '@fullcalendar/core/component/event-splitting'; + export type ConstraintInput = 'businessHours' | string | EventInput | EventInput[]; + export type Constraint = 'businessHours' | string | EventStore | false; + export type OverlapFunc = ((stillEvent: EventApi, movingEvent: EventApi | null) => boolean); + export type AllowFunc = (span: DateSpanApi, movingEvent: EventApi | null) => boolean; + export type isPropsValidTester = (props: SplittableProps, calendar: Calendar) => boolean; + export function isInteractionValid(interaction: EventInteractionState, calendar: Calendar): boolean; + export function isDateSelectionValid(dateSelection: DateSpan, calendar: Calendar): boolean; + export function isPropsValid(state: SplittableProps, calendar: Calendar, dateSpanMeta?: {}, filterConfig?: any): boolean; + export function normalizeConstraint(input: ConstraintInput, calendar: Calendar): Constraint | null; +} + +declare module '@fullcalendar/core/api/EventApi' { + import Calendar from '@fullcalendar/core/Calendar'; + import { EventDef, EventInstance } from '@fullcalendar/core/structs/event'; + import { EventMutation } from '@fullcalendar/core/structs/event-mutation'; + import { DateInput } from '@fullcalendar/core/datelib/env'; + import { DurationInput } from '@fullcalendar/core/datelib/duration'; + import { FormatterInput } from '@fullcalendar/core/datelib/formatting'; + import EventSourceApi from '@fullcalendar/core/api/EventSourceApi'; + export { EventApi as default, EventApi }; + class EventApi { + _calendar: Calendar; + _def: EventDef; + _instance: EventInstance | null; + constructor(calendar: Calendar, def: EventDef, instance?: EventInstance); + setProp(name: string, val: string): void; + setExtendedProp(name: string, val: any): void; + setStart(startInput: DateInput, options?: { + granularity?: string; + maintainDuration?: boolean; + }): void; + setEnd(endInput: DateInput | null, options?: { + granularity?: string; + }): void; + setDates(startInput: DateInput, endInput: DateInput | null, options?: { + allDay?: boolean; + granularity?: string; + }): void; + moveStart(deltaInput: DurationInput): void; + moveEnd(deltaInput: DurationInput): void; + moveDates(deltaInput: DurationInput): void; + setAllDay(allDay: boolean, options?: { + maintainDuration?: boolean; + }): void; + formatRange(formatInput: FormatterInput): any; + mutate(mutation: EventMutation): void; + remove(): void; + readonly source: EventSourceApi | null; + readonly start: Date | null; + readonly end: Date | null; + readonly id: string; + readonly groupId: string; + readonly allDay: boolean; + readonly title: string; + readonly url: string; + readonly rendering: string; + readonly startEditable: boolean; + readonly durationEditable: boolean; + readonly constraint: any; + readonly overlap: any; + readonly allow: any; + readonly backgroundColor: string; + readonly borderColor: string; + readonly textColor: string; + readonly classNames: string[]; + readonly extendedProps: any; + } +} + +declare module '@fullcalendar/core/util/requestJson' { + export default function requestJson(method: string, url: string, params: object, successCallback: any, failureCallback: any): void; +} + +declare module '@fullcalendar/core/datelib/locale' { + export type LocaleCodeArg = string | string[]; + export type LocaleSingularArg = LocaleCodeArg | RawLocale; + export interface Locale { + codeArg: LocaleCodeArg; + codes: string[]; + week: { + dow: number; + doy: number; + }; + simpleNumberFormat: Intl.NumberFormat; + options: any; + } + export interface RawLocale { + code: string; + [otherProp: string]: any; + } + export type RawLocaleMap = { + [code: string]: RawLocale; + }; + export interface RawLocaleInfo { + map: RawLocaleMap; + defaultCode: string; + } + export function parseRawLocales(explicitRawLocales: RawLocale[]): RawLocaleInfo; + export function buildLocale(inputSingular: LocaleSingularArg, available: RawLocaleMap): Locale; +} + +declare module '@fullcalendar/core/OptionsManager' { + export { OptionsManager as default, OptionsManager }; + class OptionsManager { + dirDefaults: any; + localeDefaults: any; + overrides: any; + dynamicOverrides: any; + computed: any; + constructor(overrides: any); + mutate(updates: any, removals: string[], isDynamic?: boolean): void; + compute(): void; + } +} + +declare module '@fullcalendar/core/api/EventSourceApi' { + import Calendar from '@fullcalendar/core/Calendar'; + import { EventSource } from '@fullcalendar/core/structs/event-source'; + export { EventSourceApi as default, EventSourceApi }; + class EventSourceApi { + calendar: Calendar; + internalEventSource: EventSource; + constructor(calendar: Calendar, internalEventSource: EventSource); + remove(): void; + refetch(): void; + readonly id: string; + readonly url: string; + } +} + +declare module '@fullcalendar/core/structs/view-config' { + import View from '@fullcalendar/core/View'; + import { ViewSpec } from '@fullcalendar/core/structs/view-spec'; + import { ComponentContext } from '@fullcalendar/core/component/Component'; + import DateProfileGenerator from '@fullcalendar/core/DateProfileGenerator'; + export type ViewClass = new (context: ComponentContext, viewSpec: ViewSpec, dateProfileGenerator: DateProfileGenerator, parentEl: HTMLElement) => View; + export interface ViewConfigObjectInput { + type?: string; + class?: ViewClass; + [optionName: string]: any; + } + export type ViewConfigInput = ViewClass | ViewConfigObjectInput; + export type ViewConfigInputHash = { + [viewType: string]: ViewConfigInput; + }; + export interface ViewConfig { + superType: string; + class: ViewClass | null; + options: any; + } + export type ViewConfigHash = { + [viewType: string]: ViewConfig; + }; + export function parseViewConfigs(inputs: ViewConfigInputHash): ViewConfigHash; +} + +declare module '@fullcalendar/core/datelib/calendar-system' { + import { DateMarker } from '@fullcalendar/core/datelib/marker'; + export interface CalendarSystem { + getMarkerYear(d: DateMarker): number; + getMarkerMonth(d: DateMarker): number; + getMarkerDay(d: DateMarker): number; + arrayToMarker(arr: number[]): DateMarker; + markerToArray(d: DateMarker): number[]; + } + export function registerCalendarSystem(name: any, theClass: any): void; + export function createCalendarSystem(name: any): any; +} + +declare module '@fullcalendar/core/datelib/formatting-cmd' { + import { DateFormatter, DateFormattingContext, ZonedMarker, VerboseFormattingArg } from '@fullcalendar/core/datelib/formatting'; + export type CmdFormatterFunc = (cmd: string, arg: VerboseFormattingArg) => string; + export class CmdFormatter implements DateFormatter { + cmdStr: string; + separator: string; + constructor(cmdStr: string, separator?: string); + format(date: ZonedMarker, context: DateFormattingContext): string; + formatRange(start: ZonedMarker, end: ZonedMarker, context: DateFormattingContext): string; + } +} + +declare module '@fullcalendar/core/datelib/formatting-func' { + import { DateFormatter, DateFormattingContext, ZonedMarker, VerboseFormattingArg } from '@fullcalendar/core/datelib/formatting'; + export type FuncFormatterFunc = (arg: VerboseFormattingArg) => string; + export class FuncFormatter implements DateFormatter { + func: FuncFormatterFunc; + constructor(func: FuncFormatterFunc); + format(date: ZonedMarker, context: DateFormattingContext): string; + formatRange(start: ZonedMarker, end: ZonedMarker, context: DateFormattingContext): string; + } +} + +declare module '@fullcalendar/core/event-sources/func-event-source' { + import { EventSourceError } from '@fullcalendar/core/structs/event-source'; + import { EventInput } from '@fullcalendar/core/structs/event'; + export type EventSourceFunc = (arg: { + start: Date; + end: Date; + timeZone: string; + }, successCallback: (events: EventInput[]) => void, failureCallback: (error: EventSourceError) => void) => (void | PromiseLike<EventInput[]>); + const _default: import("@fullcalendar/core/plugin-system").PluginDef; + export default _default; +} + +declare module '@fullcalendar/core/interactions/external-element-dragging' { + import { DateSpan } from '@fullcalendar/core/structs/date-span'; + import { DragMeta } from '@fullcalendar/core/structs/drag-meta'; + export type ExternalDefTransform = (dateSpan: DateSpan, dragMeta: DragMeta) => any; +} + +declare module '@fullcalendar/core/Toolbar' { + import Component, { ComponentContext } from '@fullcalendar/core/component/Component'; + export interface ToolbarRenderProps { + layout: any; + title: string; + activeButton: string; + isTodayEnabled: boolean; + isPrevEnabled: boolean; + isNextEnabled: boolean; + } + export { Toolbar as default, Toolbar }; + class Toolbar extends Component<ToolbarRenderProps> { + el: HTMLElement; + viewsWithButtons: any; + constructor(context: ComponentContext, extraClassName: any); + destroy(): void; + render(props: ToolbarRenderProps): void; + renderLayout(layout: any): void; + unrenderLayout(): void; + renderSection(position: any, buttonStr: any): HTMLElement; + updateToday(isTodayEnabled: any): void; + updatePrev(isPrevEnabled: any): void; + updateNext(isNextEnabled: any): void; + updateTitle(text: any): void; + updateActiveButton(buttonName?: any): void; + toggleButtonEnabled(buttonName: any, bool: any): void; + } +} + diff --git a/AKPlan/static/AKPlan/fullcalendar/core/main.esm.js b/AKPlan/static/AKPlan/fullcalendar/core/main.esm.js new file mode 100644 index 00000000..b3d27d75 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/main.esm.js @@ -0,0 +1,8558 @@ +/*! +FullCalendar Core Package v4.3.1 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +// Creating +// ---------------------------------------------------------------------------------------------------------------- +var elementPropHash = { + className: true, + colSpan: true, + rowSpan: true +}; +var containerTagHash = { + '<tr': 'tbody', + '<td': 'tr' +}; +function createElement(tagName, attrs, content) { + var el = document.createElement(tagName); + if (attrs) { + for (var attrName in attrs) { + if (attrName === 'style') { + applyStyle(el, attrs[attrName]); + } + else if (elementPropHash[attrName]) { + el[attrName] = attrs[attrName]; + } + else { + el.setAttribute(attrName, attrs[attrName]); + } + } + } + if (typeof content === 'string') { + el.innerHTML = content; // shortcut. no need to process HTML in any way + } + else if (content != null) { + appendToElement(el, content); + } + return el; +} +function htmlToElement(html) { + html = html.trim(); + var container = document.createElement(computeContainerTag(html)); + container.innerHTML = html; + return container.firstChild; +} +function htmlToElements(html) { + return Array.prototype.slice.call(htmlToNodeList(html)); +} +function htmlToNodeList(html) { + html = html.trim(); + var container = document.createElement(computeContainerTag(html)); + container.innerHTML = html; + return container.childNodes; +} +// assumes html already trimmed and tag names are lowercase +function computeContainerTag(html) { + return containerTagHash[html.substr(0, 3) // faster than using regex + ] || 'div'; +} +function appendToElement(el, content) { + var childNodes = normalizeContent(content); + for (var i = 0; i < childNodes.length; i++) { + el.appendChild(childNodes[i]); + } +} +function prependToElement(parent, content) { + var newEls = normalizeContent(content); + var afterEl = parent.firstChild || null; // if no firstChild, will append to end, but that's okay, b/c there were no children + for (var i = 0; i < newEls.length; i++) { + parent.insertBefore(newEls[i], afterEl); + } +} +function insertAfterElement(refEl, content) { + var newEls = normalizeContent(content); + var afterEl = refEl.nextSibling || null; + for (var i = 0; i < newEls.length; i++) { + refEl.parentNode.insertBefore(newEls[i], afterEl); + } +} +function normalizeContent(content) { + var els; + if (typeof content === 'string') { + els = htmlToElements(content); + } + else if (content instanceof Node) { + els = [content]; + } + else { // Node[] or NodeList + els = Array.prototype.slice.call(content); + } + return els; +} +function removeElement(el) { + if (el.parentNode) { + el.parentNode.removeChild(el); + } +} +// Querying +// ---------------------------------------------------------------------------------------------------------------- +// from https://developer.mozilla.org/en-US/docs/Web/API/Element/closest +var matchesMethod = Element.prototype.matches || + Element.prototype.matchesSelector || + Element.prototype.msMatchesSelector; +var closestMethod = Element.prototype.closest || function (selector) { + // polyfill + var el = this; + if (!document.documentElement.contains(el)) { + return null; + } + do { + if (elementMatches(el, selector)) { + return el; + } + el = el.parentElement || el.parentNode; + } while (el !== null && el.nodeType === 1); + return null; +}; +function elementClosest(el, selector) { + return closestMethod.call(el, selector); +} +function elementMatches(el, selector) { + return matchesMethod.call(el, selector); +} +// accepts multiple subject els +// returns a real array. good for methods like forEach +function findElements(container, selector) { + var containers = container instanceof HTMLElement ? [container] : container; + var allMatches = []; + for (var i = 0; i < containers.length; i++) { + var matches = containers[i].querySelectorAll(selector); + for (var j = 0; j < matches.length; j++) { + allMatches.push(matches[j]); + } + } + return allMatches; +} +// accepts multiple subject els +// only queries direct child elements +function findChildren(parent, selector) { + var parents = parent instanceof HTMLElement ? [parent] : parent; + var allMatches = []; + for (var i = 0; i < parents.length; i++) { + var childNodes = parents[i].children; // only ever elements + for (var j = 0; j < childNodes.length; j++) { + var childNode = childNodes[j]; + if (!selector || elementMatches(childNode, selector)) { + allMatches.push(childNode); + } + } + } + return allMatches; +} +// Attributes +// ---------------------------------------------------------------------------------------------------------------- +function forceClassName(el, className, bool) { + if (bool) { + el.classList.add(className); + } + else { + el.classList.remove(className); + } +} +// Style +// ---------------------------------------------------------------------------------------------------------------- +var PIXEL_PROP_RE = /(top|left|right|bottom|width|height)$/i; +function applyStyle(el, props) { + for (var propName in props) { + applyStyleProp(el, propName, props[propName]); + } +} +function applyStyleProp(el, name, val) { + if (val == null) { + el.style[name] = ''; + } + else if (typeof val === 'number' && PIXEL_PROP_RE.test(name)) { + el.style[name] = val + 'px'; + } + else { + el.style[name] = val; + } +} + +function pointInsideRect(point, rect) { + return point.left >= rect.left && + point.left < rect.right && + point.top >= rect.top && + point.top < rect.bottom; +} +// Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false +function intersectRects(rect1, rect2) { + var res = { + left: Math.max(rect1.left, rect2.left), + right: Math.min(rect1.right, rect2.right), + top: Math.max(rect1.top, rect2.top), + bottom: Math.min(rect1.bottom, rect2.bottom) + }; + if (res.left < res.right && res.top < res.bottom) { + return res; + } + return false; +} +function translateRect(rect, deltaX, deltaY) { + return { + left: rect.left + deltaX, + right: rect.right + deltaX, + top: rect.top + deltaY, + bottom: rect.bottom + deltaY + }; +} +// Returns a new point that will have been moved to reside within the given rectangle +function constrainPoint(point, rect) { + return { + left: Math.min(Math.max(point.left, rect.left), rect.right), + top: Math.min(Math.max(point.top, rect.top), rect.bottom) + }; +} +// Returns a point that is the center of the given rectangle +function getRectCenter(rect) { + return { + left: (rect.left + rect.right) / 2, + top: (rect.top + rect.bottom) / 2 + }; +} +// Subtracts point2's coordinates from point1's coordinates, returning a delta +function diffPoints(point1, point2) { + return { + left: point1.left - point2.left, + top: point1.top - point2.top + }; +} + +// Logic for determining if, when the element is right-to-left, the scrollbar appears on the left side +var isRtlScrollbarOnLeft = null; +function getIsRtlScrollbarOnLeft() { + if (isRtlScrollbarOnLeft === null) { + isRtlScrollbarOnLeft = computeIsRtlScrollbarOnLeft(); + } + return isRtlScrollbarOnLeft; +} +function computeIsRtlScrollbarOnLeft() { + var outerEl = createElement('div', { + style: { + position: 'absolute', + top: -1000, + left: 0, + border: 0, + padding: 0, + overflow: 'scroll', + direction: 'rtl' + } + }, '<div></div>'); + document.body.appendChild(outerEl); + var innerEl = outerEl.firstChild; + var res = innerEl.getBoundingClientRect().left > outerEl.getBoundingClientRect().left; + removeElement(outerEl); + return res; +} +// The scrollbar width computations in computeEdges are sometimes flawed when it comes to +// retina displays, rounding, and IE11. Massage them into a usable value. +function sanitizeScrollbarWidth(width) { + width = Math.max(0, width); // no negatives + width = Math.round(width); + return width; +} + +function computeEdges(el, getPadding) { + if (getPadding === void 0) { getPadding = false; } + var computedStyle = window.getComputedStyle(el); + var borderLeft = parseInt(computedStyle.borderLeftWidth, 10) || 0; + var borderRight = parseInt(computedStyle.borderRightWidth, 10) || 0; + var borderTop = parseInt(computedStyle.borderTopWidth, 10) || 0; + var borderBottom = parseInt(computedStyle.borderBottomWidth, 10) || 0; + // must use offset(Width|Height) because compatible with client(Width|Height) + var scrollbarLeftRight = sanitizeScrollbarWidth(el.offsetWidth - el.clientWidth - borderLeft - borderRight); + var scrollbarBottom = sanitizeScrollbarWidth(el.offsetHeight - el.clientHeight - borderTop - borderBottom); + var res = { + borderLeft: borderLeft, + borderRight: borderRight, + borderTop: borderTop, + borderBottom: borderBottom, + scrollbarBottom: scrollbarBottom, + scrollbarLeft: 0, + scrollbarRight: 0 + }; + if (getIsRtlScrollbarOnLeft() && computedStyle.direction === 'rtl') { // is the scrollbar on the left side? + res.scrollbarLeft = scrollbarLeftRight; + } + else { + res.scrollbarRight = scrollbarLeftRight; + } + if (getPadding) { + res.paddingLeft = parseInt(computedStyle.paddingLeft, 10) || 0; + res.paddingRight = parseInt(computedStyle.paddingRight, 10) || 0; + res.paddingTop = parseInt(computedStyle.paddingTop, 10) || 0; + res.paddingBottom = parseInt(computedStyle.paddingBottom, 10) || 0; + } + return res; +} +function computeInnerRect(el, goWithinPadding) { + if (goWithinPadding === void 0) { goWithinPadding = false; } + var outerRect = computeRect(el); + var edges = computeEdges(el, goWithinPadding); + var res = { + left: outerRect.left + edges.borderLeft + edges.scrollbarLeft, + right: outerRect.right - edges.borderRight - edges.scrollbarRight, + top: outerRect.top + edges.borderTop, + bottom: outerRect.bottom - edges.borderBottom - edges.scrollbarBottom + }; + if (goWithinPadding) { + res.left += edges.paddingLeft; + res.right -= edges.paddingRight; + res.top += edges.paddingTop; + res.bottom -= edges.paddingBottom; + } + return res; +} +function computeRect(el) { + var rect = el.getBoundingClientRect(); + return { + left: rect.left + window.pageXOffset, + top: rect.top + window.pageYOffset, + right: rect.right + window.pageXOffset, + bottom: rect.bottom + window.pageYOffset + }; +} +function computeViewportRect() { + return { + left: window.pageXOffset, + right: window.pageXOffset + document.documentElement.clientWidth, + top: window.pageYOffset, + bottom: window.pageYOffset + document.documentElement.clientHeight + }; +} +function computeHeightAndMargins(el) { + return el.getBoundingClientRect().height + computeVMargins(el); +} +function computeVMargins(el) { + var computed = window.getComputedStyle(el); + return parseInt(computed.marginTop, 10) + + parseInt(computed.marginBottom, 10); +} +// does not return window +function getClippingParents(el) { + var parents = []; + while (el instanceof HTMLElement) { // will stop when gets to document or null + var computedStyle = window.getComputedStyle(el); + if (computedStyle.position === 'fixed') { + break; + } + if ((/(auto|scroll)/).test(computedStyle.overflow + computedStyle.overflowY + computedStyle.overflowX)) { + parents.push(el); + } + el = el.parentNode; + } + return parents; +} +function computeClippingRect(el) { + return getClippingParents(el) + .map(function (el) { + return computeInnerRect(el); + }) + .concat(computeViewportRect()) + .reduce(function (rect0, rect1) { + return intersectRects(rect0, rect1) || rect1; // should always intersect + }); +} + +// Stops a mouse/touch event from doing it's native browser action +function preventDefault(ev) { + ev.preventDefault(); +} +// Event Delegation +// ---------------------------------------------------------------------------------------------------------------- +function listenBySelector(container, eventType, selector, handler) { + function realHandler(ev) { + var matchedChild = elementClosest(ev.target, selector); + if (matchedChild) { + handler.call(matchedChild, ev, matchedChild); + } + } + container.addEventListener(eventType, realHandler); + return function () { + container.removeEventListener(eventType, realHandler); + }; +} +function listenToHoverBySelector(container, selector, onMouseEnter, onMouseLeave) { + var currentMatchedChild; + return listenBySelector(container, 'mouseover', selector, function (ev, matchedChild) { + if (matchedChild !== currentMatchedChild) { + currentMatchedChild = matchedChild; + onMouseEnter(ev, matchedChild); + var realOnMouseLeave_1 = function (ev) { + currentMatchedChild = null; + onMouseLeave(ev, matchedChild); + matchedChild.removeEventListener('mouseleave', realOnMouseLeave_1); + }; + // listen to the next mouseleave, and then unattach + matchedChild.addEventListener('mouseleave', realOnMouseLeave_1); + } + }); +} +// Animation +// ---------------------------------------------------------------------------------------------------------------- +var transitionEventNames = [ + 'webkitTransitionEnd', + 'otransitionend', + 'oTransitionEnd', + 'msTransitionEnd', + 'transitionend' +]; +// triggered only when the next single subsequent transition finishes +function whenTransitionDone(el, callback) { + var realCallback = function (ev) { + callback(ev); + transitionEventNames.forEach(function (eventName) { + el.removeEventListener(eventName, realCallback); + }); + }; + transitionEventNames.forEach(function (eventName) { + el.addEventListener(eventName, realCallback); // cross-browser way to determine when the transition finishes + }); +} + +var DAY_IDS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']; +// Adding +function addWeeks(m, n) { + var a = dateToUtcArray(m); + a[2] += n * 7; + return arrayToUtcDate(a); +} +function addDays(m, n) { + var a = dateToUtcArray(m); + a[2] += n; + return arrayToUtcDate(a); +} +function addMs(m, n) { + var a = dateToUtcArray(m); + a[6] += n; + return arrayToUtcDate(a); +} +// Diffing (all return floats) +function diffWeeks(m0, m1) { + return diffDays(m0, m1) / 7; +} +function diffDays(m0, m1) { + return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60 * 24); +} +function diffHours(m0, m1) { + return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60); +} +function diffMinutes(m0, m1) { + return (m1.valueOf() - m0.valueOf()) / (1000 * 60); +} +function diffSeconds(m0, m1) { + return (m1.valueOf() - m0.valueOf()) / 1000; +} +function diffDayAndTime(m0, m1) { + var m0day = startOfDay(m0); + var m1day = startOfDay(m1); + return { + years: 0, + months: 0, + days: Math.round(diffDays(m0day, m1day)), + milliseconds: (m1.valueOf() - m1day.valueOf()) - (m0.valueOf() - m0day.valueOf()) + }; +} +// Diffing Whole Units +function diffWholeWeeks(m0, m1) { + var d = diffWholeDays(m0, m1); + if (d !== null && d % 7 === 0) { + return d / 7; + } + return null; +} +function diffWholeDays(m0, m1) { + if (timeAsMs(m0) === timeAsMs(m1)) { + return Math.round(diffDays(m0, m1)); + } + return null; +} +// Start-Of +function startOfDay(m) { + return arrayToUtcDate([ + m.getUTCFullYear(), + m.getUTCMonth(), + m.getUTCDate() + ]); +} +function startOfHour(m) { + return arrayToUtcDate([ + m.getUTCFullYear(), + m.getUTCMonth(), + m.getUTCDate(), + m.getUTCHours() + ]); +} +function startOfMinute(m) { + return arrayToUtcDate([ + m.getUTCFullYear(), + m.getUTCMonth(), + m.getUTCDate(), + m.getUTCHours(), + m.getUTCMinutes() + ]); +} +function startOfSecond(m) { + return arrayToUtcDate([ + m.getUTCFullYear(), + m.getUTCMonth(), + m.getUTCDate(), + m.getUTCHours(), + m.getUTCMinutes(), + m.getUTCSeconds() + ]); +} +// Week Computation +function weekOfYear(marker, dow, doy) { + var y = marker.getUTCFullYear(); + var w = weekOfGivenYear(marker, y, dow, doy); + if (w < 1) { + return weekOfGivenYear(marker, y - 1, dow, doy); + } + var nextW = weekOfGivenYear(marker, y + 1, dow, doy); + if (nextW >= 1) { + return Math.min(w, nextW); + } + return w; +} +function weekOfGivenYear(marker, year, dow, doy) { + var firstWeekStart = arrayToUtcDate([year, 0, 1 + firstWeekOffset(year, dow, doy)]); + var dayStart = startOfDay(marker); + var days = Math.round(diffDays(firstWeekStart, dayStart)); + return Math.floor(days / 7) + 1; // zero-indexed +} +// start-of-first-week - start-of-year +function firstWeekOffset(year, dow, doy) { + // first-week day -- which january is always in the first week (4 for iso, 1 for other) + var fwd = 7 + dow - doy; + // first-week day local weekday -- which local weekday is fwd + var fwdlw = (7 + arrayToUtcDate([year, 0, fwd]).getUTCDay() - dow) % 7; + return -fwdlw + fwd - 1; +} +// Array Conversion +function dateToLocalArray(date) { + return [ + date.getFullYear(), + date.getMonth(), + date.getDate(), + date.getHours(), + date.getMinutes(), + date.getSeconds(), + date.getMilliseconds() + ]; +} +function arrayToLocalDate(a) { + return new Date(a[0], a[1] || 0, a[2] == null ? 1 : a[2], // day of month + a[3] || 0, a[4] || 0, a[5] || 0); +} +function dateToUtcArray(date) { + return [ + date.getUTCFullYear(), + date.getUTCMonth(), + date.getUTCDate(), + date.getUTCHours(), + date.getUTCMinutes(), + date.getUTCSeconds(), + date.getUTCMilliseconds() + ]; +} +function arrayToUtcDate(a) { + // according to web standards (and Safari), a month index is required. + // massage if only given a year. + if (a.length === 1) { + a = a.concat([0]); + } + return new Date(Date.UTC.apply(Date, a)); +} +// Other Utils +function isValidDate(m) { + return !isNaN(m.valueOf()); +} +function timeAsMs(m) { + return m.getUTCHours() * 1000 * 60 * 60 + + m.getUTCMinutes() * 1000 * 60 + + m.getUTCSeconds() * 1000 + + m.getUTCMilliseconds(); +} + +var INTERNAL_UNITS = ['years', 'months', 'days', 'milliseconds']; +var PARSE_RE = /^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/; +// Parsing and Creation +function createDuration(input, unit) { + var _a; + if (typeof input === 'string') { + return parseString(input); + } + else if (typeof input === 'object' && input) { // non-null object + return normalizeObject(input); + } + else if (typeof input === 'number') { + return normalizeObject((_a = {}, _a[unit || 'milliseconds'] = input, _a)); + } + else { + return null; + } +} +function parseString(s) { + var m = PARSE_RE.exec(s); + if (m) { + var sign = m[1] ? -1 : 1; + return { + years: 0, + months: 0, + days: sign * (m[2] ? parseInt(m[2], 10) : 0), + milliseconds: sign * ((m[3] ? parseInt(m[3], 10) : 0) * 60 * 60 * 1000 + // hours + (m[4] ? parseInt(m[4], 10) : 0) * 60 * 1000 + // minutes + (m[5] ? parseInt(m[5], 10) : 0) * 1000 + // seconds + (m[6] ? parseInt(m[6], 10) : 0) // ms + ) + }; + } + return null; +} +function normalizeObject(obj) { + return { + years: obj.years || obj.year || 0, + months: obj.months || obj.month || 0, + days: (obj.days || obj.day || 0) + + getWeeksFromInput(obj) * 7, + milliseconds: (obj.hours || obj.hour || 0) * 60 * 60 * 1000 + // hours + (obj.minutes || obj.minute || 0) * 60 * 1000 + // minutes + (obj.seconds || obj.second || 0) * 1000 + // seconds + (obj.milliseconds || obj.millisecond || obj.ms || 0) // ms + }; +} +function getWeeksFromInput(obj) { + return obj.weeks || obj.week || 0; +} +// Equality +function durationsEqual(d0, d1) { + return d0.years === d1.years && + d0.months === d1.months && + d0.days === d1.days && + d0.milliseconds === d1.milliseconds; +} +function isSingleDay(dur) { + return dur.years === 0 && dur.months === 0 && dur.days === 1 && dur.milliseconds === 0; +} +// Simple Math +function addDurations(d0, d1) { + return { + years: d0.years + d1.years, + months: d0.months + d1.months, + days: d0.days + d1.days, + milliseconds: d0.milliseconds + d1.milliseconds + }; +} +function subtractDurations(d1, d0) { + return { + years: d1.years - d0.years, + months: d1.months - d0.months, + days: d1.days - d0.days, + milliseconds: d1.milliseconds - d0.milliseconds + }; +} +function multiplyDuration(d, n) { + return { + years: d.years * n, + months: d.months * n, + days: d.days * n, + milliseconds: d.milliseconds * n + }; +} +// Conversions +// "Rough" because they are based on average-case Gregorian months/years +function asRoughYears(dur) { + return asRoughDays(dur) / 365; +} +function asRoughMonths(dur) { + return asRoughDays(dur) / 30; +} +function asRoughDays(dur) { + return asRoughMs(dur) / 864e5; +} +function asRoughMinutes(dur) { + return asRoughMs(dur) / (1000 * 60); +} +function asRoughSeconds(dur) { + return asRoughMs(dur) / 1000; +} +function asRoughMs(dur) { + return dur.years * (365 * 864e5) + + dur.months * (30 * 864e5) + + dur.days * 864e5 + + dur.milliseconds; +} +// Advanced Math +function wholeDivideDurations(numerator, denominator) { + var res = null; + for (var i = 0; i < INTERNAL_UNITS.length; i++) { + var unit = INTERNAL_UNITS[i]; + if (denominator[unit]) { + var localRes = numerator[unit] / denominator[unit]; + if (!isInt(localRes) || (res !== null && res !== localRes)) { + return null; + } + res = localRes; + } + else if (numerator[unit]) { + // needs to divide by something but can't! + return null; + } + } + return res; +} +function greatestDurationDenominator(dur, dontReturnWeeks) { + var ms = dur.milliseconds; + if (ms) { + if (ms % 1000 !== 0) { + return { unit: 'millisecond', value: ms }; + } + if (ms % (1000 * 60) !== 0) { + return { unit: 'second', value: ms / 1000 }; + } + if (ms % (1000 * 60 * 60) !== 0) { + return { unit: 'minute', value: ms / (1000 * 60) }; + } + if (ms) { + return { unit: 'hour', value: ms / (1000 * 60 * 60) }; + } + } + if (dur.days) { + if (!dontReturnWeeks && dur.days % 7 === 0) { + return { unit: 'week', value: dur.days / 7 }; + } + return { unit: 'day', value: dur.days }; + } + if (dur.months) { + return { unit: 'month', value: dur.months }; + } + if (dur.years) { + return { unit: 'year', value: dur.years }; + } + return { unit: 'millisecond', value: 0 }; +} + +/* FullCalendar-specific DOM Utilities +----------------------------------------------------------------------------------------------------------------------*/ +// Given the scrollbar widths of some other container, create borders/margins on rowEls in order to match the left +// and right space that was offset by the scrollbars. A 1-pixel border first, then margin beyond that. +function compensateScroll(rowEl, scrollbarWidths) { + if (scrollbarWidths.left) { + applyStyle(rowEl, { + borderLeftWidth: 1, + marginLeft: scrollbarWidths.left - 1 + }); + } + if (scrollbarWidths.right) { + applyStyle(rowEl, { + borderRightWidth: 1, + marginRight: scrollbarWidths.right - 1 + }); + } +} +// Undoes compensateScroll and restores all borders/margins +function uncompensateScroll(rowEl) { + applyStyle(rowEl, { + marginLeft: '', + marginRight: '', + borderLeftWidth: '', + borderRightWidth: '' + }); +} +// Make the mouse cursor express that an event is not allowed in the current area +function disableCursor() { + document.body.classList.add('fc-not-allowed'); +} +// Returns the mouse cursor to its original look +function enableCursor() { + document.body.classList.remove('fc-not-allowed'); +} +// Given a total available height to fill, have `els` (essentially child rows) expand to accomodate. +// By default, all elements that are shorter than the recommended height are expanded uniformly, not considering +// any other els that are already too tall. if `shouldRedistribute` is on, it considers these tall rows and +// reduces the available height. +function distributeHeight(els, availableHeight, shouldRedistribute) { + // *FLOORING NOTE*: we floor in certain places because zoom can give inaccurate floating-point dimensions, + // and it is better to be shorter than taller, to avoid creating unnecessary scrollbars. + var minOffset1 = Math.floor(availableHeight / els.length); // for non-last element + var minOffset2 = Math.floor(availableHeight - minOffset1 * (els.length - 1)); // for last element *FLOORING NOTE* + var flexEls = []; // elements that are allowed to expand. array of DOM nodes + var flexOffsets = []; // amount of vertical space it takes up + var flexHeights = []; // actual css height + var usedHeight = 0; + undistributeHeight(els); // give all elements their natural height + // find elements that are below the recommended height (expandable). + // important to query for heights in a single first pass (to avoid reflow oscillation). + els.forEach(function (el, i) { + var minOffset = i === els.length - 1 ? minOffset2 : minOffset1; + var naturalHeight = el.getBoundingClientRect().height; + var naturalOffset = naturalHeight + computeVMargins(el); + if (naturalOffset < minOffset) { + flexEls.push(el); + flexOffsets.push(naturalOffset); + flexHeights.push(naturalHeight); + } + else { + // this element stretches past recommended height (non-expandable). mark the space as occupied. + usedHeight += naturalOffset; + } + }); + // readjust the recommended height to only consider the height available to non-maxed-out rows. + if (shouldRedistribute) { + availableHeight -= usedHeight; + minOffset1 = Math.floor(availableHeight / flexEls.length); + minOffset2 = Math.floor(availableHeight - minOffset1 * (flexEls.length - 1)); // *FLOORING NOTE* + } + // assign heights to all expandable elements + flexEls.forEach(function (el, i) { + var minOffset = i === flexEls.length - 1 ? minOffset2 : minOffset1; + var naturalOffset = flexOffsets[i]; + var naturalHeight = flexHeights[i]; + var newHeight = minOffset - (naturalOffset - naturalHeight); // subtract the margin/padding + if (naturalOffset < minOffset) { // we check this again because redistribution might have changed things + el.style.height = newHeight + 'px'; + } + }); +} +// Undoes distrubuteHeight, restoring all els to their natural height +function undistributeHeight(els) { + els.forEach(function (el) { + el.style.height = ''; + }); +} +// Given `els`, a set of <td> cells, find the cell with the largest natural width and set the widths of all the +// cells to be that width. +// PREREQUISITE: if you want a cell to take up width, it needs to have a single inner element w/ display:inline +function matchCellWidths(els) { + var maxInnerWidth = 0; + els.forEach(function (el) { + var innerEl = el.firstChild; // hopefully an element + if (innerEl instanceof HTMLElement) { + var innerWidth_1 = innerEl.getBoundingClientRect().width; + if (innerWidth_1 > maxInnerWidth) { + maxInnerWidth = innerWidth_1; + } + } + }); + maxInnerWidth++; // sometimes not accurate of width the text needs to stay on one line. insurance + els.forEach(function (el) { + el.style.width = maxInnerWidth + 'px'; + }); + return maxInnerWidth; +} +// Given one element that resides inside another, +// Subtracts the height of the inner element from the outer element. +function subtractInnerElHeight(outerEl, innerEl) { + // effin' IE8/9/10/11 sometimes returns 0 for dimensions. this weird hack was the only thing that worked + var reflowStyleProps = { + position: 'relative', + left: -1 // ensure reflow in case the el was already relative. negative is less likely to cause new scroll + }; + applyStyle(outerEl, reflowStyleProps); + applyStyle(innerEl, reflowStyleProps); + var diff = // grab the dimensions + outerEl.getBoundingClientRect().height - + innerEl.getBoundingClientRect().height; + // undo hack + var resetStyleProps = { position: '', left: '' }; + applyStyle(outerEl, resetStyleProps); + applyStyle(innerEl, resetStyleProps); + return diff; +} +/* Selection +----------------------------------------------------------------------------------------------------------------------*/ +function preventSelection(el) { + el.classList.add('fc-unselectable'); + el.addEventListener('selectstart', preventDefault); +} +function allowSelection(el) { + el.classList.remove('fc-unselectable'); + el.removeEventListener('selectstart', preventDefault); +} +/* Context Menu +----------------------------------------------------------------------------------------------------------------------*/ +function preventContextMenu(el) { + el.addEventListener('contextmenu', preventDefault); +} +function allowContextMenu(el) { + el.removeEventListener('contextmenu', preventDefault); +} +/* Object Ordering by Field +----------------------------------------------------------------------------------------------------------------------*/ +function parseFieldSpecs(input) { + var specs = []; + var tokens = []; + var i; + var token; + if (typeof input === 'string') { + tokens = input.split(/\s*,\s*/); + } + else if (typeof input === 'function') { + tokens = [input]; + } + else if (Array.isArray(input)) { + tokens = input; + } + for (i = 0; i < tokens.length; i++) { + token = tokens[i]; + if (typeof token === 'string') { + specs.push(token.charAt(0) === '-' ? + { field: token.substring(1), order: -1 } : + { field: token, order: 1 }); + } + else if (typeof token === 'function') { + specs.push({ func: token }); + } + } + return specs; +} +function compareByFieldSpecs(obj0, obj1, fieldSpecs) { + var i; + var cmp; + for (i = 0; i < fieldSpecs.length; i++) { + cmp = compareByFieldSpec(obj0, obj1, fieldSpecs[i]); + if (cmp) { + return cmp; + } + } + return 0; +} +function compareByFieldSpec(obj0, obj1, fieldSpec) { + if (fieldSpec.func) { + return fieldSpec.func(obj0, obj1); + } + return flexibleCompare(obj0[fieldSpec.field], obj1[fieldSpec.field]) + * (fieldSpec.order || 1); +} +function flexibleCompare(a, b) { + if (!a && !b) { + return 0; + } + if (b == null) { + return -1; + } + if (a == null) { + return 1; + } + if (typeof a === 'string' || typeof b === 'string') { + return String(a).localeCompare(String(b)); + } + return a - b; +} +/* String Utilities +----------------------------------------------------------------------------------------------------------------------*/ +function capitaliseFirstLetter(str) { + return str.charAt(0).toUpperCase() + str.slice(1); +} +function padStart(val, len) { + var s = String(val); + return '000'.substr(0, len - s.length) + s; +} +/* Number Utilities +----------------------------------------------------------------------------------------------------------------------*/ +function compareNumbers(a, b) { + return a - b; +} +function isInt(n) { + return n % 1 === 0; +} +/* Weird Utilities +----------------------------------------------------------------------------------------------------------------------*/ +function applyAll(functions, thisObj, args) { + if (typeof functions === 'function') { // supplied a single function + functions = [functions]; + } + if (functions) { + var i = void 0; + var ret = void 0; + for (i = 0; i < functions.length; i++) { + ret = functions[i].apply(thisObj, args) || ret; + } + return ret; + } +} +function firstDefined() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + for (var i = 0; i < args.length; i++) { + if (args[i] !== undefined) { + return args[i]; + } + } +} +// Returns a function, that, as long as it continues to be invoked, will not +// be triggered. The function will be called after it stops being called for +// N milliseconds. If `immediate` is passed, trigger the function on the +// leading edge, instead of the trailing. +// https://github.com/jashkenas/underscore/blob/1.6.0/underscore.js#L714 +function debounce(func, wait) { + var timeout; + var args; + var context; + var timestamp; + var result; + var later = function () { + var last = new Date().valueOf() - timestamp; + if (last < wait) { + timeout = setTimeout(later, wait - last); + } + else { + timeout = null; + result = func.apply(context, args); + context = args = null; + } + }; + return function () { + context = this; + args = arguments; + timestamp = new Date().valueOf(); + if (!timeout) { + timeout = setTimeout(later, wait); + } + return result; + }; +} +// Number and Boolean are only types that defaults or not computed for +// TODO: write more comments +function refineProps(rawProps, processors, defaults, leftoverProps) { + if (defaults === void 0) { defaults = {}; } + var refined = {}; + for (var key in processors) { + var processor = processors[key]; + if (rawProps[key] !== undefined) { + // found + if (processor === Function) { + refined[key] = typeof rawProps[key] === 'function' ? rawProps[key] : null; + } + else if (processor) { // a refining function? + refined[key] = processor(rawProps[key]); + } + else { + refined[key] = rawProps[key]; + } + } + else if (defaults[key] !== undefined) { + // there's an explicit default + refined[key] = defaults[key]; + } + else { + // must compute a default + if (processor === String) { + refined[key] = ''; // empty string is default for String + } + else if (!processor || processor === Number || processor === Boolean || processor === Function) { + refined[key] = null; // assign null for other non-custom processor funcs + } + else { + refined[key] = processor(null); // run the custom processor func + } + } + } + if (leftoverProps) { + for (var key in rawProps) { + if (processors[key] === undefined) { + leftoverProps[key] = rawProps[key]; + } + } + } + return refined; +} +/* Date stuff that doesn't belong in datelib core +----------------------------------------------------------------------------------------------------------------------*/ +// given a timed range, computes an all-day range that has the same exact duration, +// but whose start time is aligned with the start of the day. +function computeAlignedDayRange(timedRange) { + var dayCnt = Math.floor(diffDays(timedRange.start, timedRange.end)) || 1; + var start = startOfDay(timedRange.start); + var end = addDays(start, dayCnt); + return { start: start, end: end }; +} +// given a timed range, computes an all-day range based on how for the end date bleeds into the next day +// TODO: give nextDayThreshold a default arg +function computeVisibleDayRange(timedRange, nextDayThreshold) { + if (nextDayThreshold === void 0) { nextDayThreshold = createDuration(0); } + var startDay = null; + var endDay = null; + if (timedRange.end) { + endDay = startOfDay(timedRange.end); + var endTimeMS = timedRange.end.valueOf() - endDay.valueOf(); // # of milliseconds into `endDay` + // If the end time is actually inclusively part of the next day and is equal to or + // beyond the next day threshold, adjust the end to be the exclusive end of `endDay`. + // Otherwise, leaving it as inclusive will cause it to exclude `endDay`. + if (endTimeMS && endTimeMS >= asRoughMs(nextDayThreshold)) { + endDay = addDays(endDay, 1); + } + } + if (timedRange.start) { + startDay = startOfDay(timedRange.start); // the beginning of the day the range starts + // If end is within `startDay` but not past nextDayThreshold, assign the default duration of one day. + if (endDay && endDay <= startDay) { + endDay = addDays(startDay, 1); + } + } + return { start: startDay, end: endDay }; +} +// spans from one day into another? +function isMultiDayRange(range) { + var visibleRange = computeVisibleDayRange(range); + return diffDays(visibleRange.start, visibleRange.end) > 1; +} +function diffDates(date0, date1, dateEnv, largeUnit) { + if (largeUnit === 'year') { + return createDuration(dateEnv.diffWholeYears(date0, date1), 'year'); + } + else if (largeUnit === 'month') { + return createDuration(dateEnv.diffWholeMonths(date0, date1), 'month'); + } + else { + return diffDayAndTime(date0, date1); // returns a duration + } +} + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} + +var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; + +function parseRecurring(eventInput, allDayDefault, dateEnv, recurringTypes, leftovers) { + for (var i = 0; i < recurringTypes.length; i++) { + var localLeftovers = {}; + var parsed = recurringTypes[i].parse(eventInput, localLeftovers, dateEnv); + if (parsed) { + var allDay = localLeftovers.allDay; + delete localLeftovers.allDay; // remove from leftovers + if (allDay == null) { + allDay = allDayDefault; + if (allDay == null) { + allDay = parsed.allDayGuess; + if (allDay == null) { + allDay = false; + } + } + } + __assign(leftovers, localLeftovers); + return { + allDay: allDay, + duration: parsed.duration, + typeData: parsed.typeData, + typeId: i + }; + } + } + return null; +} +/* +Event MUST have a recurringDef +*/ +function expandRecurringRanges(eventDef, duration, framingRange, dateEnv, recurringTypes) { + var typeDef = recurringTypes[eventDef.recurringDef.typeId]; + var markers = typeDef.expand(eventDef.recurringDef.typeData, { + start: dateEnv.subtract(framingRange.start, duration), + end: framingRange.end + }, dateEnv); + // the recurrence plugins don't guarantee that all-day events are start-of-day, so we have to + if (eventDef.allDay) { + markers = markers.map(startOfDay); + } + return markers; +} + +var hasOwnProperty = Object.prototype.hasOwnProperty; +// Merges an array of objects into a single object. +// The second argument allows for an array of property names who's object values will be merged together. +function mergeProps(propObjs, complexProps) { + var dest = {}; + var i; + var name; + var complexObjs; + var j; + var val; + var props; + if (complexProps) { + for (i = 0; i < complexProps.length; i++) { + name = complexProps[i]; + complexObjs = []; + // collect the trailing object values, stopping when a non-object is discovered + for (j = propObjs.length - 1; j >= 0; j--) { + val = propObjs[j][name]; + if (typeof val === 'object' && val) { // non-null object + complexObjs.unshift(val); + } + else if (val !== undefined) { + dest[name] = val; // if there were no objects, this value will be used + break; + } + } + // if the trailing values were objects, use the merged value + if (complexObjs.length) { + dest[name] = mergeProps(complexObjs); + } + } + } + // copy values into the destination, going from last to first + for (i = propObjs.length - 1; i >= 0; i--) { + props = propObjs[i]; + for (name in props) { + if (!(name in dest)) { // if already assigned by previous props or complex props, don't reassign + dest[name] = props[name]; + } + } + } + return dest; +} +function filterHash(hash, func) { + var filtered = {}; + for (var key in hash) { + if (func(hash[key], key)) { + filtered[key] = hash[key]; + } + } + return filtered; +} +function mapHash(hash, func) { + var newHash = {}; + for (var key in hash) { + newHash[key] = func(hash[key], key); + } + return newHash; +} +function arrayToHash(a) { + var hash = {}; + for (var _i = 0, a_1 = a; _i < a_1.length; _i++) { + var item = a_1[_i]; + hash[item] = true; + } + return hash; +} +function hashValuesToArray(obj) { + var a = []; + for (var key in obj) { + a.push(obj[key]); + } + return a; +} +function isPropsEqual(obj0, obj1) { + for (var key in obj0) { + if (hasOwnProperty.call(obj0, key)) { + if (!(key in obj1)) { + return false; + } + } + } + for (var key in obj1) { + if (hasOwnProperty.call(obj1, key)) { + if (obj0[key] !== obj1[key]) { + return false; + } + } + } + return true; +} + +function parseEvents(rawEvents, sourceId, calendar, allowOpenRange) { + var eventStore = createEmptyEventStore(); + for (var _i = 0, rawEvents_1 = rawEvents; _i < rawEvents_1.length; _i++) { + var rawEvent = rawEvents_1[_i]; + var tuple = parseEvent(rawEvent, sourceId, calendar, allowOpenRange); + if (tuple) { + eventTupleToStore(tuple, eventStore); + } + } + return eventStore; +} +function eventTupleToStore(tuple, eventStore) { + if (eventStore === void 0) { eventStore = createEmptyEventStore(); } + eventStore.defs[tuple.def.defId] = tuple.def; + if (tuple.instance) { + eventStore.instances[tuple.instance.instanceId] = tuple.instance; + } + return eventStore; +} +function expandRecurring(eventStore, framingRange, calendar) { + var dateEnv = calendar.dateEnv; + var defs = eventStore.defs, instances = eventStore.instances; + // remove existing recurring instances + instances = filterHash(instances, function (instance) { + return !defs[instance.defId].recurringDef; + }); + for (var defId in defs) { + var def = defs[defId]; + if (def.recurringDef) { + var duration = def.recurringDef.duration; + if (!duration) { + duration = def.allDay ? + calendar.defaultAllDayEventDuration : + calendar.defaultTimedEventDuration; + } + var starts = expandRecurringRanges(def, duration, framingRange, calendar.dateEnv, calendar.pluginSystem.hooks.recurringTypes); + for (var _i = 0, starts_1 = starts; _i < starts_1.length; _i++) { + var start = starts_1[_i]; + var instance = createEventInstance(defId, { + start: start, + end: dateEnv.add(start, duration) + }); + instances[instance.instanceId] = instance; + } + } + } + return { defs: defs, instances: instances }; +} +// retrieves events that have the same groupId as the instance specified by `instanceId` +// or they are the same as the instance. +// why might instanceId not be in the store? an event from another calendar? +function getRelevantEvents(eventStore, instanceId) { + var instance = eventStore.instances[instanceId]; + if (instance) { + var def_1 = eventStore.defs[instance.defId]; + // get events/instances with same group + var newStore = filterEventStoreDefs(eventStore, function (lookDef) { + return isEventDefsGrouped(def_1, lookDef); + }); + // add the original + // TODO: wish we could use eventTupleToStore or something like it + newStore.defs[def_1.defId] = def_1; + newStore.instances[instance.instanceId] = instance; + return newStore; + } + return createEmptyEventStore(); +} +function isEventDefsGrouped(def0, def1) { + return Boolean(def0.groupId && def0.groupId === def1.groupId); +} +function transformRawEvents(rawEvents, eventSource, calendar) { + var calEachTransform = calendar.opt('eventDataTransform'); + var sourceEachTransform = eventSource ? eventSource.eventDataTransform : null; + if (sourceEachTransform) { + rawEvents = transformEachRawEvent(rawEvents, sourceEachTransform); + } + if (calEachTransform) { + rawEvents = transformEachRawEvent(rawEvents, calEachTransform); + } + return rawEvents; +} +function transformEachRawEvent(rawEvents, func) { + var refinedEvents; + if (!func) { + refinedEvents = rawEvents; + } + else { + refinedEvents = []; + for (var _i = 0, rawEvents_2 = rawEvents; _i < rawEvents_2.length; _i++) { + var rawEvent = rawEvents_2[_i]; + var refinedEvent = func(rawEvent); + if (refinedEvent) { + refinedEvents.push(refinedEvent); + } + else if (refinedEvent == null) { + refinedEvents.push(rawEvent); + } // if a different falsy value, do nothing + } + } + return refinedEvents; +} +function createEmptyEventStore() { + return { defs: {}, instances: {} }; +} +function mergeEventStores(store0, store1) { + return { + defs: __assign({}, store0.defs, store1.defs), + instances: __assign({}, store0.instances, store1.instances) + }; +} +function filterEventStoreDefs(eventStore, filterFunc) { + var defs = filterHash(eventStore.defs, filterFunc); + var instances = filterHash(eventStore.instances, function (instance) { + return defs[instance.defId]; // still exists? + }); + return { defs: defs, instances: instances }; +} + +function parseRange(input, dateEnv) { + var start = null; + var end = null; + if (input.start) { + start = dateEnv.createMarker(input.start); + } + if (input.end) { + end = dateEnv.createMarker(input.end); + } + if (!start && !end) { + return null; + } + if (start && end && end < start) { + return null; + } + return { start: start, end: end }; +} +// SIDE-EFFECT: will mutate ranges. +// Will return a new array result. +function invertRanges(ranges, constraintRange) { + var invertedRanges = []; + var start = constraintRange.start; // the end of the previous range. the start of the new range + var i; + var dateRange; + // ranges need to be in order. required for our date-walking algorithm + ranges.sort(compareRanges); + for (i = 0; i < ranges.length; i++) { + dateRange = ranges[i]; + // add the span of time before the event (if there is any) + if (dateRange.start > start) { // compare millisecond time (skip any ambig logic) + invertedRanges.push({ start: start, end: dateRange.start }); + } + if (dateRange.end > start) { + start = dateRange.end; + } + } + // add the span of time after the last event (if there is any) + if (start < constraintRange.end) { // compare millisecond time (skip any ambig logic) + invertedRanges.push({ start: start, end: constraintRange.end }); + } + return invertedRanges; +} +function compareRanges(range0, range1) { + return range0.start.valueOf() - range1.start.valueOf(); // earlier ranges go first +} +function intersectRanges(range0, range1) { + var start = range0.start; + var end = range0.end; + var newRange = null; + if (range1.start !== null) { + if (start === null) { + start = range1.start; + } + else { + start = new Date(Math.max(start.valueOf(), range1.start.valueOf())); + } + } + if (range1.end != null) { + if (end === null) { + end = range1.end; + } + else { + end = new Date(Math.min(end.valueOf(), range1.end.valueOf())); + } + } + if (start === null || end === null || start < end) { + newRange = { start: start, end: end }; + } + return newRange; +} +function rangesEqual(range0, range1) { + return (range0.start === null ? null : range0.start.valueOf()) === (range1.start === null ? null : range1.start.valueOf()) && + (range0.end === null ? null : range0.end.valueOf()) === (range1.end === null ? null : range1.end.valueOf()); +} +function rangesIntersect(range0, range1) { + return (range0.end === null || range1.start === null || range0.end > range1.start) && + (range0.start === null || range1.end === null || range0.start < range1.end); +} +function rangeContainsRange(outerRange, innerRange) { + return (outerRange.start === null || (innerRange.start !== null && innerRange.start >= outerRange.start)) && + (outerRange.end === null || (innerRange.end !== null && innerRange.end <= outerRange.end)); +} +function rangeContainsMarker(range, date) { + return (range.start === null || date >= range.start) && + (range.end === null || date < range.end); +} +// If the given date is not within the given range, move it inside. +// (If it's past the end, make it one millisecond before the end). +function constrainMarkerToRange(date, range) { + if (range.start != null && date < range.start) { + return range.start; + } + if (range.end != null && date >= range.end) { + return new Date(range.end.valueOf() - 1); + } + return date; +} + +function removeExact(array, exactVal) { + var removeCnt = 0; + var i = 0; + while (i < array.length) { + if (array[i] === exactVal) { + array.splice(i, 1); + removeCnt++; + } + else { + i++; + } + } + return removeCnt; +} +function isArraysEqual(a0, a1) { + var len = a0.length; + var i; + if (len !== a1.length) { // not array? or not same length? + return false; + } + for (i = 0; i < len; i++) { + if (a0[i] !== a1[i]) { + return false; + } + } + return true; +} + +function memoize(workerFunc) { + var args; + var res; + return function () { + if (!args || !isArraysEqual(args, arguments)) { + args = arguments; + res = workerFunc.apply(this, arguments); + } + return res; + }; +} +/* +always executes the workerFunc, but if the result is equal to the previous result, +return the previous result instead. +*/ +function memoizeOutput(workerFunc, equalityFunc) { + var cachedRes = null; + return function () { + var newRes = workerFunc.apply(this, arguments); + if (cachedRes === null || !(cachedRes === newRes || equalityFunc(cachedRes, newRes))) { + cachedRes = newRes; + } + return cachedRes; + }; +} + +var EXTENDED_SETTINGS_AND_SEVERITIES = { + week: 3, + separator: 0, + omitZeroMinute: 0, + meridiem: 0, + omitCommas: 0 +}; +var STANDARD_DATE_PROP_SEVERITIES = { + timeZoneName: 7, + era: 6, + year: 5, + month: 4, + day: 2, + weekday: 2, + hour: 1, + minute: 1, + second: 1 +}; +var MERIDIEM_RE = /\s*([ap])\.?m\.?/i; // eats up leading spaces too +var COMMA_RE = /,/g; // we need re for globalness +var MULTI_SPACE_RE = /\s+/g; +var LTR_RE = /\u200e/g; // control character +var UTC_RE = /UTC|GMT/; +var NativeFormatter = /** @class */ (function () { + function NativeFormatter(formatSettings) { + var standardDateProps = {}; + var extendedSettings = {}; + var severity = 0; + for (var name_1 in formatSettings) { + if (name_1 in EXTENDED_SETTINGS_AND_SEVERITIES) { + extendedSettings[name_1] = formatSettings[name_1]; + severity = Math.max(EXTENDED_SETTINGS_AND_SEVERITIES[name_1], severity); + } + else { + standardDateProps[name_1] = formatSettings[name_1]; + if (name_1 in STANDARD_DATE_PROP_SEVERITIES) { + severity = Math.max(STANDARD_DATE_PROP_SEVERITIES[name_1], severity); + } + } + } + this.standardDateProps = standardDateProps; + this.extendedSettings = extendedSettings; + this.severity = severity; + this.buildFormattingFunc = memoize(buildFormattingFunc); + } + NativeFormatter.prototype.format = function (date, context) { + return this.buildFormattingFunc(this.standardDateProps, this.extendedSettings, context)(date); + }; + NativeFormatter.prototype.formatRange = function (start, end, context) { + var _a = this, standardDateProps = _a.standardDateProps, extendedSettings = _a.extendedSettings; + var diffSeverity = computeMarkerDiffSeverity(start.marker, end.marker, context.calendarSystem); + if (!diffSeverity) { + return this.format(start, context); + } + var biggestUnitForPartial = diffSeverity; + if (biggestUnitForPartial > 1 && // the two dates are different in a way that's larger scale than time + (standardDateProps.year === 'numeric' || standardDateProps.year === '2-digit') && + (standardDateProps.month === 'numeric' || standardDateProps.month === '2-digit') && + (standardDateProps.day === 'numeric' || standardDateProps.day === '2-digit')) { + biggestUnitForPartial = 1; // make it look like the dates are only different in terms of time + } + var full0 = this.format(start, context); + var full1 = this.format(end, context); + if (full0 === full1) { + return full0; + } + var partialDateProps = computePartialFormattingOptions(standardDateProps, biggestUnitForPartial); + var partialFormattingFunc = buildFormattingFunc(partialDateProps, extendedSettings, context); + var partial0 = partialFormattingFunc(start); + var partial1 = partialFormattingFunc(end); + var insertion = findCommonInsertion(full0, partial0, full1, partial1); + var separator = extendedSettings.separator || ''; + if (insertion) { + return insertion.before + partial0 + separator + partial1 + insertion.after; + } + return full0 + separator + full1; + }; + NativeFormatter.prototype.getLargestUnit = function () { + switch (this.severity) { + case 7: + case 6: + case 5: + return 'year'; + case 4: + return 'month'; + case 3: + return 'week'; + default: + return 'day'; + } + }; + return NativeFormatter; +}()); +function buildFormattingFunc(standardDateProps, extendedSettings, context) { + var standardDatePropCnt = Object.keys(standardDateProps).length; + if (standardDatePropCnt === 1 && standardDateProps.timeZoneName === 'short') { + return function (date) { + return formatTimeZoneOffset(date.timeZoneOffset); + }; + } + if (standardDatePropCnt === 0 && extendedSettings.week) { + return function (date) { + return formatWeekNumber(context.computeWeekNumber(date.marker), context.weekLabel, context.locale, extendedSettings.week); + }; + } + return buildNativeFormattingFunc(standardDateProps, extendedSettings, context); +} +function buildNativeFormattingFunc(standardDateProps, extendedSettings, context) { + standardDateProps = __assign({}, standardDateProps); // copy + extendedSettings = __assign({}, extendedSettings); // copy + sanitizeSettings(standardDateProps, extendedSettings); + standardDateProps.timeZone = 'UTC'; // we leverage the only guaranteed timeZone for our UTC markers + var normalFormat = new Intl.DateTimeFormat(context.locale.codes, standardDateProps); + var zeroFormat; // needed? + if (extendedSettings.omitZeroMinute) { + var zeroProps = __assign({}, standardDateProps); + delete zeroProps.minute; // seconds and ms were already considered in sanitizeSettings + zeroFormat = new Intl.DateTimeFormat(context.locale.codes, zeroProps); + } + return function (date) { + var marker = date.marker; + var format; + if (zeroFormat && !marker.getUTCMinutes()) { + format = zeroFormat; + } + else { + format = normalFormat; + } + var s = format.format(marker); + return postProcess(s, date, standardDateProps, extendedSettings, context); + }; +} +function sanitizeSettings(standardDateProps, extendedSettings) { + // deal with a browser inconsistency where formatting the timezone + // requires that the hour/minute be present. + if (standardDateProps.timeZoneName) { + if (!standardDateProps.hour) { + standardDateProps.hour = '2-digit'; + } + if (!standardDateProps.minute) { + standardDateProps.minute = '2-digit'; + } + } + // only support short timezone names + if (standardDateProps.timeZoneName === 'long') { + standardDateProps.timeZoneName = 'short'; + } + // if requesting to display seconds, MUST display minutes + if (extendedSettings.omitZeroMinute && (standardDateProps.second || standardDateProps.millisecond)) { + delete extendedSettings.omitZeroMinute; + } +} +function postProcess(s, date, standardDateProps, extendedSettings, context) { + s = s.replace(LTR_RE, ''); // remove left-to-right control chars. do first. good for other regexes + if (standardDateProps.timeZoneName === 'short') { + s = injectTzoStr(s, (context.timeZone === 'UTC' || date.timeZoneOffset == null) ? + 'UTC' : // important to normalize for IE, which does "GMT" + formatTimeZoneOffset(date.timeZoneOffset)); + } + if (extendedSettings.omitCommas) { + s = s.replace(COMMA_RE, '').trim(); + } + if (extendedSettings.omitZeroMinute) { + s = s.replace(':00', ''); // zeroFormat doesn't always achieve this + } + // ^ do anything that might create adjacent spaces before this point, + // because MERIDIEM_RE likes to eat up loading spaces + if (extendedSettings.meridiem === false) { + s = s.replace(MERIDIEM_RE, '').trim(); + } + else if (extendedSettings.meridiem === 'narrow') { // a/p + s = s.replace(MERIDIEM_RE, function (m0, m1) { + return m1.toLocaleLowerCase(); + }); + } + else if (extendedSettings.meridiem === 'short') { // am/pm + s = s.replace(MERIDIEM_RE, function (m0, m1) { + return m1.toLocaleLowerCase() + 'm'; + }); + } + else if (extendedSettings.meridiem === 'lowercase') { // other meridiem transformers already converted to lowercase + s = s.replace(MERIDIEM_RE, function (m0) { + return m0.toLocaleLowerCase(); + }); + } + s = s.replace(MULTI_SPACE_RE, ' '); + s = s.trim(); + return s; +} +function injectTzoStr(s, tzoStr) { + var replaced = false; + s = s.replace(UTC_RE, function () { + replaced = true; + return tzoStr; + }); + // IE11 doesn't include UTC/GMT in the original string, so append to end + if (!replaced) { + s += ' ' + tzoStr; + } + return s; +} +function formatWeekNumber(num, weekLabel, locale, display) { + var parts = []; + if (display === 'narrow') { + parts.push(weekLabel); + } + else if (display === 'short') { + parts.push(weekLabel, ' '); + } + // otherwise, considered 'numeric' + parts.push(locale.simpleNumberFormat.format(num)); + if (locale.options.isRtl) { // TODO: use control characters instead? + parts.reverse(); + } + return parts.join(''); +} +// Range Formatting Utils +// 0 = exactly the same +// 1 = different by time +// and bigger +function computeMarkerDiffSeverity(d0, d1, ca) { + if (ca.getMarkerYear(d0) !== ca.getMarkerYear(d1)) { + return 5; + } + if (ca.getMarkerMonth(d0) !== ca.getMarkerMonth(d1)) { + return 4; + } + if (ca.getMarkerDay(d0) !== ca.getMarkerDay(d1)) { + return 2; + } + if (timeAsMs(d0) !== timeAsMs(d1)) { + return 1; + } + return 0; +} +function computePartialFormattingOptions(options, biggestUnit) { + var partialOptions = {}; + for (var name_2 in options) { + if (!(name_2 in STANDARD_DATE_PROP_SEVERITIES) || // not a date part prop (like timeZone) + STANDARD_DATE_PROP_SEVERITIES[name_2] <= biggestUnit) { + partialOptions[name_2] = options[name_2]; + } + } + return partialOptions; +} +function findCommonInsertion(full0, partial0, full1, partial1) { + var i0 = 0; + while (i0 < full0.length) { + var found0 = full0.indexOf(partial0, i0); + if (found0 === -1) { + break; + } + var before0 = full0.substr(0, found0); + i0 = found0 + partial0.length; + var after0 = full0.substr(i0); + var i1 = 0; + while (i1 < full1.length) { + var found1 = full1.indexOf(partial1, i1); + if (found1 === -1) { + break; + } + var before1 = full1.substr(0, found1); + i1 = found1 + partial1.length; + var after1 = full1.substr(i1); + if (before0 === before1 && after0 === after1) { + return { + before: before0, + after: after0 + }; + } + } + } + return null; +} + +/* +TODO: fix the terminology of "formatter" vs "formatting func" +*/ +/* +At the time of instantiation, this object does not know which cmd-formatting system it will use. +It receives this at the time of formatting, as a setting. +*/ +var CmdFormatter = /** @class */ (function () { + function CmdFormatter(cmdStr, separator) { + this.cmdStr = cmdStr; + this.separator = separator; + } + CmdFormatter.prototype.format = function (date, context) { + return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(date, null, context, this.separator)); + }; + CmdFormatter.prototype.formatRange = function (start, end, context) { + return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(start, end, context, this.separator)); + }; + return CmdFormatter; +}()); + +var FuncFormatter = /** @class */ (function () { + function FuncFormatter(func) { + this.func = func; + } + FuncFormatter.prototype.format = function (date, context) { + return this.func(createVerboseFormattingArg(date, null, context)); + }; + FuncFormatter.prototype.formatRange = function (start, end, context) { + return this.func(createVerboseFormattingArg(start, end, context)); + }; + return FuncFormatter; +}()); + +// Formatter Object Creation +function createFormatter(input, defaultSeparator) { + if (typeof input === 'object' && input) { // non-null object + if (typeof defaultSeparator === 'string') { + input = __assign({ separator: defaultSeparator }, input); + } + return new NativeFormatter(input); + } + else if (typeof input === 'string') { + return new CmdFormatter(input, defaultSeparator); + } + else if (typeof input === 'function') { + return new FuncFormatter(input); + } +} +// String Utils +// timeZoneOffset is in minutes +function buildIsoString(marker, timeZoneOffset, stripZeroTime) { + if (stripZeroTime === void 0) { stripZeroTime = false; } + var s = marker.toISOString(); + s = s.replace('.000', ''); + if (stripZeroTime) { + s = s.replace('T00:00:00Z', ''); + } + if (s.length > 10) { // time part wasn't stripped, can add timezone info + if (timeZoneOffset == null) { + s = s.replace('Z', ''); + } + else if (timeZoneOffset !== 0) { + s = s.replace('Z', formatTimeZoneOffset(timeZoneOffset, true)); + } + // otherwise, its UTC-0 and we want to keep the Z + } + return s; +} +function formatIsoTimeString(marker) { + return padStart(marker.getUTCHours(), 2) + ':' + + padStart(marker.getUTCMinutes(), 2) + ':' + + padStart(marker.getUTCSeconds(), 2); +} +function formatTimeZoneOffset(minutes, doIso) { + if (doIso === void 0) { doIso = false; } + var sign = minutes < 0 ? '-' : '+'; + var abs = Math.abs(minutes); + var hours = Math.floor(abs / 60); + var mins = Math.round(abs % 60); + if (doIso) { + return sign + padStart(hours, 2) + ':' + padStart(mins, 2); + } + else { + return 'GMT' + sign + hours + (mins ? ':' + padStart(mins, 2) : ''); + } +} +// Arg Utils +function createVerboseFormattingArg(start, end, context, separator) { + var startInfo = expandZonedMarker(start, context.calendarSystem); + var endInfo = end ? expandZonedMarker(end, context.calendarSystem) : null; + return { + date: startInfo, + start: startInfo, + end: endInfo, + timeZone: context.timeZone, + localeCodes: context.locale.codes, + separator: separator + }; +} +function expandZonedMarker(dateInfo, calendarSystem) { + var a = calendarSystem.markerToArray(dateInfo.marker); + return { + marker: dateInfo.marker, + timeZoneOffset: dateInfo.timeZoneOffset, + array: a, + year: a[0], + month: a[1], + day: a[2], + hour: a[3], + minute: a[4], + second: a[5], + millisecond: a[6] + }; +} + +var EventSourceApi = /** @class */ (function () { + function EventSourceApi(calendar, internalEventSource) { + this.calendar = calendar; + this.internalEventSource = internalEventSource; + } + EventSourceApi.prototype.remove = function () { + this.calendar.dispatch({ + type: 'REMOVE_EVENT_SOURCE', + sourceId: this.internalEventSource.sourceId + }); + }; + EventSourceApi.prototype.refetch = function () { + this.calendar.dispatch({ + type: 'FETCH_EVENT_SOURCES', + sourceIds: [this.internalEventSource.sourceId] + }); + }; + Object.defineProperty(EventSourceApi.prototype, "id", { + get: function () { + return this.internalEventSource.publicId; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventSourceApi.prototype, "url", { + // only relevant to json-feed event sources + get: function () { + return this.internalEventSource.meta.url; + }, + enumerable: true, + configurable: true + }); + return EventSourceApi; +}()); + +var EventApi = /** @class */ (function () { + function EventApi(calendar, def, instance) { + this._calendar = calendar; + this._def = def; + this._instance = instance || null; + } + /* + TODO: make event struct more responsible for this + */ + EventApi.prototype.setProp = function (name, val) { + var _a, _b; + if (name in DATE_PROPS) ; + else if (name in NON_DATE_PROPS) { + if (typeof NON_DATE_PROPS[name] === 'function') { + val = NON_DATE_PROPS[name](val); + } + this.mutate({ + standardProps: (_a = {}, _a[name] = val, _a) + }); + } + else if (name in UNSCOPED_EVENT_UI_PROPS) { + var ui = void 0; + if (typeof UNSCOPED_EVENT_UI_PROPS[name] === 'function') { + val = UNSCOPED_EVENT_UI_PROPS[name](val); + } + if (name === 'color') { + ui = { backgroundColor: val, borderColor: val }; + } + else if (name === 'editable') { + ui = { startEditable: val, durationEditable: val }; + } + else { + ui = (_b = {}, _b[name] = val, _b); + } + this.mutate({ + standardProps: { ui: ui } + }); + } + }; + EventApi.prototype.setExtendedProp = function (name, val) { + var _a; + this.mutate({ + extendedProps: (_a = {}, _a[name] = val, _a) + }); + }; + EventApi.prototype.setStart = function (startInput, options) { + if (options === void 0) { options = {}; } + var dateEnv = this._calendar.dateEnv; + var start = dateEnv.createMarker(startInput); + if (start && this._instance) { // TODO: warning if parsed bad + var instanceRange = this._instance.range; + var startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity); // what if parsed bad!? + if (options.maintainDuration) { + this.mutate({ datesDelta: startDelta }); + } + else { + this.mutate({ startDelta: startDelta }); + } + } + }; + EventApi.prototype.setEnd = function (endInput, options) { + if (options === void 0) { options = {}; } + var dateEnv = this._calendar.dateEnv; + var end; + if (endInput != null) { + end = dateEnv.createMarker(endInput); + if (!end) { + return; // TODO: warning if parsed bad + } + } + if (this._instance) { + if (end) { + var endDelta = diffDates(this._instance.range.end, end, dateEnv, options.granularity); + this.mutate({ endDelta: endDelta }); + } + else { + this.mutate({ standardProps: { hasEnd: false } }); + } + } + }; + EventApi.prototype.setDates = function (startInput, endInput, options) { + if (options === void 0) { options = {}; } + var dateEnv = this._calendar.dateEnv; + var standardProps = { allDay: options.allDay }; + var start = dateEnv.createMarker(startInput); + var end; + if (!start) { + return; // TODO: warning if parsed bad + } + if (endInput != null) { + end = dateEnv.createMarker(endInput); + if (!end) { // TODO: warning if parsed bad + return; + } + } + if (this._instance) { + var instanceRange = this._instance.range; + // when computing the diff for an event being converted to all-day, + // compute diff off of the all-day values the way event-mutation does. + if (options.allDay === true) { + instanceRange = computeAlignedDayRange(instanceRange); + } + var startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity); + if (end) { + var endDelta = diffDates(instanceRange.end, end, dateEnv, options.granularity); + if (durationsEqual(startDelta, endDelta)) { + this.mutate({ datesDelta: startDelta, standardProps: standardProps }); + } + else { + this.mutate({ startDelta: startDelta, endDelta: endDelta, standardProps: standardProps }); + } + } + else { // means "clear the end" + standardProps.hasEnd = false; + this.mutate({ datesDelta: startDelta, standardProps: standardProps }); + } + } + }; + EventApi.prototype.moveStart = function (deltaInput) { + var delta = createDuration(deltaInput); + if (delta) { // TODO: warning if parsed bad + this.mutate({ startDelta: delta }); + } + }; + EventApi.prototype.moveEnd = function (deltaInput) { + var delta = createDuration(deltaInput); + if (delta) { // TODO: warning if parsed bad + this.mutate({ endDelta: delta }); + } + }; + EventApi.prototype.moveDates = function (deltaInput) { + var delta = createDuration(deltaInput); + if (delta) { // TODO: warning if parsed bad + this.mutate({ datesDelta: delta }); + } + }; + EventApi.prototype.setAllDay = function (allDay, options) { + if (options === void 0) { options = {}; } + var standardProps = { allDay: allDay }; + var maintainDuration = options.maintainDuration; + if (maintainDuration == null) { + maintainDuration = this._calendar.opt('allDayMaintainDuration'); + } + if (this._def.allDay !== allDay) { + standardProps.hasEnd = maintainDuration; + } + this.mutate({ standardProps: standardProps }); + }; + EventApi.prototype.formatRange = function (formatInput) { + var dateEnv = this._calendar.dateEnv; + var instance = this._instance; + var formatter = createFormatter(formatInput, this._calendar.opt('defaultRangeSeparator')); + if (this._def.hasEnd) { + return dateEnv.formatRange(instance.range.start, instance.range.end, formatter, { + forcedStartTzo: instance.forcedStartTzo, + forcedEndTzo: instance.forcedEndTzo + }); + } + else { + return dateEnv.format(instance.range.start, formatter, { + forcedTzo: instance.forcedStartTzo + }); + } + }; + EventApi.prototype.mutate = function (mutation) { + var def = this._def; + var instance = this._instance; + if (instance) { + this._calendar.dispatch({ + type: 'MUTATE_EVENTS', + instanceId: instance.instanceId, + mutation: mutation, + fromApi: true + }); + var eventStore = this._calendar.state.eventStore; + this._def = eventStore.defs[def.defId]; + this._instance = eventStore.instances[instance.instanceId]; + } + }; + EventApi.prototype.remove = function () { + this._calendar.dispatch({ + type: 'REMOVE_EVENT_DEF', + defId: this._def.defId + }); + }; + Object.defineProperty(EventApi.prototype, "source", { + get: function () { + var sourceId = this._def.sourceId; + if (sourceId) { + return new EventSourceApi(this._calendar, this._calendar.state.eventSources[sourceId]); + } + return null; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "start", { + get: function () { + return this._instance ? + this._calendar.dateEnv.toDate(this._instance.range.start) : + null; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "end", { + get: function () { + return (this._instance && this._def.hasEnd) ? + this._calendar.dateEnv.toDate(this._instance.range.end) : + null; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "id", { + // computable props that all access the def + // TODO: find a TypeScript-compatible way to do this at scale + get: function () { return this._def.publicId; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "groupId", { + get: function () { return this._def.groupId; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "allDay", { + get: function () { return this._def.allDay; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "title", { + get: function () { return this._def.title; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "url", { + get: function () { return this._def.url; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "rendering", { + get: function () { return this._def.rendering; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "startEditable", { + get: function () { return this._def.ui.startEditable; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "durationEditable", { + get: function () { return this._def.ui.durationEditable; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "constraint", { + get: function () { return this._def.ui.constraints[0] || null; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "overlap", { + get: function () { return this._def.ui.overlap; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "allow", { + get: function () { return this._def.ui.allows[0] || null; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "backgroundColor", { + get: function () { return this._def.ui.backgroundColor; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "borderColor", { + get: function () { return this._def.ui.borderColor; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "textColor", { + get: function () { return this._def.ui.textColor; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "classNames", { + // NOTE: user can't modify these because Object.freeze was called in event-def parsing + get: function () { return this._def.ui.classNames; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "extendedProps", { + get: function () { return this._def.extendedProps; }, + enumerable: true, + configurable: true + }); + return EventApi; +}()); + +/* +Specifying nextDayThreshold signals that all-day ranges should be sliced. +*/ +function sliceEventStore(eventStore, eventUiBases, framingRange, nextDayThreshold) { + var inverseBgByGroupId = {}; + var inverseBgByDefId = {}; + var defByGroupId = {}; + var bgRanges = []; + var fgRanges = []; + var eventUis = compileEventUis(eventStore.defs, eventUiBases); + for (var defId in eventStore.defs) { + var def = eventStore.defs[defId]; + if (def.rendering === 'inverse-background') { + if (def.groupId) { + inverseBgByGroupId[def.groupId] = []; + if (!defByGroupId[def.groupId]) { + defByGroupId[def.groupId] = def; + } + } + else { + inverseBgByDefId[defId] = []; + } + } + } + for (var instanceId in eventStore.instances) { + var instance = eventStore.instances[instanceId]; + var def = eventStore.defs[instance.defId]; + var ui = eventUis[def.defId]; + var origRange = instance.range; + var normalRange = (!def.allDay && nextDayThreshold) ? + computeVisibleDayRange(origRange, nextDayThreshold) : + origRange; + var slicedRange = intersectRanges(normalRange, framingRange); + if (slicedRange) { + if (def.rendering === 'inverse-background') { + if (def.groupId) { + inverseBgByGroupId[def.groupId].push(slicedRange); + } + else { + inverseBgByDefId[instance.defId].push(slicedRange); + } + } + else { + (def.rendering === 'background' ? bgRanges : fgRanges).push({ + def: def, + ui: ui, + instance: instance, + range: slicedRange, + isStart: normalRange.start && normalRange.start.valueOf() === slicedRange.start.valueOf(), + isEnd: normalRange.end && normalRange.end.valueOf() === slicedRange.end.valueOf() + }); + } + } + } + for (var groupId in inverseBgByGroupId) { // BY GROUP + var ranges = inverseBgByGroupId[groupId]; + var invertedRanges = invertRanges(ranges, framingRange); + for (var _i = 0, invertedRanges_1 = invertedRanges; _i < invertedRanges_1.length; _i++) { + var invertedRange = invertedRanges_1[_i]; + var def = defByGroupId[groupId]; + var ui = eventUis[def.defId]; + bgRanges.push({ + def: def, + ui: ui, + instance: null, + range: invertedRange, + isStart: false, + isEnd: false + }); + } + } + for (var defId in inverseBgByDefId) { + var ranges = inverseBgByDefId[defId]; + var invertedRanges = invertRanges(ranges, framingRange); + for (var _a = 0, invertedRanges_2 = invertedRanges; _a < invertedRanges_2.length; _a++) { + var invertedRange = invertedRanges_2[_a]; + bgRanges.push({ + def: eventStore.defs[defId], + ui: eventUis[defId], + instance: null, + range: invertedRange, + isStart: false, + isEnd: false + }); + } + } + return { bg: bgRanges, fg: fgRanges }; +} +function hasBgRendering(def) { + return def.rendering === 'background' || def.rendering === 'inverse-background'; +} +function filterSegsViaEls(view, segs, isMirror) { + if (view.hasPublicHandlers('eventRender')) { + segs = segs.filter(function (seg) { + var custom = view.publiclyTrigger('eventRender', [ + { + event: new EventApi(view.calendar, seg.eventRange.def, seg.eventRange.instance), + isMirror: isMirror, + isStart: seg.isStart, + isEnd: seg.isEnd, + // TODO: include seg.range once all components consistently generate it + el: seg.el, + view: view + } + ]); + if (custom === false) { // means don't render at all + return false; + } + else if (custom && custom !== true) { + seg.el = custom; + } + return true; + }); + } + for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { + var seg = segs_1[_i]; + setElSeg(seg.el, seg); + } + return segs; +} +function setElSeg(el, seg) { + el.fcSeg = seg; +} +function getElSeg(el) { + return el.fcSeg || null; +} +// event ui computation +function compileEventUis(eventDefs, eventUiBases) { + return mapHash(eventDefs, function (eventDef) { + return compileEventUi(eventDef, eventUiBases); + }); +} +function compileEventUi(eventDef, eventUiBases) { + var uis = []; + if (eventUiBases['']) { + uis.push(eventUiBases['']); + } + if (eventUiBases[eventDef.defId]) { + uis.push(eventUiBases[eventDef.defId]); + } + uis.push(eventDef.ui); + return combineEventUis(uis); +} + +// applies the mutation to ALL defs/instances within the event store +function applyMutationToEventStore(eventStore, eventConfigBase, mutation, calendar) { + var eventConfigs = compileEventUis(eventStore.defs, eventConfigBase); + var dest = createEmptyEventStore(); + for (var defId in eventStore.defs) { + var def = eventStore.defs[defId]; + dest.defs[defId] = applyMutationToEventDef(def, eventConfigs[defId], mutation, calendar.pluginSystem.hooks.eventDefMutationAppliers, calendar); + } + for (var instanceId in eventStore.instances) { + var instance = eventStore.instances[instanceId]; + var def = dest.defs[instance.defId]; // important to grab the newly modified def + dest.instances[instanceId] = applyMutationToEventInstance(instance, def, eventConfigs[instance.defId], mutation, calendar); + } + return dest; +} +function applyMutationToEventDef(eventDef, eventConfig, mutation, appliers, calendar) { + var standardProps = mutation.standardProps || {}; + // if hasEnd has not been specified, guess a good value based on deltas. + // if duration will change, there's no way the default duration will persist, + // and thus, we need to mark the event as having a real end + if (standardProps.hasEnd == null && + eventConfig.durationEditable && + (mutation.startDelta || mutation.endDelta)) { + standardProps.hasEnd = true; // TODO: is this mutation okay? + } + var copy = __assign({}, eventDef, standardProps, { ui: __assign({}, eventDef.ui, standardProps.ui) }); + if (mutation.extendedProps) { + copy.extendedProps = __assign({}, copy.extendedProps, mutation.extendedProps); + } + for (var _i = 0, appliers_1 = appliers; _i < appliers_1.length; _i++) { + var applier = appliers_1[_i]; + applier(copy, mutation, calendar); + } + if (!copy.hasEnd && calendar.opt('forceEventDuration')) { + copy.hasEnd = true; + } + return copy; +} +function applyMutationToEventInstance(eventInstance, eventDef, // must first be modified by applyMutationToEventDef +eventConfig, mutation, calendar) { + var dateEnv = calendar.dateEnv; + var forceAllDay = mutation.standardProps && mutation.standardProps.allDay === true; + var clearEnd = mutation.standardProps && mutation.standardProps.hasEnd === false; + var copy = __assign({}, eventInstance); + if (forceAllDay) { + copy.range = computeAlignedDayRange(copy.range); + } + if (mutation.datesDelta && eventConfig.startEditable) { + copy.range = { + start: dateEnv.add(copy.range.start, mutation.datesDelta), + end: dateEnv.add(copy.range.end, mutation.datesDelta) + }; + } + if (mutation.startDelta && eventConfig.durationEditable) { + copy.range = { + start: dateEnv.add(copy.range.start, mutation.startDelta), + end: copy.range.end + }; + } + if (mutation.endDelta && eventConfig.durationEditable) { + copy.range = { + start: copy.range.start, + end: dateEnv.add(copy.range.end, mutation.endDelta) + }; + } + if (clearEnd) { + copy.range = { + start: copy.range.start, + end: calendar.getDefaultEventEnd(eventDef.allDay, copy.range.start) + }; + } + // in case event was all-day but the supplied deltas were not + // better util for this? + if (eventDef.allDay) { + copy.range = { + start: startOfDay(copy.range.start), + end: startOfDay(copy.range.end) + }; + } + // handle invalid durations + if (copy.range.end < copy.range.start) { + copy.range.end = calendar.getDefaultEventEnd(eventDef.allDay, copy.range.start); + } + return copy; +} + +function reduceEventStore (eventStore, action, eventSources, dateProfile, calendar) { + switch (action.type) { + case 'RECEIVE_EVENTS': // raw + return receiveRawEvents(eventStore, eventSources[action.sourceId], action.fetchId, action.fetchRange, action.rawEvents, calendar); + case 'ADD_EVENTS': // already parsed, but not expanded + return addEvent(eventStore, action.eventStore, // new ones + dateProfile ? dateProfile.activeRange : null, calendar); + case 'MERGE_EVENTS': // already parsed and expanded + return mergeEventStores(eventStore, action.eventStore); + case 'PREV': // TODO: how do we track all actions that affect dateProfile :( + case 'NEXT': + case 'SET_DATE': + case 'SET_VIEW_TYPE': + if (dateProfile) { + return expandRecurring(eventStore, dateProfile.activeRange, calendar); + } + else { + return eventStore; + } + case 'CHANGE_TIMEZONE': + return rezoneDates(eventStore, action.oldDateEnv, calendar.dateEnv); + case 'MUTATE_EVENTS': + return applyMutationToRelated(eventStore, action.instanceId, action.mutation, action.fromApi, calendar); + case 'REMOVE_EVENT_INSTANCES': + return excludeInstances(eventStore, action.instances); + case 'REMOVE_EVENT_DEF': + return filterEventStoreDefs(eventStore, function (eventDef) { + return eventDef.defId !== action.defId; + }); + case 'REMOVE_EVENT_SOURCE': + return excludeEventsBySourceId(eventStore, action.sourceId); + case 'REMOVE_ALL_EVENT_SOURCES': + return filterEventStoreDefs(eventStore, function (eventDef) { + return !eventDef.sourceId; // only keep events with no source id + }); + case 'REMOVE_ALL_EVENTS': + return createEmptyEventStore(); + case 'RESET_EVENTS': + return { + defs: eventStore.defs, + instances: eventStore.instances + }; + default: + return eventStore; + } +} +function receiveRawEvents(eventStore, eventSource, fetchId, fetchRange, rawEvents, calendar) { + if (eventSource && // not already removed + fetchId === eventSource.latestFetchId // TODO: wish this logic was always in event-sources + ) { + var subset = parseEvents(transformRawEvents(rawEvents, eventSource, calendar), eventSource.sourceId, calendar); + if (fetchRange) { + subset = expandRecurring(subset, fetchRange, calendar); + } + return mergeEventStores(excludeEventsBySourceId(eventStore, eventSource.sourceId), subset); + } + return eventStore; +} +function addEvent(eventStore, subset, expandRange, calendar) { + if (expandRange) { + subset = expandRecurring(subset, expandRange, calendar); + } + return mergeEventStores(eventStore, subset); +} +function rezoneDates(eventStore, oldDateEnv, newDateEnv) { + var defs = eventStore.defs; + var instances = mapHash(eventStore.instances, function (instance) { + var def = defs[instance.defId]; + if (def.allDay || def.recurringDef) { + return instance; // isn't dependent on timezone + } + else { + return __assign({}, instance, { range: { + start: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.start, instance.forcedStartTzo)), + end: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.end, instance.forcedEndTzo)) + }, forcedStartTzo: newDateEnv.canComputeOffset ? null : instance.forcedStartTzo, forcedEndTzo: newDateEnv.canComputeOffset ? null : instance.forcedEndTzo }); + } + }); + return { defs: defs, instances: instances }; +} +function applyMutationToRelated(eventStore, instanceId, mutation, fromApi, calendar) { + var relevant = getRelevantEvents(eventStore, instanceId); + var eventConfigBase = fromApi ? + { '': { + startEditable: true, + durationEditable: true, + constraints: [], + overlap: null, + allows: [], + backgroundColor: '', + borderColor: '', + textColor: '', + classNames: [] + } } : + calendar.eventUiBases; + relevant = applyMutationToEventStore(relevant, eventConfigBase, mutation, calendar); + return mergeEventStores(eventStore, relevant); +} +function excludeEventsBySourceId(eventStore, sourceId) { + return filterEventStoreDefs(eventStore, function (eventDef) { + return eventDef.sourceId !== sourceId; + }); +} +// QUESTION: why not just return instances? do a general object-property-exclusion util +function excludeInstances(eventStore, removals) { + return { + defs: eventStore.defs, + instances: filterHash(eventStore.instances, function (instance) { + return !removals[instance.instanceId]; + }) + }; +} + +// high-level segmenting-aware tester functions +// ------------------------------------------------------------------------------------------------------------------------ +function isInteractionValid(interaction, calendar) { + return isNewPropsValid({ eventDrag: interaction }, calendar); // HACK: the eventDrag props is used for ALL interactions +} +function isDateSelectionValid(dateSelection, calendar) { + return isNewPropsValid({ dateSelection: dateSelection }, calendar); +} +function isNewPropsValid(newProps, calendar) { + var view = calendar.view; + var props = __assign({ businessHours: view ? view.props.businessHours : createEmptyEventStore(), dateSelection: '', eventStore: calendar.state.eventStore, eventUiBases: calendar.eventUiBases, eventSelection: '', eventDrag: null, eventResize: null }, newProps); + return (calendar.pluginSystem.hooks.isPropsValid || isPropsValid)(props, calendar); +} +function isPropsValid(state, calendar, dateSpanMeta, filterConfig) { + if (dateSpanMeta === void 0) { dateSpanMeta = {}; } + if (state.eventDrag && !isInteractionPropsValid(state, calendar, dateSpanMeta, filterConfig)) { + return false; + } + if (state.dateSelection && !isDateSelectionPropsValid(state, calendar, dateSpanMeta, filterConfig)) { + return false; + } + return true; +} +// Moving Event Validation +// ------------------------------------------------------------------------------------------------------------------------ +function isInteractionPropsValid(state, calendar, dateSpanMeta, filterConfig) { + var interaction = state.eventDrag; // HACK: the eventDrag props is used for ALL interactions + var subjectEventStore = interaction.mutatedEvents; + var subjectDefs = subjectEventStore.defs; + var subjectInstances = subjectEventStore.instances; + var subjectConfigs = compileEventUis(subjectDefs, interaction.isEvent ? + state.eventUiBases : + { '': calendar.selectionConfig } // if not a real event, validate as a selection + ); + if (filterConfig) { + subjectConfigs = mapHash(subjectConfigs, filterConfig); + } + var otherEventStore = excludeInstances(state.eventStore, interaction.affectedEvents.instances); // exclude the subject events. TODO: exclude defs too? + var otherDefs = otherEventStore.defs; + var otherInstances = otherEventStore.instances; + var otherConfigs = compileEventUis(otherDefs, state.eventUiBases); + for (var subjectInstanceId in subjectInstances) { + var subjectInstance = subjectInstances[subjectInstanceId]; + var subjectRange = subjectInstance.range; + var subjectConfig = subjectConfigs[subjectInstance.defId]; + var subjectDef = subjectDefs[subjectInstance.defId]; + // constraint + if (!allConstraintsPass(subjectConfig.constraints, subjectRange, otherEventStore, state.businessHours, calendar)) { + return false; + } + // overlap + var overlapFunc = calendar.opt('eventOverlap'); + if (typeof overlapFunc !== 'function') { + overlapFunc = null; + } + for (var otherInstanceId in otherInstances) { + var otherInstance = otherInstances[otherInstanceId]; + // intersect! evaluate + if (rangesIntersect(subjectRange, otherInstance.range)) { + var otherOverlap = otherConfigs[otherInstance.defId].overlap; + // consider the other event's overlap. only do this if the subject event is a "real" event + if (otherOverlap === false && interaction.isEvent) { + return false; + } + if (subjectConfig.overlap === false) { + return false; + } + if (overlapFunc && !overlapFunc(new EventApi(calendar, otherDefs[otherInstance.defId], otherInstance), // still event + new EventApi(calendar, subjectDef, subjectInstance) // moving event + )) { + return false; + } + } + } + // allow (a function) + var calendarEventStore = calendar.state.eventStore; // need global-to-calendar, not local to component (splittable)state + for (var _i = 0, _a = subjectConfig.allows; _i < _a.length; _i++) { + var subjectAllow = _a[_i]; + var subjectDateSpan = __assign({}, dateSpanMeta, { range: subjectInstance.range, allDay: subjectDef.allDay }); + var origDef = calendarEventStore.defs[subjectDef.defId]; + var origInstance = calendarEventStore.instances[subjectInstanceId]; + var eventApi = void 0; + if (origDef) { // was previously in the calendar + eventApi = new EventApi(calendar, origDef, origInstance); + } + else { // was an external event + eventApi = new EventApi(calendar, subjectDef); // no instance, because had no dates + } + if (!subjectAllow(calendar.buildDateSpanApi(subjectDateSpan), eventApi)) { + return false; + } + } + } + return true; +} +// Date Selection Validation +// ------------------------------------------------------------------------------------------------------------------------ +function isDateSelectionPropsValid(state, calendar, dateSpanMeta, filterConfig) { + var relevantEventStore = state.eventStore; + var relevantDefs = relevantEventStore.defs; + var relevantInstances = relevantEventStore.instances; + var selection = state.dateSelection; + var selectionRange = selection.range; + var selectionConfig = calendar.selectionConfig; + if (filterConfig) { + selectionConfig = filterConfig(selectionConfig); + } + // constraint + if (!allConstraintsPass(selectionConfig.constraints, selectionRange, relevantEventStore, state.businessHours, calendar)) { + return false; + } + // overlap + var overlapFunc = calendar.opt('selectOverlap'); + if (typeof overlapFunc !== 'function') { + overlapFunc = null; + } + for (var relevantInstanceId in relevantInstances) { + var relevantInstance = relevantInstances[relevantInstanceId]; + // intersect! evaluate + if (rangesIntersect(selectionRange, relevantInstance.range)) { + if (selectionConfig.overlap === false) { + return false; + } + if (overlapFunc && !overlapFunc(new EventApi(calendar, relevantDefs[relevantInstance.defId], relevantInstance))) { + return false; + } + } + } + // allow (a function) + for (var _i = 0, _a = selectionConfig.allows; _i < _a.length; _i++) { + var selectionAllow = _a[_i]; + var fullDateSpan = __assign({}, dateSpanMeta, selection); + if (!selectionAllow(calendar.buildDateSpanApi(fullDateSpan), null)) { + return false; + } + } + return true; +} +// Constraint Utils +// ------------------------------------------------------------------------------------------------------------------------ +function allConstraintsPass(constraints, subjectRange, otherEventStore, businessHoursUnexpanded, calendar) { + for (var _i = 0, constraints_1 = constraints; _i < constraints_1.length; _i++) { + var constraint = constraints_1[_i]; + if (!anyRangesContainRange(constraintToRanges(constraint, subjectRange, otherEventStore, businessHoursUnexpanded, calendar), subjectRange)) { + return false; + } + } + return true; +} +function constraintToRanges(constraint, subjectRange, // for expanding a recurring constraint, or expanding business hours +otherEventStore, // for if constraint is an even group ID +businessHoursUnexpanded, // for if constraint is 'businessHours' +calendar // for expanding businesshours +) { + if (constraint === 'businessHours') { + return eventStoreToRanges(expandRecurring(businessHoursUnexpanded, subjectRange, calendar)); + } + else if (typeof constraint === 'string') { // an group ID + return eventStoreToRanges(filterEventStoreDefs(otherEventStore, function (eventDef) { + return eventDef.groupId === constraint; + })); + } + else if (typeof constraint === 'object' && constraint) { // non-null object + return eventStoreToRanges(expandRecurring(constraint, subjectRange, calendar)); + } + return []; // if it's false +} +// TODO: move to event-store file? +function eventStoreToRanges(eventStore) { + var instances = eventStore.instances; + var ranges = []; + for (var instanceId in instances) { + ranges.push(instances[instanceId].range); + } + return ranges; +} +// TODO: move to geom file? +function anyRangesContainRange(outerRanges, innerRange) { + for (var _i = 0, outerRanges_1 = outerRanges; _i < outerRanges_1.length; _i++) { + var outerRange = outerRanges_1[_i]; + if (rangeContainsRange(outerRange, innerRange)) { + return true; + } + } + return false; +} +// Parsing +// ------------------------------------------------------------------------------------------------------------------------ +function normalizeConstraint(input, calendar) { + if (Array.isArray(input)) { + return parseEvents(input, '', calendar, true); // allowOpenRange=true + } + else if (typeof input === 'object' && input) { // non-null object + return parseEvents([input], '', calendar, true); // allowOpenRange=true + } + else if (input != null) { + return String(input); + } + else { + return null; + } +} + +function htmlEscape(s) { + return (s + '').replace(/&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/'/g, ''') + .replace(/"/g, '"') + .replace(/\n/g, '<br />'); +} +// Given a hash of CSS properties, returns a string of CSS. +// Uses property names as-is (no camel-case conversion). Will not make statements for null/undefined values. +function cssToStr(cssProps) { + var statements = []; + for (var name_1 in cssProps) { + var val = cssProps[name_1]; + if (val != null && val !== '') { + statements.push(name_1 + ':' + val); + } + } + return statements.join(';'); +} +// Given an object hash of HTML attribute names to values, +// generates a string that can be injected between < > in HTML +function attrsToStr(attrs) { + var parts = []; + for (var name_2 in attrs) { + var val = attrs[name_2]; + if (val != null) { + parts.push(name_2 + '="' + htmlEscape(val) + '"'); + } + } + return parts.join(' '); +} +function parseClassName(raw) { + if (Array.isArray(raw)) { + return raw; + } + else if (typeof raw === 'string') { + return raw.split(/\s+/); + } + else { + return []; + } +} + +var UNSCOPED_EVENT_UI_PROPS = { + editable: Boolean, + startEditable: Boolean, + durationEditable: Boolean, + constraint: null, + overlap: null, + allow: null, + className: parseClassName, + classNames: parseClassName, + color: String, + backgroundColor: String, + borderColor: String, + textColor: String +}; +function processUnscopedUiProps(rawProps, calendar, leftovers) { + var props = refineProps(rawProps, UNSCOPED_EVENT_UI_PROPS, {}, leftovers); + var constraint = normalizeConstraint(props.constraint, calendar); + return { + startEditable: props.startEditable != null ? props.startEditable : props.editable, + durationEditable: props.durationEditable != null ? props.durationEditable : props.editable, + constraints: constraint != null ? [constraint] : [], + overlap: props.overlap, + allows: props.allow != null ? [props.allow] : [], + backgroundColor: props.backgroundColor || props.color, + borderColor: props.borderColor || props.color, + textColor: props.textColor, + classNames: props.classNames.concat(props.className) + }; +} +function processScopedUiProps(prefix, rawScoped, calendar, leftovers) { + var rawUnscoped = {}; + var wasFound = {}; + for (var key in UNSCOPED_EVENT_UI_PROPS) { + var scopedKey = prefix + capitaliseFirstLetter(key); + rawUnscoped[key] = rawScoped[scopedKey]; + wasFound[scopedKey] = true; + } + if (prefix === 'event') { + rawUnscoped.editable = rawScoped.editable; // special case. there is no 'eventEditable', just 'editable' + } + if (leftovers) { + for (var key in rawScoped) { + if (!wasFound[key]) { + leftovers[key] = rawScoped[key]; + } + } + } + return processUnscopedUiProps(rawUnscoped, calendar); +} +var EMPTY_EVENT_UI = { + startEditable: null, + durationEditable: null, + constraints: [], + overlap: null, + allows: [], + backgroundColor: '', + borderColor: '', + textColor: '', + classNames: [] +}; +// prevent against problems with <2 args! +function combineEventUis(uis) { + return uis.reduce(combineTwoEventUis, EMPTY_EVENT_UI); +} +function combineTwoEventUis(item0, item1) { + return { + startEditable: item1.startEditable != null ? item1.startEditable : item0.startEditable, + durationEditable: item1.durationEditable != null ? item1.durationEditable : item0.durationEditable, + constraints: item0.constraints.concat(item1.constraints), + overlap: typeof item1.overlap === 'boolean' ? item1.overlap : item0.overlap, + allows: item0.allows.concat(item1.allows), + backgroundColor: item1.backgroundColor || item0.backgroundColor, + borderColor: item1.borderColor || item0.borderColor, + textColor: item1.textColor || item0.textColor, + classNames: item0.classNames.concat(item1.classNames) + }; +} + +var NON_DATE_PROPS = { + id: String, + groupId: String, + title: String, + url: String, + rendering: String, + extendedProps: null +}; +var DATE_PROPS = { + start: null, + date: null, + end: null, + allDay: null +}; +var uid = 0; +function parseEvent(raw, sourceId, calendar, allowOpenRange) { + var allDayDefault = computeIsAllDayDefault(sourceId, calendar); + var leftovers0 = {}; + var recurringRes = parseRecurring(raw, // raw, but with single-event stuff stripped out + allDayDefault, calendar.dateEnv, calendar.pluginSystem.hooks.recurringTypes, leftovers0 // will populate with non-recurring props + ); + if (recurringRes) { + var def = parseEventDef(leftovers0, sourceId, recurringRes.allDay, Boolean(recurringRes.duration), calendar); + def.recurringDef = { + typeId: recurringRes.typeId, + typeData: recurringRes.typeData, + duration: recurringRes.duration + }; + return { def: def, instance: null }; + } + else { + var leftovers1 = {}; + var singleRes = parseSingle(raw, allDayDefault, calendar, leftovers1, allowOpenRange); + if (singleRes) { + var def = parseEventDef(leftovers1, sourceId, singleRes.allDay, singleRes.hasEnd, calendar); + var instance = createEventInstance(def.defId, singleRes.range, singleRes.forcedStartTzo, singleRes.forcedEndTzo); + return { def: def, instance: instance }; + } + } + return null; +} +/* +Will NOT populate extendedProps with the leftover properties. +Will NOT populate date-related props. +The EventNonDateInput has been normalized (id => publicId, etc). +*/ +function parseEventDef(raw, sourceId, allDay, hasEnd, calendar) { + var leftovers = {}; + var def = pluckNonDateProps(raw, calendar, leftovers); + def.defId = String(uid++); + def.sourceId = sourceId; + def.allDay = allDay; + def.hasEnd = hasEnd; + for (var _i = 0, _a = calendar.pluginSystem.hooks.eventDefParsers; _i < _a.length; _i++) { + var eventDefParser = _a[_i]; + var newLeftovers = {}; + eventDefParser(def, leftovers, newLeftovers); + leftovers = newLeftovers; + } + def.extendedProps = __assign(leftovers, def.extendedProps || {}); + // help out EventApi from having user modify props + Object.freeze(def.ui.classNames); + Object.freeze(def.extendedProps); + return def; +} +function createEventInstance(defId, range, forcedStartTzo, forcedEndTzo) { + return { + instanceId: String(uid++), + defId: defId, + range: range, + forcedStartTzo: forcedStartTzo == null ? null : forcedStartTzo, + forcedEndTzo: forcedEndTzo == null ? null : forcedEndTzo + }; +} +function parseSingle(raw, allDayDefault, calendar, leftovers, allowOpenRange) { + var props = pluckDateProps(raw, leftovers); + var allDay = props.allDay; + var startMeta; + var startMarker = null; + var hasEnd = false; + var endMeta; + var endMarker = null; + startMeta = calendar.dateEnv.createMarkerMeta(props.start); + if (startMeta) { + startMarker = startMeta.marker; + } + else if (!allowOpenRange) { + return null; + } + if (props.end != null) { + endMeta = calendar.dateEnv.createMarkerMeta(props.end); + } + if (allDay == null) { + if (allDayDefault != null) { + allDay = allDayDefault; + } + else { + // fall back to the date props LAST + allDay = (!startMeta || startMeta.isTimeUnspecified) && + (!endMeta || endMeta.isTimeUnspecified); + } + } + if (allDay && startMarker) { + startMarker = startOfDay(startMarker); + } + if (endMeta) { + endMarker = endMeta.marker; + if (allDay) { + endMarker = startOfDay(endMarker); + } + if (startMarker && endMarker <= startMarker) { + endMarker = null; + } + } + if (endMarker) { + hasEnd = true; + } + else if (!allowOpenRange) { + hasEnd = calendar.opt('forceEventDuration') || false; + endMarker = calendar.dateEnv.add(startMarker, allDay ? + calendar.defaultAllDayEventDuration : + calendar.defaultTimedEventDuration); + } + return { + allDay: allDay, + hasEnd: hasEnd, + range: { start: startMarker, end: endMarker }, + forcedStartTzo: startMeta ? startMeta.forcedTzo : null, + forcedEndTzo: endMeta ? endMeta.forcedTzo : null + }; +} +function pluckDateProps(raw, leftovers) { + var props = refineProps(raw, DATE_PROPS, {}, leftovers); + props.start = (props.start !== null) ? props.start : props.date; + delete props.date; + return props; +} +function pluckNonDateProps(raw, calendar, leftovers) { + var preLeftovers = {}; + var props = refineProps(raw, NON_DATE_PROPS, {}, preLeftovers); + var ui = processUnscopedUiProps(preLeftovers, calendar, leftovers); + props.publicId = props.id; + delete props.id; + props.ui = ui; + return props; +} +function computeIsAllDayDefault(sourceId, calendar) { + var res = null; + if (sourceId) { + var source = calendar.state.eventSources[sourceId]; + res = source.allDayDefault; + } + if (res == null) { + res = calendar.opt('allDayDefault'); + } + return res; +} + +var DEF_DEFAULTS = { + startTime: '09:00', + endTime: '17:00', + daysOfWeek: [1, 2, 3, 4, 5], + rendering: 'inverse-background', + classNames: 'fc-nonbusiness', + groupId: '_businessHours' // so multiple defs get grouped +}; +/* +TODO: pass around as EventDefHash!!! +*/ +function parseBusinessHours(input, calendar) { + return parseEvents(refineInputs(input), '', calendar); +} +function refineInputs(input) { + var rawDefs; + if (input === true) { + rawDefs = [{}]; // will get DEF_DEFAULTS verbatim + } + else if (Array.isArray(input)) { + // if specifying an array, every sub-definition NEEDS a day-of-week + rawDefs = input.filter(function (rawDef) { + return rawDef.daysOfWeek; + }); + } + else if (typeof input === 'object' && input) { // non-null object + rawDefs = [input]; + } + else { // is probably false + rawDefs = []; + } + rawDefs = rawDefs.map(function (rawDef) { + return __assign({}, DEF_DEFAULTS, rawDef); + }); + return rawDefs; +} + +function memoizeRendering(renderFunc, unrenderFunc, dependencies) { + if (dependencies === void 0) { dependencies = []; } + var dependents = []; + var thisContext; + var prevArgs; + function unrender() { + if (prevArgs) { + for (var _i = 0, dependents_1 = dependents; _i < dependents_1.length; _i++) { + var dependent = dependents_1[_i]; + dependent.unrender(); + } + if (unrenderFunc) { + unrenderFunc.apply(thisContext, prevArgs); + } + prevArgs = null; + } + } + function res() { + if (!prevArgs || !isArraysEqual(prevArgs, arguments)) { + unrender(); + thisContext = this; + prevArgs = arguments; + renderFunc.apply(this, arguments); + } + } + res.dependents = dependents; + res.unrender = unrender; + for (var _i = 0, dependencies_1 = dependencies; _i < dependencies_1.length; _i++) { + var dependency = dependencies_1[_i]; + dependency.dependents.push(res); + } + return res; +} + +var EMPTY_EVENT_STORE = createEmptyEventStore(); // for purecomponents. TODO: keep elsewhere +var Splitter = /** @class */ (function () { + function Splitter() { + this.getKeysForEventDefs = memoize(this._getKeysForEventDefs); + this.splitDateSelection = memoize(this._splitDateSpan); + this.splitEventStore = memoize(this._splitEventStore); + this.splitIndividualUi = memoize(this._splitIndividualUi); + this.splitEventDrag = memoize(this._splitInteraction); + this.splitEventResize = memoize(this._splitInteraction); + this.eventUiBuilders = {}; // TODO: typescript protection + } + Splitter.prototype.splitProps = function (props) { + var _this = this; + var keyInfos = this.getKeyInfo(props); + var defKeys = this.getKeysForEventDefs(props.eventStore); + var dateSelections = this.splitDateSelection(props.dateSelection); + var individualUi = this.splitIndividualUi(props.eventUiBases, defKeys); // the individual *bases* + var eventStores = this.splitEventStore(props.eventStore, defKeys); + var eventDrags = this.splitEventDrag(props.eventDrag); + var eventResizes = this.splitEventResize(props.eventResize); + var splitProps = {}; + this.eventUiBuilders = mapHash(keyInfos, function (info, key) { + return _this.eventUiBuilders[key] || memoize(buildEventUiForKey); + }); + for (var key in keyInfos) { + var keyInfo = keyInfos[key]; + var eventStore = eventStores[key] || EMPTY_EVENT_STORE; + var buildEventUi = this.eventUiBuilders[key]; + splitProps[key] = { + businessHours: keyInfo.businessHours || props.businessHours, + dateSelection: dateSelections[key] || null, + eventStore: eventStore, + eventUiBases: buildEventUi(props.eventUiBases[''], keyInfo.ui, individualUi[key]), + eventSelection: eventStore.instances[props.eventSelection] ? props.eventSelection : '', + eventDrag: eventDrags[key] || null, + eventResize: eventResizes[key] || null + }; + } + return splitProps; + }; + Splitter.prototype._splitDateSpan = function (dateSpan) { + var dateSpans = {}; + if (dateSpan) { + var keys = this.getKeysForDateSpan(dateSpan); + for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { + var key = keys_1[_i]; + dateSpans[key] = dateSpan; + } + } + return dateSpans; + }; + Splitter.prototype._getKeysForEventDefs = function (eventStore) { + var _this = this; + return mapHash(eventStore.defs, function (eventDef) { + return _this.getKeysForEventDef(eventDef); + }); + }; + Splitter.prototype._splitEventStore = function (eventStore, defKeys) { + var defs = eventStore.defs, instances = eventStore.instances; + var splitStores = {}; + for (var defId in defs) { + for (var _i = 0, _a = defKeys[defId]; _i < _a.length; _i++) { + var key = _a[_i]; + if (!splitStores[key]) { + splitStores[key] = createEmptyEventStore(); + } + splitStores[key].defs[defId] = defs[defId]; + } + } + for (var instanceId in instances) { + var instance = instances[instanceId]; + for (var _b = 0, _c = defKeys[instance.defId]; _b < _c.length; _b++) { + var key = _c[_b]; + if (splitStores[key]) { // must have already been created + splitStores[key].instances[instanceId] = instance; + } + } + } + return splitStores; + }; + Splitter.prototype._splitIndividualUi = function (eventUiBases, defKeys) { + var splitHashes = {}; + for (var defId in eventUiBases) { + if (defId) { // not the '' key + for (var _i = 0, _a = defKeys[defId]; _i < _a.length; _i++) { + var key = _a[_i]; + if (!splitHashes[key]) { + splitHashes[key] = {}; + } + splitHashes[key][defId] = eventUiBases[defId]; + } + } + } + return splitHashes; + }; + Splitter.prototype._splitInteraction = function (interaction) { + var splitStates = {}; + if (interaction) { + var affectedStores_1 = this._splitEventStore(interaction.affectedEvents, this._getKeysForEventDefs(interaction.affectedEvents) // can't use cached. might be events from other calendar + ); + // can't rely on defKeys because event data is mutated + var mutatedKeysByDefId = this._getKeysForEventDefs(interaction.mutatedEvents); + var mutatedStores_1 = this._splitEventStore(interaction.mutatedEvents, mutatedKeysByDefId); + var populate = function (key) { + if (!splitStates[key]) { + splitStates[key] = { + affectedEvents: affectedStores_1[key] || EMPTY_EVENT_STORE, + mutatedEvents: mutatedStores_1[key] || EMPTY_EVENT_STORE, + isEvent: interaction.isEvent, + origSeg: interaction.origSeg + }; + } + }; + for (var key in affectedStores_1) { + populate(key); + } + for (var key in mutatedStores_1) { + populate(key); + } + } + return splitStates; + }; + return Splitter; +}()); +function buildEventUiForKey(allUi, eventUiForKey, individualUi) { + var baseParts = []; + if (allUi) { + baseParts.push(allUi); + } + if (eventUiForKey) { + baseParts.push(eventUiForKey); + } + var stuff = { + '': combineEventUis(baseParts) + }; + if (individualUi) { + __assign(stuff, individualUi); + } + return stuff; +} + +// Generates HTML for an anchor to another view into the calendar. +// Will either generate an <a> tag or a non-clickable <span> tag, depending on enabled settings. +// `gotoOptions` can either be a DateMarker, or an object with the form: +// { date, type, forceOff } +// `type` is a view-type like "day" or "week". default value is "day". +// `attrs` and `innerHtml` are use to generate the rest of the HTML tag. +function buildGotoAnchorHtml(component, gotoOptions, attrs, innerHtml) { + var dateEnv = component.dateEnv; + var date; + var type; + var forceOff; + var finalOptions; + if (gotoOptions instanceof Date) { + date = gotoOptions; // a single date-like input + } + else { + date = gotoOptions.date; + type = gotoOptions.type; + forceOff = gotoOptions.forceOff; + } + finalOptions = { + date: dateEnv.formatIso(date, { omitTime: true }), + type: type || 'day' + }; + if (typeof attrs === 'string') { + innerHtml = attrs; + attrs = null; + } + attrs = attrs ? ' ' + attrsToStr(attrs) : ''; // will have a leading space + innerHtml = innerHtml || ''; + if (!forceOff && component.opt('navLinks')) { + return '<a' + attrs + + ' data-goto="' + htmlEscape(JSON.stringify(finalOptions)) + '">' + + innerHtml + + '</a>'; + } + else { + return '<span' + attrs + '>' + + innerHtml + + '</span>'; + } +} +function getAllDayHtml(component) { + return component.opt('allDayHtml') || htmlEscape(component.opt('allDayText')); +} +// Computes HTML classNames for a single-day element +function getDayClasses(date, dateProfile, context, noThemeHighlight) { + var calendar = context.calendar, view = context.view, theme = context.theme, dateEnv = context.dateEnv; + var classes = []; + var todayStart; + var todayEnd; + if (!rangeContainsMarker(dateProfile.activeRange, date)) { + classes.push('fc-disabled-day'); + } + else { + classes.push('fc-' + DAY_IDS[date.getUTCDay()]); + if (view.opt('monthMode') && + dateEnv.getMonth(date) !== dateEnv.getMonth(dateProfile.currentRange.start)) { + classes.push('fc-other-month'); + } + todayStart = startOfDay(calendar.getNow()); + todayEnd = addDays(todayStart, 1); + if (date < todayStart) { + classes.push('fc-past'); + } + else if (date >= todayEnd) { + classes.push('fc-future'); + } + else { + classes.push('fc-today'); + if (noThemeHighlight !== true) { + classes.push(theme.getClass('today')); + } + } + } + return classes; +} + +// given a function that resolves a result asynchronously. +// the function can either call passed-in success and failure callbacks, +// or it can return a promise. +// if you need to pass additional params to func, bind them first. +function unpromisify(func, success, failure) { + // guard against success/failure callbacks being called more than once + // and guard against a promise AND callback being used together. + var isResolved = false; + var wrappedSuccess = function () { + if (!isResolved) { + isResolved = true; + success.apply(this, arguments); + } + }; + var wrappedFailure = function () { + if (!isResolved) { + isResolved = true; + if (failure) { + failure.apply(this, arguments); + } + } + }; + var res = func(wrappedSuccess, wrappedFailure); + if (res && typeof res.then === 'function') { + res.then(wrappedSuccess, wrappedFailure); + } +} + +var Mixin = /** @class */ (function () { + function Mixin() { + } + // mix into a CLASS + Mixin.mixInto = function (destClass) { + this.mixIntoObj(destClass.prototype); + }; + // mix into ANY object + Mixin.mixIntoObj = function (destObj) { + var _this = this; + Object.getOwnPropertyNames(this.prototype).forEach(function (name) { + if (!destObj[name]) { // if destination doesn't already define it + destObj[name] = _this.prototype[name]; + } + }); + }; + /* + will override existing methods + TODO: remove! not used anymore + */ + Mixin.mixOver = function (destClass) { + var _this = this; + Object.getOwnPropertyNames(this.prototype).forEach(function (name) { + destClass.prototype[name] = _this.prototype[name]; + }); + }; + return Mixin; +}()); + +/* +USAGE: + import { default as EmitterMixin, EmitterInterface } from './EmitterMixin' +in class: + on: EmitterInterface['on'] + one: EmitterInterface['one'] + off: EmitterInterface['off'] + trigger: EmitterInterface['trigger'] + triggerWith: EmitterInterface['triggerWith'] + hasHandlers: EmitterInterface['hasHandlers'] +after class: + EmitterMixin.mixInto(TheClass) +*/ +var EmitterMixin = /** @class */ (function (_super) { + __extends(EmitterMixin, _super); + function EmitterMixin() { + return _super !== null && _super.apply(this, arguments) || this; + } + EmitterMixin.prototype.on = function (type, handler) { + addToHash(this._handlers || (this._handlers = {}), type, handler); + return this; // for chaining + }; + // todo: add comments + EmitterMixin.prototype.one = function (type, handler) { + addToHash(this._oneHandlers || (this._oneHandlers = {}), type, handler); + return this; // for chaining + }; + EmitterMixin.prototype.off = function (type, handler) { + if (this._handlers) { + removeFromHash(this._handlers, type, handler); + } + if (this._oneHandlers) { + removeFromHash(this._oneHandlers, type, handler); + } + return this; // for chaining + }; + EmitterMixin.prototype.trigger = function (type) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + this.triggerWith(type, this, args); + return this; // for chaining + }; + EmitterMixin.prototype.triggerWith = function (type, context, args) { + if (this._handlers) { + applyAll(this._handlers[type], context, args); + } + if (this._oneHandlers) { + applyAll(this._oneHandlers[type], context, args); + delete this._oneHandlers[type]; // will never fire again + } + return this; // for chaining + }; + EmitterMixin.prototype.hasHandlers = function (type) { + return (this._handlers && this._handlers[type] && this._handlers[type].length) || + (this._oneHandlers && this._oneHandlers[type] && this._oneHandlers[type].length); + }; + return EmitterMixin; +}(Mixin)); +function addToHash(hash, type, handler) { + (hash[type] || (hash[type] = [])) + .push(handler); +} +function removeFromHash(hash, type, handler) { + if (handler) { + if (hash[type]) { + hash[type] = hash[type].filter(function (func) { + return func !== handler; + }); + } + } + else { + delete hash[type]; // remove all handler funcs for this type + } +} + +/* +Records offset information for a set of elements, relative to an origin element. +Can record the left/right OR the top/bottom OR both. +Provides methods for querying the cache by position. +*/ +var PositionCache = /** @class */ (function () { + function PositionCache(originEl, els, isHorizontal, isVertical) { + this.originEl = originEl; + this.els = els; + this.isHorizontal = isHorizontal; + this.isVertical = isVertical; + } + // Queries the els for coordinates and stores them. + // Call this method before using and of the get* methods below. + PositionCache.prototype.build = function () { + var originEl = this.originEl; + var originClientRect = this.originClientRect = + originEl.getBoundingClientRect(); // relative to viewport top-left + if (this.isHorizontal) { + this.buildElHorizontals(originClientRect.left); + } + if (this.isVertical) { + this.buildElVerticals(originClientRect.top); + } + }; + // Populates the left/right internal coordinate arrays + PositionCache.prototype.buildElHorizontals = function (originClientLeft) { + var lefts = []; + var rights = []; + for (var _i = 0, _a = this.els; _i < _a.length; _i++) { + var el = _a[_i]; + var rect = el.getBoundingClientRect(); + lefts.push(rect.left - originClientLeft); + rights.push(rect.right - originClientLeft); + } + this.lefts = lefts; + this.rights = rights; + }; + // Populates the top/bottom internal coordinate arrays + PositionCache.prototype.buildElVerticals = function (originClientTop) { + var tops = []; + var bottoms = []; + for (var _i = 0, _a = this.els; _i < _a.length; _i++) { + var el = _a[_i]; + var rect = el.getBoundingClientRect(); + tops.push(rect.top - originClientTop); + bottoms.push(rect.bottom - originClientTop); + } + this.tops = tops; + this.bottoms = bottoms; + }; + // Given a left offset (from document left), returns the index of the el that it horizontally intersects. + // If no intersection is made, returns undefined. + PositionCache.prototype.leftToIndex = function (leftPosition) { + var lefts = this.lefts; + var rights = this.rights; + var len = lefts.length; + var i; + for (i = 0; i < len; i++) { + if (leftPosition >= lefts[i] && leftPosition < rights[i]) { + return i; + } + } + }; + // Given a top offset (from document top), returns the index of the el that it vertically intersects. + // If no intersection is made, returns undefined. + PositionCache.prototype.topToIndex = function (topPosition) { + var tops = this.tops; + var bottoms = this.bottoms; + var len = tops.length; + var i; + for (i = 0; i < len; i++) { + if (topPosition >= tops[i] && topPosition < bottoms[i]) { + return i; + } + } + }; + // Gets the width of the element at the given index + PositionCache.prototype.getWidth = function (leftIndex) { + return this.rights[leftIndex] - this.lefts[leftIndex]; + }; + // Gets the height of the element at the given index + PositionCache.prototype.getHeight = function (topIndex) { + return this.bottoms[topIndex] - this.tops[topIndex]; + }; + return PositionCache; +}()); + +/* +An object for getting/setting scroll-related information for an element. +Internally, this is done very differently for window versus DOM element, +so this object serves as a common interface. +*/ +var ScrollController = /** @class */ (function () { + function ScrollController() { + } + ScrollController.prototype.getMaxScrollTop = function () { + return this.getScrollHeight() - this.getClientHeight(); + }; + ScrollController.prototype.getMaxScrollLeft = function () { + return this.getScrollWidth() - this.getClientWidth(); + }; + ScrollController.prototype.canScrollVertically = function () { + return this.getMaxScrollTop() > 0; + }; + ScrollController.prototype.canScrollHorizontally = function () { + return this.getMaxScrollLeft() > 0; + }; + ScrollController.prototype.canScrollUp = function () { + return this.getScrollTop() > 0; + }; + ScrollController.prototype.canScrollDown = function () { + return this.getScrollTop() < this.getMaxScrollTop(); + }; + ScrollController.prototype.canScrollLeft = function () { + return this.getScrollLeft() > 0; + }; + ScrollController.prototype.canScrollRight = function () { + return this.getScrollLeft() < this.getMaxScrollLeft(); + }; + return ScrollController; +}()); +var ElementScrollController = /** @class */ (function (_super) { + __extends(ElementScrollController, _super); + function ElementScrollController(el) { + var _this = _super.call(this) || this; + _this.el = el; + return _this; + } + ElementScrollController.prototype.getScrollTop = function () { + return this.el.scrollTop; + }; + ElementScrollController.prototype.getScrollLeft = function () { + return this.el.scrollLeft; + }; + ElementScrollController.prototype.setScrollTop = function (top) { + this.el.scrollTop = top; + }; + ElementScrollController.prototype.setScrollLeft = function (left) { + this.el.scrollLeft = left; + }; + ElementScrollController.prototype.getScrollWidth = function () { + return this.el.scrollWidth; + }; + ElementScrollController.prototype.getScrollHeight = function () { + return this.el.scrollHeight; + }; + ElementScrollController.prototype.getClientHeight = function () { + return this.el.clientHeight; + }; + ElementScrollController.prototype.getClientWidth = function () { + return this.el.clientWidth; + }; + return ElementScrollController; +}(ScrollController)); +var WindowScrollController = /** @class */ (function (_super) { + __extends(WindowScrollController, _super); + function WindowScrollController() { + return _super !== null && _super.apply(this, arguments) || this; + } + WindowScrollController.prototype.getScrollTop = function () { + return window.pageYOffset; + }; + WindowScrollController.prototype.getScrollLeft = function () { + return window.pageXOffset; + }; + WindowScrollController.prototype.setScrollTop = function (n) { + window.scroll(window.pageXOffset, n); + }; + WindowScrollController.prototype.setScrollLeft = function (n) { + window.scroll(n, window.pageYOffset); + }; + WindowScrollController.prototype.getScrollWidth = function () { + return document.documentElement.scrollWidth; + }; + WindowScrollController.prototype.getScrollHeight = function () { + return document.documentElement.scrollHeight; + }; + WindowScrollController.prototype.getClientHeight = function () { + return document.documentElement.clientHeight; + }; + WindowScrollController.prototype.getClientWidth = function () { + return document.documentElement.clientWidth; + }; + return WindowScrollController; +}(ScrollController)); + +/* +Embodies a div that has potential scrollbars +*/ +var ScrollComponent = /** @class */ (function (_super) { + __extends(ScrollComponent, _super); + function ScrollComponent(overflowX, overflowY) { + var _this = _super.call(this, createElement('div', { + className: 'fc-scroller' + })) || this; + _this.overflowX = overflowX; + _this.overflowY = overflowY; + _this.applyOverflow(); + return _this; + } + // sets to natural height, unlocks overflow + ScrollComponent.prototype.clear = function () { + this.setHeight('auto'); + this.applyOverflow(); + }; + ScrollComponent.prototype.destroy = function () { + removeElement(this.el); + }; + // Overflow + // ----------------------------------------------------------------------------------------------------------------- + ScrollComponent.prototype.applyOverflow = function () { + applyStyle(this.el, { + overflowX: this.overflowX, + overflowY: this.overflowY + }); + }; + // Causes any 'auto' overflow values to resolves to 'scroll' or 'hidden'. + // Useful for preserving scrollbar widths regardless of future resizes. + // Can pass in scrollbarWidths for optimization. + ScrollComponent.prototype.lockOverflow = function (scrollbarWidths) { + var overflowX = this.overflowX; + var overflowY = this.overflowY; + scrollbarWidths = scrollbarWidths || this.getScrollbarWidths(); + if (overflowX === 'auto') { + overflowX = (scrollbarWidths.bottom || // horizontal scrollbars? + this.canScrollHorizontally() // OR scrolling pane with massless scrollbars? + ) ? 'scroll' : 'hidden'; + } + if (overflowY === 'auto') { + overflowY = (scrollbarWidths.left || scrollbarWidths.right || // horizontal scrollbars? + this.canScrollVertically() // OR scrolling pane with massless scrollbars? + ) ? 'scroll' : 'hidden'; + } + applyStyle(this.el, { overflowX: overflowX, overflowY: overflowY }); + }; + ScrollComponent.prototype.setHeight = function (height) { + applyStyleProp(this.el, 'height', height); + }; + ScrollComponent.prototype.getScrollbarWidths = function () { + var edges = computeEdges(this.el); + return { + left: edges.scrollbarLeft, + right: edges.scrollbarRight, + bottom: edges.scrollbarBottom + }; + }; + return ScrollComponent; +}(ElementScrollController)); + +var Theme = /** @class */ (function () { + function Theme(calendarOptions) { + this.calendarOptions = calendarOptions; + this.processIconOverride(); + } + Theme.prototype.processIconOverride = function () { + if (this.iconOverrideOption) { + this.setIconOverride(this.calendarOptions[this.iconOverrideOption]); + } + }; + Theme.prototype.setIconOverride = function (iconOverrideHash) { + var iconClassesCopy; + var buttonName; + if (typeof iconOverrideHash === 'object' && iconOverrideHash) { // non-null object + iconClassesCopy = __assign({}, this.iconClasses); + for (buttonName in iconOverrideHash) { + iconClassesCopy[buttonName] = this.applyIconOverridePrefix(iconOverrideHash[buttonName]); + } + this.iconClasses = iconClassesCopy; + } + else if (iconOverrideHash === false) { + this.iconClasses = {}; + } + }; + Theme.prototype.applyIconOverridePrefix = function (className) { + var prefix = this.iconOverridePrefix; + if (prefix && className.indexOf(prefix) !== 0) { // if not already present + className = prefix + className; + } + return className; + }; + Theme.prototype.getClass = function (key) { + return this.classes[key] || ''; + }; + Theme.prototype.getIconClass = function (buttonName) { + var className = this.iconClasses[buttonName]; + if (className) { + return this.baseIconClass + ' ' + className; + } + return ''; + }; + Theme.prototype.getCustomButtonIconClass = function (customButtonProps) { + var className; + if (this.iconOverrideCustomButtonOption) { + className = customButtonProps[this.iconOverrideCustomButtonOption]; + if (className) { + return this.baseIconClass + ' ' + this.applyIconOverridePrefix(className); + } + } + return ''; + }; + return Theme; +}()); +Theme.prototype.classes = {}; +Theme.prototype.iconClasses = {}; +Theme.prototype.baseIconClass = ''; +Theme.prototype.iconOverridePrefix = ''; + +var guid = 0; +var Component = /** @class */ (function () { + function Component(context, isView) { + // HACK to populate view at top of component instantiation call chain + if (isView) { + context.view = this; + } + this.uid = String(guid++); + this.context = context; + this.dateEnv = context.dateEnv; + this.theme = context.theme; + this.view = context.view; + this.calendar = context.calendar; + this.isRtl = this.opt('dir') === 'rtl'; + } + Component.addEqualityFuncs = function (newFuncs) { + this.prototype.equalityFuncs = __assign({}, this.prototype.equalityFuncs, newFuncs); + }; + Component.prototype.opt = function (name) { + return this.context.options[name]; + }; + Component.prototype.receiveProps = function (props) { + var _a = recycleProps(this.props || {}, props, this.equalityFuncs), anyChanges = _a.anyChanges, comboProps = _a.comboProps; + this.props = comboProps; + if (anyChanges) { + this.render(comboProps); + } + }; + Component.prototype.render = function (props) { + }; + // after destroy is called, this component won't ever be used again + Component.prototype.destroy = function () { + }; + return Component; +}()); +Component.prototype.equalityFuncs = {}; +/* +Reuses old values when equal. If anything is unequal, returns newProps as-is. +Great for PureComponent, but won't be feasible with React, so just eliminate and use React's DOM diffing. +*/ +function recycleProps(oldProps, newProps, equalityFuncs) { + var comboProps = {}; // some old, some new + var anyChanges = false; + for (var key in newProps) { + if (key in oldProps && (oldProps[key] === newProps[key] || + (equalityFuncs[key] && equalityFuncs[key](oldProps[key], newProps[key])))) { + // equal to old? use old prop + comboProps[key] = oldProps[key]; + } + else { + comboProps[key] = newProps[key]; + anyChanges = true; + } + } + for (var key in oldProps) { + if (!(key in newProps)) { + anyChanges = true; + break; + } + } + return { anyChanges: anyChanges, comboProps: comboProps }; +} + +/* +PURPOSES: +- hook up to fg, fill, and mirror renderers +- interface for dragging and hits +*/ +var DateComponent = /** @class */ (function (_super) { + __extends(DateComponent, _super); + function DateComponent(context, el, isView) { + var _this = _super.call(this, context, isView) || this; + _this.el = el; + return _this; + } + DateComponent.prototype.destroy = function () { + _super.prototype.destroy.call(this); + removeElement(this.el); + }; + // TODO: WHAT ABOUT (sourceSeg && sourceSeg.component.doesDragMirror) + // + // Event Drag-n-Drop Rendering (for both events and external elements) + // --------------------------------------------------------------------------------------------------------------- + /* + renderEventDragSegs(state: EventSegUiInteractionState) { + if (state) { + let { isEvent, segs, sourceSeg } = state + + if (this.eventRenderer) { + this.eventRenderer.hideByHash(state.affectedInstances) + } + + // if the user is dragging something that is considered an event with real event data, + // and this component likes to do drag mirrors OR the component where the seg came from + // likes to do drag mirrors, then render a drag mirror. + if (isEvent && (this.doesDragMirror || sourceSeg && sourceSeg.component.doesDragMirror)) { + if (this.mirrorRenderer) { + this.mirrorRenderer.renderSegs(segs, { isDragging: true, sourceSeg }) + } + } + + // if it would be impossible to render a drag mirror OR this component likes to render + // highlights, then render a highlight. + if (!isEvent || this.doesDragHighlight) { + if (this.fillRenderer) { + this.fillRenderer.renderSegs('highlight', segs) + } + } + } + } + */ + // Hit System + // ----------------------------------------------------------------------------------------------------------------- + DateComponent.prototype.buildPositionCaches = function () { + }; + DateComponent.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) { + return null; // this should be abstract + }; + // Validation + // ----------------------------------------------------------------------------------------------------------------- + DateComponent.prototype.isInteractionValid = function (interaction) { + var calendar = this.calendar; + var dateProfile = this.props.dateProfile; // HACK + var instances = interaction.mutatedEvents.instances; + if (dateProfile) { // HACK for DayTile + for (var instanceId in instances) { + if (!rangeContainsRange(dateProfile.validRange, instances[instanceId].range)) { + return false; + } + } + } + return isInteractionValid(interaction, calendar); + }; + DateComponent.prototype.isDateSelectionValid = function (selection) { + var dateProfile = this.props.dateProfile; // HACK + if (dateProfile && // HACK for DayTile + !rangeContainsRange(dateProfile.validRange, selection.range)) { + return false; + } + return isDateSelectionValid(selection, this.calendar); + }; + // Triggering + // ----------------------------------------------------------------------------------------------------------------- + // TODO: move to Calendar + DateComponent.prototype.publiclyTrigger = function (name, args) { + var calendar = this.calendar; + return calendar.publiclyTrigger(name, args); + }; + DateComponent.prototype.publiclyTriggerAfterSizing = function (name, args) { + var calendar = this.calendar; + return calendar.publiclyTriggerAfterSizing(name, args); + }; + DateComponent.prototype.hasPublicHandlers = function (name) { + var calendar = this.calendar; + return calendar.hasPublicHandlers(name); + }; + DateComponent.prototype.triggerRenderedSegs = function (segs, isMirrors) { + var calendar = this.calendar; + if (this.hasPublicHandlers('eventPositioned')) { + for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { + var seg = segs_1[_i]; + this.publiclyTriggerAfterSizing('eventPositioned', [ + { + event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance), + isMirror: isMirrors, + isStart: seg.isStart, + isEnd: seg.isEnd, + el: seg.el, + view: this // safe to cast because this method is only called on context.view + } + ]); + } + } + if (!calendar.state.loadingLevel) { // avoid initial empty state while pending + calendar.afterSizingTriggers._eventsPositioned = [null]; // fire once + } + }; + DateComponent.prototype.triggerWillRemoveSegs = function (segs, isMirrors) { + var calendar = this.calendar; + for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { + var seg = segs_2[_i]; + calendar.trigger('eventElRemove', seg.el); + } + if (this.hasPublicHandlers('eventDestroy')) { + for (var _a = 0, segs_3 = segs; _a < segs_3.length; _a++) { + var seg = segs_3[_a]; + this.publiclyTrigger('eventDestroy', [ + { + event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance), + isMirror: isMirrors, + el: seg.el, + view: this // safe to cast because this method is only called on context.view + } + ]); + } + } + }; + // Pointer Interaction Utils + // ----------------------------------------------------------------------------------------------------------------- + DateComponent.prototype.isValidSegDownEl = function (el) { + return !this.props.eventDrag && // HACK + !this.props.eventResize && // HACK + !elementClosest(el, '.fc-mirror') && + (this.isPopover() || !this.isInPopover(el)); + // ^above line ensures we don't detect a seg interaction within a nested component. + // it's a HACK because it only supports a popover as the nested component. + }; + DateComponent.prototype.isValidDateDownEl = function (el) { + var segEl = elementClosest(el, this.fgSegSelector); + return (!segEl || segEl.classList.contains('fc-mirror')) && + !elementClosest(el, '.fc-more') && // a "more.." link + !elementClosest(el, 'a[data-goto]') && // a clickable nav link + !this.isInPopover(el); + }; + DateComponent.prototype.isPopover = function () { + return this.el.classList.contains('fc-popover'); + }; + DateComponent.prototype.isInPopover = function (el) { + return Boolean(elementClosest(el, '.fc-popover')); + }; + return DateComponent; +}(Component)); +DateComponent.prototype.fgSegSelector = '.fc-event-container > *'; +DateComponent.prototype.bgSegSelector = '.fc-bgevent:not(.fc-nonbusiness)'; + +var uid$1 = 0; +function createPlugin(input) { + return { + id: String(uid$1++), + deps: input.deps || [], + reducers: input.reducers || [], + eventDefParsers: input.eventDefParsers || [], + isDraggableTransformers: input.isDraggableTransformers || [], + eventDragMutationMassagers: input.eventDragMutationMassagers || [], + eventDefMutationAppliers: input.eventDefMutationAppliers || [], + dateSelectionTransformers: input.dateSelectionTransformers || [], + datePointTransforms: input.datePointTransforms || [], + dateSpanTransforms: input.dateSpanTransforms || [], + views: input.views || {}, + viewPropsTransformers: input.viewPropsTransformers || [], + isPropsValid: input.isPropsValid || null, + externalDefTransforms: input.externalDefTransforms || [], + eventResizeJoinTransforms: input.eventResizeJoinTransforms || [], + viewContainerModifiers: input.viewContainerModifiers || [], + eventDropTransformers: input.eventDropTransformers || [], + componentInteractions: input.componentInteractions || [], + calendarInteractions: input.calendarInteractions || [], + themeClasses: input.themeClasses || {}, + eventSourceDefs: input.eventSourceDefs || [], + cmdFormatter: input.cmdFormatter, + recurringTypes: input.recurringTypes || [], + namedTimeZonedImpl: input.namedTimeZonedImpl, + defaultView: input.defaultView || '', + elementDraggingImpl: input.elementDraggingImpl, + optionChangeHandlers: input.optionChangeHandlers || {} + }; +} +var PluginSystem = /** @class */ (function () { + function PluginSystem() { + this.hooks = { + reducers: [], + eventDefParsers: [], + isDraggableTransformers: [], + eventDragMutationMassagers: [], + eventDefMutationAppliers: [], + dateSelectionTransformers: [], + datePointTransforms: [], + dateSpanTransforms: [], + views: {}, + viewPropsTransformers: [], + isPropsValid: null, + externalDefTransforms: [], + eventResizeJoinTransforms: [], + viewContainerModifiers: [], + eventDropTransformers: [], + componentInteractions: [], + calendarInteractions: [], + themeClasses: {}, + eventSourceDefs: [], + cmdFormatter: null, + recurringTypes: [], + namedTimeZonedImpl: null, + defaultView: '', + elementDraggingImpl: null, + optionChangeHandlers: {} + }; + this.addedHash = {}; + } + PluginSystem.prototype.add = function (plugin) { + if (!this.addedHash[plugin.id]) { + this.addedHash[plugin.id] = true; + for (var _i = 0, _a = plugin.deps; _i < _a.length; _i++) { + var dep = _a[_i]; + this.add(dep); + } + this.hooks = combineHooks(this.hooks, plugin); + } + }; + return PluginSystem; +}()); +function combineHooks(hooks0, hooks1) { + return { + reducers: hooks0.reducers.concat(hooks1.reducers), + eventDefParsers: hooks0.eventDefParsers.concat(hooks1.eventDefParsers), + isDraggableTransformers: hooks0.isDraggableTransformers.concat(hooks1.isDraggableTransformers), + eventDragMutationMassagers: hooks0.eventDragMutationMassagers.concat(hooks1.eventDragMutationMassagers), + eventDefMutationAppliers: hooks0.eventDefMutationAppliers.concat(hooks1.eventDefMutationAppliers), + dateSelectionTransformers: hooks0.dateSelectionTransformers.concat(hooks1.dateSelectionTransformers), + datePointTransforms: hooks0.datePointTransforms.concat(hooks1.datePointTransforms), + dateSpanTransforms: hooks0.dateSpanTransforms.concat(hooks1.dateSpanTransforms), + views: __assign({}, hooks0.views, hooks1.views), + viewPropsTransformers: hooks0.viewPropsTransformers.concat(hooks1.viewPropsTransformers), + isPropsValid: hooks1.isPropsValid || hooks0.isPropsValid, + externalDefTransforms: hooks0.externalDefTransforms.concat(hooks1.externalDefTransforms), + eventResizeJoinTransforms: hooks0.eventResizeJoinTransforms.concat(hooks1.eventResizeJoinTransforms), + viewContainerModifiers: hooks0.viewContainerModifiers.concat(hooks1.viewContainerModifiers), + eventDropTransformers: hooks0.eventDropTransformers.concat(hooks1.eventDropTransformers), + calendarInteractions: hooks0.calendarInteractions.concat(hooks1.calendarInteractions), + componentInteractions: hooks0.componentInteractions.concat(hooks1.componentInteractions), + themeClasses: __assign({}, hooks0.themeClasses, hooks1.themeClasses), + eventSourceDefs: hooks0.eventSourceDefs.concat(hooks1.eventSourceDefs), + cmdFormatter: hooks1.cmdFormatter || hooks0.cmdFormatter, + recurringTypes: hooks0.recurringTypes.concat(hooks1.recurringTypes), + namedTimeZonedImpl: hooks1.namedTimeZonedImpl || hooks0.namedTimeZonedImpl, + defaultView: hooks0.defaultView || hooks1.defaultView, + elementDraggingImpl: hooks0.elementDraggingImpl || hooks1.elementDraggingImpl, + optionChangeHandlers: __assign({}, hooks0.optionChangeHandlers, hooks1.optionChangeHandlers) + }; +} + +var eventSourceDef = { + ignoreRange: true, + parseMeta: function (raw) { + if (Array.isArray(raw)) { // short form + return raw; + } + else if (Array.isArray(raw.events)) { + return raw.events; + } + return null; + }, + fetch: function (arg, success) { + success({ + rawEvents: arg.eventSource.meta + }); + } +}; +var ArrayEventSourcePlugin = createPlugin({ + eventSourceDefs: [eventSourceDef] +}); + +var eventSourceDef$1 = { + parseMeta: function (raw) { + if (typeof raw === 'function') { // short form + return raw; + } + else if (typeof raw.events === 'function') { + return raw.events; + } + return null; + }, + fetch: function (arg, success, failure) { + var dateEnv = arg.calendar.dateEnv; + var func = arg.eventSource.meta; + unpromisify(func.bind(null, { + start: dateEnv.toDate(arg.range.start), + end: dateEnv.toDate(arg.range.end), + startStr: dateEnv.formatIso(arg.range.start), + endStr: dateEnv.formatIso(arg.range.end), + timeZone: dateEnv.timeZone + }), function (rawEvents) { + success({ rawEvents: rawEvents }); // needs an object response + }, failure // send errorObj directly to failure callback + ); + } +}; +var FuncEventSourcePlugin = createPlugin({ + eventSourceDefs: [eventSourceDef$1] +}); + +function requestJson(method, url, params, successCallback, failureCallback) { + method = method.toUpperCase(); + var body = null; + if (method === 'GET') { + url = injectQueryStringParams(url, params); + } + else { + body = encodeParams(params); + } + var xhr = new XMLHttpRequest(); + xhr.open(method, url, true); + if (method !== 'GET') { + xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + } + xhr.onload = function () { + if (xhr.status >= 200 && xhr.status < 400) { + try { + var res = JSON.parse(xhr.responseText); + successCallback(res, xhr); + } + catch (err) { + failureCallback('Failure parsing JSON', xhr); + } + } + else { + failureCallback('Request failed', xhr); + } + }; + xhr.onerror = function () { + failureCallback('Request failed', xhr); + }; + xhr.send(body); +} +function injectQueryStringParams(url, params) { + return url + + (url.indexOf('?') === -1 ? '?' : '&') + + encodeParams(params); +} +function encodeParams(params) { + var parts = []; + for (var key in params) { + parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(params[key])); + } + return parts.join('&'); +} + +var eventSourceDef$2 = { + parseMeta: function (raw) { + if (typeof raw === 'string') { // short form + raw = { url: raw }; + } + else if (!raw || typeof raw !== 'object' || !raw.url) { + return null; + } + return { + url: raw.url, + method: (raw.method || 'GET').toUpperCase(), + extraParams: raw.extraParams, + startParam: raw.startParam, + endParam: raw.endParam, + timeZoneParam: raw.timeZoneParam + }; + }, + fetch: function (arg, success, failure) { + var meta = arg.eventSource.meta; + var requestParams = buildRequestParams(meta, arg.range, arg.calendar); + requestJson(meta.method, meta.url, requestParams, function (rawEvents, xhr) { + success({ rawEvents: rawEvents, xhr: xhr }); + }, function (errorMessage, xhr) { + failure({ message: errorMessage, xhr: xhr }); + }); + } +}; +var JsonFeedEventSourcePlugin = createPlugin({ + eventSourceDefs: [eventSourceDef$2] +}); +function buildRequestParams(meta, range, calendar) { + var dateEnv = calendar.dateEnv; + var startParam; + var endParam; + var timeZoneParam; + var customRequestParams; + var params = {}; + startParam = meta.startParam; + if (startParam == null) { + startParam = calendar.opt('startParam'); + } + endParam = meta.endParam; + if (endParam == null) { + endParam = calendar.opt('endParam'); + } + timeZoneParam = meta.timeZoneParam; + if (timeZoneParam == null) { + timeZoneParam = calendar.opt('timeZoneParam'); + } + // retrieve any outbound GET/POST data from the options + if (typeof meta.extraParams === 'function') { + // supplied as a function that returns a key/value object + customRequestParams = meta.extraParams(); + } + else { + // probably supplied as a straight key/value object + customRequestParams = meta.extraParams || {}; + } + __assign(params, customRequestParams); + params[startParam] = dateEnv.formatIso(range.start); + params[endParam] = dateEnv.formatIso(range.end); + if (dateEnv.timeZone !== 'local') { + params[timeZoneParam] = dateEnv.timeZone; + } + return params; +} + +var recurring = { + parse: function (rawEvent, leftoverProps, dateEnv) { + var createMarker = dateEnv.createMarker.bind(dateEnv); + var processors = { + daysOfWeek: null, + startTime: createDuration, + endTime: createDuration, + startRecur: createMarker, + endRecur: createMarker + }; + var props = refineProps(rawEvent, processors, {}, leftoverProps); + var anyValid = false; + for (var propName in props) { + if (props[propName] != null) { + anyValid = true; + break; + } + } + if (anyValid) { + var duration = null; + if ('duration' in leftoverProps) { + duration = createDuration(leftoverProps.duration); + delete leftoverProps.duration; + } + if (!duration && props.startTime && props.endTime) { + duration = subtractDurations(props.endTime, props.startTime); + } + return { + allDayGuess: Boolean(!props.startTime && !props.endTime), + duration: duration, + typeData: props // doesn't need endTime anymore but oh well + }; + } + return null; + }, + expand: function (typeData, framingRange, dateEnv) { + var clippedFramingRange = intersectRanges(framingRange, { start: typeData.startRecur, end: typeData.endRecur }); + if (clippedFramingRange) { + return expandRanges(typeData.daysOfWeek, typeData.startTime, clippedFramingRange, dateEnv); + } + else { + return []; + } + } +}; +var SimpleRecurrencePlugin = createPlugin({ + recurringTypes: [recurring] +}); +function expandRanges(daysOfWeek, startTime, framingRange, dateEnv) { + var dowHash = daysOfWeek ? arrayToHash(daysOfWeek) : null; + var dayMarker = startOfDay(framingRange.start); + var endMarker = framingRange.end; + var instanceStarts = []; + while (dayMarker < endMarker) { + var instanceStart + // if everyday, or this particular day-of-week + = void 0; + // if everyday, or this particular day-of-week + if (!dowHash || dowHash[dayMarker.getUTCDay()]) { + if (startTime) { + instanceStart = dateEnv.add(dayMarker, startTime); + } + else { + instanceStart = dayMarker; + } + instanceStarts.push(instanceStart); + } + dayMarker = addDays(dayMarker, 1); + } + return instanceStarts; +} + +var DefaultOptionChangeHandlers = createPlugin({ + optionChangeHandlers: { + events: function (events, calendar, deepEqual) { + handleEventSources([events], calendar, deepEqual); + }, + eventSources: handleEventSources, + plugins: handlePlugins + } +}); +function handleEventSources(inputs, calendar, deepEqual) { + var unfoundSources = hashValuesToArray(calendar.state.eventSources); + var newInputs = []; + for (var _i = 0, inputs_1 = inputs; _i < inputs_1.length; _i++) { + var input = inputs_1[_i]; + var inputFound = false; + for (var i = 0; i < unfoundSources.length; i++) { + if (deepEqual(unfoundSources[i]._raw, input)) { + unfoundSources.splice(i, 1); // delete + inputFound = true; + break; + } + } + if (!inputFound) { + newInputs.push(input); + } + } + for (var _a = 0, unfoundSources_1 = unfoundSources; _a < unfoundSources_1.length; _a++) { + var unfoundSource = unfoundSources_1[_a]; + calendar.dispatch({ + type: 'REMOVE_EVENT_SOURCE', + sourceId: unfoundSource.sourceId + }); + } + for (var _b = 0, newInputs_1 = newInputs; _b < newInputs_1.length; _b++) { + var newInput = newInputs_1[_b]; + calendar.addEventSource(newInput); + } +} +// shortcoming: won't remove plugins +function handlePlugins(inputs, calendar) { + calendar.addPluginInputs(inputs); // will gracefully handle duplicates +} + +var config = {}; // TODO: make these options +var globalDefaults = { + defaultRangeSeparator: ' - ', + titleRangeSeparator: ' \u2013 ', + defaultTimedEventDuration: '01:00:00', + defaultAllDayEventDuration: { day: 1 }, + forceEventDuration: false, + nextDayThreshold: '00:00:00', + // display + columnHeader: true, + defaultView: '', + aspectRatio: 1.35, + header: { + left: 'title', + center: '', + right: 'today prev,next' + }, + weekends: true, + weekNumbers: false, + weekNumberCalculation: 'local', + editable: false, + // nowIndicator: false, + scrollTime: '06:00:00', + minTime: '00:00:00', + maxTime: '24:00:00', + showNonCurrentDates: true, + // event ajax + lazyFetching: true, + startParam: 'start', + endParam: 'end', + timeZoneParam: 'timeZone', + timeZone: 'local', + // allDayDefault: undefined, + // locale + locales: [], + locale: '', + // dir: will get this from the default locale + // buttonIcons: null, + // allows setting a min-height to the event segment to prevent short events overlapping each other + timeGridEventMinHeight: 0, + themeSystem: 'standard', + // eventResizableFromStart: false, + dragRevertDuration: 500, + dragScroll: true, + allDayMaintainDuration: false, + // selectable: false, + unselectAuto: true, + // selectMinDistance: 0, + dropAccept: '*', + eventOrder: 'start,-duration,allDay,title', + // ^ if start tie, longer events go before shorter. final tie-breaker is title text + // rerenderDelay: null, + eventLimit: false, + eventLimitClick: 'popover', + dayPopoverFormat: { month: 'long', day: 'numeric', year: 'numeric' }, + handleWindowResize: true, + windowResizeDelay: 100, + longPressDelay: 1000, + eventDragMinDistance: 5 // only applies to mouse +}; +var rtlDefaults = { + header: { + left: 'next,prev today', + center: '', + right: 'title' + }, + buttonIcons: { + // TODO: make RTL support the responibility of the theme + prev: 'fc-icon-chevron-right', + next: 'fc-icon-chevron-left', + prevYear: 'fc-icon-chevrons-right', + nextYear: 'fc-icon-chevrons-left' + } +}; +var complexOptions = [ + 'header', + 'footer', + 'buttonText', + 'buttonIcons' +]; +// Merges an array of option objects into a single object +function mergeOptions(optionObjs) { + return mergeProps(optionObjs, complexOptions); +} +// TODO: move this stuff to a "plugin"-related file... +var INTERNAL_PLUGINS = [ + ArrayEventSourcePlugin, + FuncEventSourcePlugin, + JsonFeedEventSourcePlugin, + SimpleRecurrencePlugin, + DefaultOptionChangeHandlers +]; +function refinePluginDefs(pluginInputs) { + var plugins = []; + for (var _i = 0, pluginInputs_1 = pluginInputs; _i < pluginInputs_1.length; _i++) { + var pluginInput = pluginInputs_1[_i]; + if (typeof pluginInput === 'string') { + var globalName = 'FullCalendar' + capitaliseFirstLetter(pluginInput); + if (!window[globalName]) { + console.warn('Plugin file not loaded for ' + pluginInput); + } + else { + plugins.push(window[globalName].default); // is an ES6 module + } + } + else { + plugins.push(pluginInput); + } + } + return INTERNAL_PLUGINS.concat(plugins); +} + +var RAW_EN_LOCALE = { + code: 'en', + week: { + dow: 0, + doy: 4 // 4 days need to be within the year to be considered the first week + }, + dir: 'ltr', + buttonText: { + prev: 'prev', + next: 'next', + prevYear: 'prev year', + nextYear: 'next year', + year: 'year', + today: 'today', + month: 'month', + week: 'week', + day: 'day', + list: 'list' + }, + weekLabel: 'W', + allDayText: 'all-day', + eventLimitText: 'more', + noEventsMessage: 'No events to display' +}; +function parseRawLocales(explicitRawLocales) { + var defaultCode = explicitRawLocales.length > 0 ? explicitRawLocales[0].code : 'en'; + var globalArray = window['FullCalendarLocalesAll'] || []; // from locales-all.js + var globalObject = window['FullCalendarLocales'] || {}; // from locales/*.js. keys are meaningless + var allRawLocales = globalArray.concat(// globalArray is low prio + hashValuesToArray(globalObject), // medium prio + explicitRawLocales // highest prio + ); + var rawLocaleMap = { + en: RAW_EN_LOCALE // necessary? + }; + for (var _i = 0, allRawLocales_1 = allRawLocales; _i < allRawLocales_1.length; _i++) { + var rawLocale = allRawLocales_1[_i]; + rawLocaleMap[rawLocale.code] = rawLocale; + } + return { + map: rawLocaleMap, + defaultCode: defaultCode + }; +} +function buildLocale(inputSingular, available) { + if (typeof inputSingular === 'object' && !Array.isArray(inputSingular)) { + return parseLocale(inputSingular.code, [inputSingular.code], inputSingular); + } + else { + return queryLocale(inputSingular, available); + } +} +function queryLocale(codeArg, available) { + var codes = [].concat(codeArg || []); // will convert to array + var raw = queryRawLocale(codes, available) || RAW_EN_LOCALE; + return parseLocale(codeArg, codes, raw); +} +function queryRawLocale(codes, available) { + for (var i = 0; i < codes.length; i++) { + var parts = codes[i].toLocaleLowerCase().split('-'); + for (var j = parts.length; j > 0; j--) { + var simpleId = parts.slice(0, j).join('-'); + if (available[simpleId]) { + return available[simpleId]; + } + } + } + return null; +} +function parseLocale(codeArg, codes, raw) { + var merged = mergeProps([RAW_EN_LOCALE, raw], ['buttonText']); + delete merged.code; // don't want this part of the options + var week = merged.week; + delete merged.week; + return { + codeArg: codeArg, + codes: codes, + week: week, + simpleNumberFormat: new Intl.NumberFormat(codeArg), + options: merged + }; +} + +var OptionsManager = /** @class */ (function () { + function OptionsManager(overrides) { + this.overrides = __assign({}, overrides); // make a copy + this.dynamicOverrides = {}; + this.compute(); + } + OptionsManager.prototype.mutate = function (updates, removals, isDynamic) { + var overrideHash = isDynamic ? this.dynamicOverrides : this.overrides; + __assign(overrideHash, updates); + for (var _i = 0, removals_1 = removals; _i < removals_1.length; _i++) { + var propName = removals_1[_i]; + delete overrideHash[propName]; + } + this.compute(); + }; + // Computes the flattened options hash for the calendar and assigns to `this.options`. + // Assumes this.overrides and this.dynamicOverrides have already been initialized. + OptionsManager.prototype.compute = function () { + // TODO: not a very efficient system + var locales = firstDefined(// explicit locale option given? + this.dynamicOverrides.locales, this.overrides.locales, globalDefaults.locales); + var locale = firstDefined(// explicit locales option given? + this.dynamicOverrides.locale, this.overrides.locale, globalDefaults.locale); + var available = parseRawLocales(locales); + var localeDefaults = buildLocale(locale || available.defaultCode, available.map).options; + var dir = firstDefined(// based on options computed so far, is direction RTL? + this.dynamicOverrides.dir, this.overrides.dir, localeDefaults.dir); + var dirDefaults = dir === 'rtl' ? rtlDefaults : {}; + this.dirDefaults = dirDefaults; + this.localeDefaults = localeDefaults; + this.computed = mergeOptions([ + globalDefaults, + dirDefaults, + localeDefaults, + this.overrides, + this.dynamicOverrides + ]); + }; + return OptionsManager; +}()); + +var calendarSystemClassMap = {}; +function registerCalendarSystem(name, theClass) { + calendarSystemClassMap[name] = theClass; +} +function createCalendarSystem(name) { + return new calendarSystemClassMap[name](); +} +var GregorianCalendarSystem = /** @class */ (function () { + function GregorianCalendarSystem() { + } + GregorianCalendarSystem.prototype.getMarkerYear = function (d) { + return d.getUTCFullYear(); + }; + GregorianCalendarSystem.prototype.getMarkerMonth = function (d) { + return d.getUTCMonth(); + }; + GregorianCalendarSystem.prototype.getMarkerDay = function (d) { + return d.getUTCDate(); + }; + GregorianCalendarSystem.prototype.arrayToMarker = function (arr) { + return arrayToUtcDate(arr); + }; + GregorianCalendarSystem.prototype.markerToArray = function (marker) { + return dateToUtcArray(marker); + }; + return GregorianCalendarSystem; +}()); +registerCalendarSystem('gregory', GregorianCalendarSystem); + +var ISO_RE = /^\s*(\d{4})(-(\d{2})(-(\d{2})([T ](\d{2}):(\d{2})(:(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/; +function parse(str) { + var m = ISO_RE.exec(str); + if (m) { + var marker = new Date(Date.UTC(Number(m[1]), m[3] ? Number(m[3]) - 1 : 0, Number(m[5] || 1), Number(m[7] || 0), Number(m[8] || 0), Number(m[10] || 0), m[12] ? Number('0.' + m[12]) * 1000 : 0)); + if (isValidDate(marker)) { + var timeZoneOffset = null; + if (m[13]) { + timeZoneOffset = (m[15] === '-' ? -1 : 1) * (Number(m[16] || 0) * 60 + + Number(m[18] || 0)); + } + return { + marker: marker, + isTimeUnspecified: !m[6], + timeZoneOffset: timeZoneOffset + }; + } + } + return null; +} + +var DateEnv = /** @class */ (function () { + function DateEnv(settings) { + var timeZone = this.timeZone = settings.timeZone; + var isNamedTimeZone = timeZone !== 'local' && timeZone !== 'UTC'; + if (settings.namedTimeZoneImpl && isNamedTimeZone) { + this.namedTimeZoneImpl = new settings.namedTimeZoneImpl(timeZone); + } + this.canComputeOffset = Boolean(!isNamedTimeZone || this.namedTimeZoneImpl); + this.calendarSystem = createCalendarSystem(settings.calendarSystem); + this.locale = settings.locale; + this.weekDow = settings.locale.week.dow; + this.weekDoy = settings.locale.week.doy; + if (settings.weekNumberCalculation === 'ISO') { + this.weekDow = 1; + this.weekDoy = 4; + } + if (typeof settings.firstDay === 'number') { + this.weekDow = settings.firstDay; + } + if (typeof settings.weekNumberCalculation === 'function') { + this.weekNumberFunc = settings.weekNumberCalculation; + } + this.weekLabel = settings.weekLabel != null ? settings.weekLabel : settings.locale.options.weekLabel; + this.cmdFormatter = settings.cmdFormatter; + } + // Creating / Parsing + DateEnv.prototype.createMarker = function (input) { + var meta = this.createMarkerMeta(input); + if (meta === null) { + return null; + } + return meta.marker; + }; + DateEnv.prototype.createNowMarker = function () { + if (this.canComputeOffset) { + return this.timestampToMarker(new Date().valueOf()); + } + else { + // if we can't compute the current date val for a timezone, + // better to give the current local date vals than UTC + return arrayToUtcDate(dateToLocalArray(new Date())); + } + }; + DateEnv.prototype.createMarkerMeta = function (input) { + if (typeof input === 'string') { + return this.parse(input); + } + var marker = null; + if (typeof input === 'number') { + marker = this.timestampToMarker(input); + } + else if (input instanceof Date) { + input = input.valueOf(); + if (!isNaN(input)) { + marker = this.timestampToMarker(input); + } + } + else if (Array.isArray(input)) { + marker = arrayToUtcDate(input); + } + if (marker === null || !isValidDate(marker)) { + return null; + } + return { marker: marker, isTimeUnspecified: false, forcedTzo: null }; + }; + DateEnv.prototype.parse = function (s) { + var parts = parse(s); + if (parts === null) { + return null; + } + var marker = parts.marker; + var forcedTzo = null; + if (parts.timeZoneOffset !== null) { + if (this.canComputeOffset) { + marker = this.timestampToMarker(marker.valueOf() - parts.timeZoneOffset * 60 * 1000); + } + else { + forcedTzo = parts.timeZoneOffset; + } + } + return { marker: marker, isTimeUnspecified: parts.isTimeUnspecified, forcedTzo: forcedTzo }; + }; + // Accessors + DateEnv.prototype.getYear = function (marker) { + return this.calendarSystem.getMarkerYear(marker); + }; + DateEnv.prototype.getMonth = function (marker) { + return this.calendarSystem.getMarkerMonth(marker); + }; + // Adding / Subtracting + DateEnv.prototype.add = function (marker, dur) { + var a = this.calendarSystem.markerToArray(marker); + a[0] += dur.years; + a[1] += dur.months; + a[2] += dur.days; + a[6] += dur.milliseconds; + return this.calendarSystem.arrayToMarker(a); + }; + DateEnv.prototype.subtract = function (marker, dur) { + var a = this.calendarSystem.markerToArray(marker); + a[0] -= dur.years; + a[1] -= dur.months; + a[2] -= dur.days; + a[6] -= dur.milliseconds; + return this.calendarSystem.arrayToMarker(a); + }; + DateEnv.prototype.addYears = function (marker, n) { + var a = this.calendarSystem.markerToArray(marker); + a[0] += n; + return this.calendarSystem.arrayToMarker(a); + }; + DateEnv.prototype.addMonths = function (marker, n) { + var a = this.calendarSystem.markerToArray(marker); + a[1] += n; + return this.calendarSystem.arrayToMarker(a); + }; + // Diffing Whole Units + DateEnv.prototype.diffWholeYears = function (m0, m1) { + var calendarSystem = this.calendarSystem; + if (timeAsMs(m0) === timeAsMs(m1) && + calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1) && + calendarSystem.getMarkerMonth(m0) === calendarSystem.getMarkerMonth(m1)) { + return calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0); + } + return null; + }; + DateEnv.prototype.diffWholeMonths = function (m0, m1) { + var calendarSystem = this.calendarSystem; + if (timeAsMs(m0) === timeAsMs(m1) && + calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1)) { + return (calendarSystem.getMarkerMonth(m1) - calendarSystem.getMarkerMonth(m0)) + + (calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0)) * 12; + } + return null; + }; + // Range / Duration + DateEnv.prototype.greatestWholeUnit = function (m0, m1) { + var n = this.diffWholeYears(m0, m1); + if (n !== null) { + return { unit: 'year', value: n }; + } + n = this.diffWholeMonths(m0, m1); + if (n !== null) { + return { unit: 'month', value: n }; + } + n = diffWholeWeeks(m0, m1); + if (n !== null) { + return { unit: 'week', value: n }; + } + n = diffWholeDays(m0, m1); + if (n !== null) { + return { unit: 'day', value: n }; + } + n = diffHours(m0, m1); + if (isInt(n)) { + return { unit: 'hour', value: n }; + } + n = diffMinutes(m0, m1); + if (isInt(n)) { + return { unit: 'minute', value: n }; + } + n = diffSeconds(m0, m1); + if (isInt(n)) { + return { unit: 'second', value: n }; + } + return { unit: 'millisecond', value: m1.valueOf() - m0.valueOf() }; + }; + DateEnv.prototype.countDurationsBetween = function (m0, m1, d) { + // TODO: can use greatestWholeUnit + var diff; + if (d.years) { + diff = this.diffWholeYears(m0, m1); + if (diff !== null) { + return diff / asRoughYears(d); + } + } + if (d.months) { + diff = this.diffWholeMonths(m0, m1); + if (diff !== null) { + return diff / asRoughMonths(d); + } + } + if (d.days) { + diff = diffWholeDays(m0, m1); + if (diff !== null) { + return diff / asRoughDays(d); + } + } + return (m1.valueOf() - m0.valueOf()) / asRoughMs(d); + }; + // Start-Of + DateEnv.prototype.startOf = function (m, unit) { + if (unit === 'year') { + return this.startOfYear(m); + } + else if (unit === 'month') { + return this.startOfMonth(m); + } + else if (unit === 'week') { + return this.startOfWeek(m); + } + else if (unit === 'day') { + return startOfDay(m); + } + else if (unit === 'hour') { + return startOfHour(m); + } + else if (unit === 'minute') { + return startOfMinute(m); + } + else if (unit === 'second') { + return startOfSecond(m); + } + }; + DateEnv.prototype.startOfYear = function (m) { + return this.calendarSystem.arrayToMarker([ + this.calendarSystem.getMarkerYear(m) + ]); + }; + DateEnv.prototype.startOfMonth = function (m) { + return this.calendarSystem.arrayToMarker([ + this.calendarSystem.getMarkerYear(m), + this.calendarSystem.getMarkerMonth(m) + ]); + }; + DateEnv.prototype.startOfWeek = function (m) { + return this.calendarSystem.arrayToMarker([ + this.calendarSystem.getMarkerYear(m), + this.calendarSystem.getMarkerMonth(m), + m.getUTCDate() - ((m.getUTCDay() - this.weekDow + 7) % 7) + ]); + }; + // Week Number + DateEnv.prototype.computeWeekNumber = function (marker) { + if (this.weekNumberFunc) { + return this.weekNumberFunc(this.toDate(marker)); + } + else { + return weekOfYear(marker, this.weekDow, this.weekDoy); + } + }; + // TODO: choke on timeZoneName: long + DateEnv.prototype.format = function (marker, formatter, dateOptions) { + if (dateOptions === void 0) { dateOptions = {}; } + return formatter.format({ + marker: marker, + timeZoneOffset: dateOptions.forcedTzo != null ? + dateOptions.forcedTzo : + this.offsetForMarker(marker) + }, this); + }; + DateEnv.prototype.formatRange = function (start, end, formatter, dateOptions) { + if (dateOptions === void 0) { dateOptions = {}; } + if (dateOptions.isEndExclusive) { + end = addMs(end, -1); + } + return formatter.formatRange({ + marker: start, + timeZoneOffset: dateOptions.forcedStartTzo != null ? + dateOptions.forcedStartTzo : + this.offsetForMarker(start) + }, { + marker: end, + timeZoneOffset: dateOptions.forcedEndTzo != null ? + dateOptions.forcedEndTzo : + this.offsetForMarker(end) + }, this); + }; + DateEnv.prototype.formatIso = function (marker, extraOptions) { + if (extraOptions === void 0) { extraOptions = {}; } + var timeZoneOffset = null; + if (!extraOptions.omitTimeZoneOffset) { + if (extraOptions.forcedTzo != null) { + timeZoneOffset = extraOptions.forcedTzo; + } + else { + timeZoneOffset = this.offsetForMarker(marker); + } + } + return buildIsoString(marker, timeZoneOffset, extraOptions.omitTime); + }; + // TimeZone + DateEnv.prototype.timestampToMarker = function (ms) { + if (this.timeZone === 'local') { + return arrayToUtcDate(dateToLocalArray(new Date(ms))); + } + else if (this.timeZone === 'UTC' || !this.namedTimeZoneImpl) { + return new Date(ms); + } + else { + return arrayToUtcDate(this.namedTimeZoneImpl.timestampToArray(ms)); + } + }; + DateEnv.prototype.offsetForMarker = function (m) { + if (this.timeZone === 'local') { + return -arrayToLocalDate(dateToUtcArray(m)).getTimezoneOffset(); // convert "inverse" offset to "normal" offset + } + else if (this.timeZone === 'UTC') { + return 0; + } + else if (this.namedTimeZoneImpl) { + return this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)); + } + return null; + }; + // Conversion + DateEnv.prototype.toDate = function (m, forcedTzo) { + if (this.timeZone === 'local') { + return arrayToLocalDate(dateToUtcArray(m)); + } + else if (this.timeZone === 'UTC') { + return new Date(m.valueOf()); // make sure it's a copy + } + else if (!this.namedTimeZoneImpl) { + return new Date(m.valueOf() - (forcedTzo || 0)); + } + else { + return new Date(m.valueOf() - + this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)) * 1000 * 60 // convert minutes -> ms + ); + } + }; + return DateEnv; +}()); + +var SIMPLE_SOURCE_PROPS = { + id: String, + allDayDefault: Boolean, + eventDataTransform: Function, + success: Function, + failure: Function +}; +var uid$2 = 0; +function doesSourceNeedRange(eventSource, calendar) { + var defs = calendar.pluginSystem.hooks.eventSourceDefs; + return !defs[eventSource.sourceDefId].ignoreRange; +} +function parseEventSource(raw, calendar) { + var defs = calendar.pluginSystem.hooks.eventSourceDefs; + for (var i = defs.length - 1; i >= 0; i--) { // later-added plugins take precedence + var def = defs[i]; + var meta = def.parseMeta(raw); + if (meta) { + var res = parseEventSourceProps(typeof raw === 'object' ? raw : {}, meta, i, calendar); + res._raw = raw; + return res; + } + } + return null; +} +function parseEventSourceProps(raw, meta, sourceDefId, calendar) { + var leftovers0 = {}; + var props = refineProps(raw, SIMPLE_SOURCE_PROPS, {}, leftovers0); + var leftovers1 = {}; + var ui = processUnscopedUiProps(leftovers0, calendar, leftovers1); + props.isFetching = false; + props.latestFetchId = ''; + props.fetchRange = null; + props.publicId = String(raw.id || ''); + props.sourceId = String(uid$2++); + props.sourceDefId = sourceDefId; + props.meta = meta; + props.ui = ui; + props.extendedProps = leftovers1; + return props; +} + +function reduceEventSources (eventSources, action, dateProfile, calendar) { + switch (action.type) { + case 'ADD_EVENT_SOURCES': // already parsed + return addSources(eventSources, action.sources, dateProfile ? dateProfile.activeRange : null, calendar); + case 'REMOVE_EVENT_SOURCE': + return removeSource(eventSources, action.sourceId); + case 'PREV': // TODO: how do we track all actions that affect dateProfile :( + case 'NEXT': + case 'SET_DATE': + case 'SET_VIEW_TYPE': + if (dateProfile) { + return fetchDirtySources(eventSources, dateProfile.activeRange, calendar); + } + else { + return eventSources; + } + case 'FETCH_EVENT_SOURCES': + case 'CHANGE_TIMEZONE': + return fetchSourcesByIds(eventSources, action.sourceIds ? + arrayToHash(action.sourceIds) : + excludeStaticSources(eventSources, calendar), dateProfile ? dateProfile.activeRange : null, calendar); + case 'RECEIVE_EVENTS': + case 'RECEIVE_EVENT_ERROR': + return receiveResponse(eventSources, action.sourceId, action.fetchId, action.fetchRange); + case 'REMOVE_ALL_EVENT_SOURCES': + return {}; + default: + return eventSources; + } +} +var uid$3 = 0; +function addSources(eventSourceHash, sources, fetchRange, calendar) { + var hash = {}; + for (var _i = 0, sources_1 = sources; _i < sources_1.length; _i++) { + var source = sources_1[_i]; + hash[source.sourceId] = source; + } + if (fetchRange) { + hash = fetchDirtySources(hash, fetchRange, calendar); + } + return __assign({}, eventSourceHash, hash); +} +function removeSource(eventSourceHash, sourceId) { + return filterHash(eventSourceHash, function (eventSource) { + return eventSource.sourceId !== sourceId; + }); +} +function fetchDirtySources(sourceHash, fetchRange, calendar) { + return fetchSourcesByIds(sourceHash, filterHash(sourceHash, function (eventSource) { + return isSourceDirty(eventSource, fetchRange, calendar); + }), fetchRange, calendar); +} +function isSourceDirty(eventSource, fetchRange, calendar) { + if (!doesSourceNeedRange(eventSource, calendar)) { + return !eventSource.latestFetchId; + } + else { + return !calendar.opt('lazyFetching') || + !eventSource.fetchRange || + fetchRange.start < eventSource.fetchRange.start || + fetchRange.end > eventSource.fetchRange.end; + } +} +function fetchSourcesByIds(prevSources, sourceIdHash, fetchRange, calendar) { + var nextSources = {}; + for (var sourceId in prevSources) { + var source = prevSources[sourceId]; + if (sourceIdHash[sourceId]) { + nextSources[sourceId] = fetchSource(source, fetchRange, calendar); + } + else { + nextSources[sourceId] = source; + } + } + return nextSources; +} +function fetchSource(eventSource, fetchRange, calendar) { + var sourceDef = calendar.pluginSystem.hooks.eventSourceDefs[eventSource.sourceDefId]; + var fetchId = String(uid$3++); + sourceDef.fetch({ + eventSource: eventSource, + calendar: calendar, + range: fetchRange + }, function (res) { + var rawEvents = res.rawEvents; + var calSuccess = calendar.opt('eventSourceSuccess'); + var calSuccessRes; + var sourceSuccessRes; + if (eventSource.success) { + sourceSuccessRes = eventSource.success(rawEvents, res.xhr); + } + if (calSuccess) { + calSuccessRes = calSuccess(rawEvents, res.xhr); + } + rawEvents = sourceSuccessRes || calSuccessRes || rawEvents; + calendar.dispatch({ + type: 'RECEIVE_EVENTS', + sourceId: eventSource.sourceId, + fetchId: fetchId, + fetchRange: fetchRange, + rawEvents: rawEvents + }); + }, function (error) { + var callFailure = calendar.opt('eventSourceFailure'); + console.warn(error.message, error); + if (eventSource.failure) { + eventSource.failure(error); + } + if (callFailure) { + callFailure(error); + } + calendar.dispatch({ + type: 'RECEIVE_EVENT_ERROR', + sourceId: eventSource.sourceId, + fetchId: fetchId, + fetchRange: fetchRange, + error: error + }); + }); + return __assign({}, eventSource, { isFetching: true, latestFetchId: fetchId }); +} +function receiveResponse(sourceHash, sourceId, fetchId, fetchRange) { + var _a; + var eventSource = sourceHash[sourceId]; + if (eventSource && // not already removed + fetchId === eventSource.latestFetchId) { + return __assign({}, sourceHash, (_a = {}, _a[sourceId] = __assign({}, eventSource, { isFetching: false, fetchRange: fetchRange }), _a)); + } + return sourceHash; +} +function excludeStaticSources(eventSources, calendar) { + return filterHash(eventSources, function (eventSource) { + return doesSourceNeedRange(eventSource, calendar); + }); +} + +var DateProfileGenerator = /** @class */ (function () { + function DateProfileGenerator(viewSpec, calendar) { + this.viewSpec = viewSpec; + this.options = viewSpec.options; + this.dateEnv = calendar.dateEnv; + this.calendar = calendar; + this.initHiddenDays(); + } + /* Date Range Computation + ------------------------------------------------------------------------------------------------------------------*/ + // Builds a structure with info about what the dates/ranges will be for the "prev" view. + DateProfileGenerator.prototype.buildPrev = function (currentDateProfile, currentDate) { + var dateEnv = this.dateEnv; + var prevDate = dateEnv.subtract(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month + currentDateProfile.dateIncrement); + return this.build(prevDate, -1); + }; + // Builds a structure with info about what the dates/ranges will be for the "next" view. + DateProfileGenerator.prototype.buildNext = function (currentDateProfile, currentDate) { + var dateEnv = this.dateEnv; + var nextDate = dateEnv.add(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month + currentDateProfile.dateIncrement); + return this.build(nextDate, 1); + }; + // Builds a structure holding dates/ranges for rendering around the given date. + // Optional direction param indicates whether the date is being incremented/decremented + // from its previous value. decremented = -1, incremented = 1 (default). + DateProfileGenerator.prototype.build = function (currentDate, direction, forceToValid) { + if (forceToValid === void 0) { forceToValid = false; } + var validRange; + var minTime = null; + var maxTime = null; + var currentInfo; + var isRangeAllDay; + var renderRange; + var activeRange; + var isValid; + validRange = this.buildValidRange(); + validRange = this.trimHiddenDays(validRange); + if (forceToValid) { + currentDate = constrainMarkerToRange(currentDate, validRange); + } + currentInfo = this.buildCurrentRangeInfo(currentDate, direction); + isRangeAllDay = /^(year|month|week|day)$/.test(currentInfo.unit); + renderRange = this.buildRenderRange(this.trimHiddenDays(currentInfo.range), currentInfo.unit, isRangeAllDay); + renderRange = this.trimHiddenDays(renderRange); + activeRange = renderRange; + if (!this.options.showNonCurrentDates) { + activeRange = intersectRanges(activeRange, currentInfo.range); + } + minTime = createDuration(this.options.minTime); + maxTime = createDuration(this.options.maxTime); + activeRange = this.adjustActiveRange(activeRange, minTime, maxTime); + activeRange = intersectRanges(activeRange, validRange); // might return null + // it's invalid if the originally requested date is not contained, + // or if the range is completely outside of the valid range. + isValid = rangesIntersect(currentInfo.range, validRange); + return { + // constraint for where prev/next operations can go and where events can be dragged/resized to. + // an object with optional start and end properties. + validRange: validRange, + // range the view is formally responsible for. + // for example, a month view might have 1st-31st, excluding padded dates + currentRange: currentInfo.range, + // name of largest unit being displayed, like "month" or "week" + currentRangeUnit: currentInfo.unit, + isRangeAllDay: isRangeAllDay, + // dates that display events and accept drag-n-drop + // will be `null` if no dates accept events + activeRange: activeRange, + // date range with a rendered skeleton + // includes not-active days that need some sort of DOM + renderRange: renderRange, + // Duration object that denotes the first visible time of any given day + minTime: minTime, + // Duration object that denotes the exclusive visible end time of any given day + maxTime: maxTime, + isValid: isValid, + // how far the current date will move for a prev/next operation + dateIncrement: this.buildDateIncrement(currentInfo.duration) + // pass a fallback (might be null) ^ + }; + }; + // Builds an object with optional start/end properties. + // Indicates the minimum/maximum dates to display. + // not responsible for trimming hidden days. + DateProfileGenerator.prototype.buildValidRange = function () { + return this.getRangeOption('validRange', this.calendar.getNow()) || + { start: null, end: null }; // completely open-ended + }; + // Builds a structure with info about the "current" range, the range that is + // highlighted as being the current month for example. + // See build() for a description of `direction`. + // Guaranteed to have `range` and `unit` properties. `duration` is optional. + DateProfileGenerator.prototype.buildCurrentRangeInfo = function (date, direction) { + var _a = this, viewSpec = _a.viewSpec, dateEnv = _a.dateEnv; + var duration = null; + var unit = null; + var range = null; + var dayCount; + if (viewSpec.duration) { + duration = viewSpec.duration; + unit = viewSpec.durationUnit; + range = this.buildRangeFromDuration(date, direction, duration, unit); + } + else if ((dayCount = this.options.dayCount)) { + unit = 'day'; + range = this.buildRangeFromDayCount(date, direction, dayCount); + } + else if ((range = this.buildCustomVisibleRange(date))) { + unit = dateEnv.greatestWholeUnit(range.start, range.end).unit; + } + else { + duration = this.getFallbackDuration(); + unit = greatestDurationDenominator(duration).unit; + range = this.buildRangeFromDuration(date, direction, duration, unit); + } + return { duration: duration, unit: unit, range: range }; + }; + DateProfileGenerator.prototype.getFallbackDuration = function () { + return createDuration({ day: 1 }); + }; + // Returns a new activeRange to have time values (un-ambiguate) + // minTime or maxTime causes the range to expand. + DateProfileGenerator.prototype.adjustActiveRange = function (range, minTime, maxTime) { + var dateEnv = this.dateEnv; + var start = range.start; + var end = range.end; + if (this.viewSpec.class.prototype.usesMinMaxTime) { + // expand active range if minTime is negative (why not when positive?) + if (asRoughDays(minTime) < 0) { + start = startOfDay(start); // necessary? + start = dateEnv.add(start, minTime); + } + // expand active range if maxTime is beyond one day (why not when positive?) + if (asRoughDays(maxTime) > 1) { + end = startOfDay(end); // necessary? + end = addDays(end, -1); + end = dateEnv.add(end, maxTime); + } + } + return { start: start, end: end }; + }; + // Builds the "current" range when it is specified as an explicit duration. + // `unit` is the already-computed greatestDurationDenominator unit of duration. + DateProfileGenerator.prototype.buildRangeFromDuration = function (date, direction, duration, unit) { + var dateEnv = this.dateEnv; + var alignment = this.options.dateAlignment; + var dateIncrementInput; + var dateIncrementDuration; + var start; + var end; + var res; + // compute what the alignment should be + if (!alignment) { + dateIncrementInput = this.options.dateIncrement; + if (dateIncrementInput) { + dateIncrementDuration = createDuration(dateIncrementInput); + // use the smaller of the two units + if (asRoughMs(dateIncrementDuration) < asRoughMs(duration)) { + alignment = greatestDurationDenominator(dateIncrementDuration, !getWeeksFromInput(dateIncrementInput)).unit; + } + else { + alignment = unit; + } + } + else { + alignment = unit; + } + } + // if the view displays a single day or smaller + if (asRoughDays(duration) <= 1) { + if (this.isHiddenDay(start)) { + start = this.skipHiddenDays(start, direction); + start = startOfDay(start); + } + } + function computeRes() { + start = dateEnv.startOf(date, alignment); + end = dateEnv.add(start, duration); + res = { start: start, end: end }; + } + computeRes(); + // if range is completely enveloped by hidden days, go past the hidden days + if (!this.trimHiddenDays(res)) { + date = this.skipHiddenDays(date, direction); + computeRes(); + } + return res; + }; + // Builds the "current" range when a dayCount is specified. + DateProfileGenerator.prototype.buildRangeFromDayCount = function (date, direction, dayCount) { + var dateEnv = this.dateEnv; + var customAlignment = this.options.dateAlignment; + var runningCount = 0; + var start = date; + var end; + if (customAlignment) { + start = dateEnv.startOf(start, customAlignment); + } + start = startOfDay(start); + start = this.skipHiddenDays(start, direction); + end = start; + do { + end = addDays(end, 1); + if (!this.isHiddenDay(end)) { + runningCount++; + } + } while (runningCount < dayCount); + return { start: start, end: end }; + }; + // Builds a normalized range object for the "visible" range, + // which is a way to define the currentRange and activeRange at the same time. + DateProfileGenerator.prototype.buildCustomVisibleRange = function (date) { + var dateEnv = this.dateEnv; + var visibleRange = this.getRangeOption('visibleRange', dateEnv.toDate(date)); + if (visibleRange && (visibleRange.start == null || visibleRange.end == null)) { + return null; + } + return visibleRange; + }; + // Computes the range that will represent the element/cells for *rendering*, + // but which may have voided days/times. + // not responsible for trimming hidden days. + DateProfileGenerator.prototype.buildRenderRange = function (currentRange, currentRangeUnit, isRangeAllDay) { + return currentRange; + }; + // Compute the duration value that should be added/substracted to the current date + // when a prev/next operation happens. + DateProfileGenerator.prototype.buildDateIncrement = function (fallback) { + var dateIncrementInput = this.options.dateIncrement; + var customAlignment; + if (dateIncrementInput) { + return createDuration(dateIncrementInput); + } + else if ((customAlignment = this.options.dateAlignment)) { + return createDuration(1, customAlignment); + } + else if (fallback) { + return fallback; + } + else { + return createDuration({ days: 1 }); + } + }; + // Arguments after name will be forwarded to a hypothetical function value + // WARNING: passed-in arguments will be given to generator functions as-is and can cause side-effects. + // Always clone your objects if you fear mutation. + DateProfileGenerator.prototype.getRangeOption = function (name) { + var otherArgs = []; + for (var _i = 1; _i < arguments.length; _i++) { + otherArgs[_i - 1] = arguments[_i]; + } + var val = this.options[name]; + if (typeof val === 'function') { + val = val.apply(null, otherArgs); + } + if (val) { + val = parseRange(val, this.dateEnv); + } + if (val) { + val = computeVisibleDayRange(val); + } + return val; + }; + /* Hidden Days + ------------------------------------------------------------------------------------------------------------------*/ + // Initializes internal variables related to calculating hidden days-of-week + DateProfileGenerator.prototype.initHiddenDays = function () { + var hiddenDays = this.options.hiddenDays || []; // array of day-of-week indices that are hidden + var isHiddenDayHash = []; // is the day-of-week hidden? (hash with day-of-week-index -> bool) + var dayCnt = 0; + var i; + if (this.options.weekends === false) { + hiddenDays.push(0, 6); // 0=sunday, 6=saturday + } + for (i = 0; i < 7; i++) { + if (!(isHiddenDayHash[i] = hiddenDays.indexOf(i) !== -1)) { + dayCnt++; + } + } + if (!dayCnt) { + throw new Error('invalid hiddenDays'); // all days were hidden? bad. + } + this.isHiddenDayHash = isHiddenDayHash; + }; + // Remove days from the beginning and end of the range that are computed as hidden. + // If the whole range is trimmed off, returns null + DateProfileGenerator.prototype.trimHiddenDays = function (range) { + var start = range.start; + var end = range.end; + if (start) { + start = this.skipHiddenDays(start); + } + if (end) { + end = this.skipHiddenDays(end, -1, true); + } + if (start == null || end == null || start < end) { + return { start: start, end: end }; + } + return null; + }; + // Is the current day hidden? + // `day` is a day-of-week index (0-6), or a Date (used for UTC) + DateProfileGenerator.prototype.isHiddenDay = function (day) { + if (day instanceof Date) { + day = day.getUTCDay(); + } + return this.isHiddenDayHash[day]; + }; + // Incrementing the current day until it is no longer a hidden day, returning a copy. + // DOES NOT CONSIDER validRange! + // If the initial value of `date` is not a hidden day, don't do anything. + // Pass `isExclusive` as `true` if you are dealing with an end date. + // `inc` defaults to `1` (increment one day forward each time) + DateProfileGenerator.prototype.skipHiddenDays = function (date, inc, isExclusive) { + if (inc === void 0) { inc = 1; } + if (isExclusive === void 0) { isExclusive = false; } + while (this.isHiddenDayHash[(date.getUTCDay() + (isExclusive ? inc : 0) + 7) % 7]) { + date = addDays(date, inc); + } + return date; + }; + return DateProfileGenerator; +}()); +// TODO: find a way to avoid comparing DateProfiles. it's tedious +function isDateProfilesEqual(p0, p1) { + return rangesEqual(p0.validRange, p1.validRange) && + rangesEqual(p0.activeRange, p1.activeRange) && + rangesEqual(p0.renderRange, p1.renderRange) && + durationsEqual(p0.minTime, p1.minTime) && + durationsEqual(p0.maxTime, p1.maxTime); + /* + TODO: compare more? + currentRange: DateRange + currentRangeUnit: string + isRangeAllDay: boolean + isValid: boolean + dateIncrement: Duration + */ +} + +function reduce (state, action, calendar) { + var viewType = reduceViewType(state.viewType, action); + var dateProfile = reduceDateProfile(state.dateProfile, action, state.currentDate, viewType, calendar); + var eventSources = reduceEventSources(state.eventSources, action, dateProfile, calendar); + var nextState = __assign({}, state, { viewType: viewType, + dateProfile: dateProfile, currentDate: reduceCurrentDate(state.currentDate, action, dateProfile), eventSources: eventSources, eventStore: reduceEventStore(state.eventStore, action, eventSources, dateProfile, calendar), dateSelection: reduceDateSelection(state.dateSelection, action, calendar), eventSelection: reduceSelectedEvent(state.eventSelection, action), eventDrag: reduceEventDrag(state.eventDrag, action, eventSources, calendar), eventResize: reduceEventResize(state.eventResize, action, eventSources, calendar), eventSourceLoadingLevel: computeLoadingLevel(eventSources), loadingLevel: computeLoadingLevel(eventSources) }); + for (var _i = 0, _a = calendar.pluginSystem.hooks.reducers; _i < _a.length; _i++) { + var reducerFunc = _a[_i]; + nextState = reducerFunc(nextState, action, calendar); + } + // console.log(action.type, nextState) + return nextState; +} +function reduceViewType(currentViewType, action) { + switch (action.type) { + case 'SET_VIEW_TYPE': + return action.viewType; + default: + return currentViewType; + } +} +function reduceDateProfile(currentDateProfile, action, currentDate, viewType, calendar) { + var newDateProfile; + switch (action.type) { + case 'PREV': + newDateProfile = calendar.dateProfileGenerators[viewType].buildPrev(currentDateProfile, currentDate); + break; + case 'NEXT': + newDateProfile = calendar.dateProfileGenerators[viewType].buildNext(currentDateProfile, currentDate); + break; + case 'SET_DATE': + if (!currentDateProfile.activeRange || + !rangeContainsMarker(currentDateProfile.currentRange, action.dateMarker)) { + newDateProfile = calendar.dateProfileGenerators[viewType].build(action.dateMarker, undefined, true // forceToValid + ); + } + break; + case 'SET_VIEW_TYPE': + var generator = calendar.dateProfileGenerators[viewType]; + if (!generator) { + throw new Error(viewType ? + 'The FullCalendar view "' + viewType + '" does not exist. Make sure your plugins are loaded correctly.' : + 'No available FullCalendar view plugins.'); + } + newDateProfile = generator.build(action.dateMarker || currentDate, undefined, true // forceToValid + ); + break; + } + if (newDateProfile && + newDateProfile.isValid && + !(currentDateProfile && isDateProfilesEqual(currentDateProfile, newDateProfile))) { + return newDateProfile; + } + else { + return currentDateProfile; + } +} +function reduceCurrentDate(currentDate, action, dateProfile) { + switch (action.type) { + case 'PREV': + case 'NEXT': + if (!rangeContainsMarker(dateProfile.currentRange, currentDate)) { + return dateProfile.currentRange.start; + } + else { + return currentDate; + } + case 'SET_DATE': + case 'SET_VIEW_TYPE': + var newDate = action.dateMarker || currentDate; + if (dateProfile.activeRange && !rangeContainsMarker(dateProfile.activeRange, newDate)) { + return dateProfile.currentRange.start; + } + else { + return newDate; + } + default: + return currentDate; + } +} +function reduceDateSelection(currentSelection, action, calendar) { + switch (action.type) { + case 'SELECT_DATES': + return action.selection; + case 'UNSELECT_DATES': + return null; + default: + return currentSelection; + } +} +function reduceSelectedEvent(currentInstanceId, action) { + switch (action.type) { + case 'SELECT_EVENT': + return action.eventInstanceId; + case 'UNSELECT_EVENT': + return ''; + default: + return currentInstanceId; + } +} +function reduceEventDrag(currentDrag, action, sources, calendar) { + switch (action.type) { + case 'SET_EVENT_DRAG': + var newDrag = action.state; + return { + affectedEvents: newDrag.affectedEvents, + mutatedEvents: newDrag.mutatedEvents, + isEvent: newDrag.isEvent, + origSeg: newDrag.origSeg + }; + case 'UNSET_EVENT_DRAG': + return null; + default: + return currentDrag; + } +} +function reduceEventResize(currentResize, action, sources, calendar) { + switch (action.type) { + case 'SET_EVENT_RESIZE': + var newResize = action.state; + return { + affectedEvents: newResize.affectedEvents, + mutatedEvents: newResize.mutatedEvents, + isEvent: newResize.isEvent, + origSeg: newResize.origSeg + }; + case 'UNSET_EVENT_RESIZE': + return null; + default: + return currentResize; + } +} +function computeLoadingLevel(eventSources) { + var cnt = 0; + for (var sourceId in eventSources) { + if (eventSources[sourceId].isFetching) { + cnt++; + } + } + return cnt; +} + +var STANDARD_PROPS = { + start: null, + end: null, + allDay: Boolean +}; +function parseDateSpan(raw, dateEnv, defaultDuration) { + var span = parseOpenDateSpan(raw, dateEnv); + var range = span.range; + if (!range.start) { + return null; + } + if (!range.end) { + if (defaultDuration == null) { + return null; + } + else { + range.end = dateEnv.add(range.start, defaultDuration); + } + } + return span; +} +/* +TODO: somehow combine with parseRange? +Will return null if the start/end props were present but parsed invalidly. +*/ +function parseOpenDateSpan(raw, dateEnv) { + var leftovers = {}; + var standardProps = refineProps(raw, STANDARD_PROPS, {}, leftovers); + var startMeta = standardProps.start ? dateEnv.createMarkerMeta(standardProps.start) : null; + var endMeta = standardProps.end ? dateEnv.createMarkerMeta(standardProps.end) : null; + var allDay = standardProps.allDay; + if (allDay == null) { + allDay = (startMeta && startMeta.isTimeUnspecified) && + (!endMeta || endMeta.isTimeUnspecified); + } + // use this leftover object as the selection object + leftovers.range = { + start: startMeta ? startMeta.marker : null, + end: endMeta ? endMeta.marker : null + }; + leftovers.allDay = allDay; + return leftovers; +} +function isDateSpansEqual(span0, span1) { + return rangesEqual(span0.range, span1.range) && + span0.allDay === span1.allDay && + isSpanPropsEqual(span0, span1); +} +// the NON-DATE-RELATED props +function isSpanPropsEqual(span0, span1) { + for (var propName in span1) { + if (propName !== 'range' && propName !== 'allDay') { + if (span0[propName] !== span1[propName]) { + return false; + } + } + } + // are there any props that span0 has that span1 DOESN'T have? + // both have range/allDay, so no need to special-case. + for (var propName in span0) { + if (!(propName in span1)) { + return false; + } + } + return true; +} +function buildDateSpanApi(span, dateEnv) { + return { + start: dateEnv.toDate(span.range.start), + end: dateEnv.toDate(span.range.end), + startStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }), + endStr: dateEnv.formatIso(span.range.end, { omitTime: span.allDay }), + allDay: span.allDay + }; +} +function buildDatePointApi(span, dateEnv) { + return { + date: dateEnv.toDate(span.range.start), + dateStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }), + allDay: span.allDay + }; +} +function fabricateEventRange(dateSpan, eventUiBases, calendar) { + var def = parseEventDef({ editable: false }, '', // sourceId + dateSpan.allDay, true, // hasEnd + calendar); + return { + def: def, + ui: compileEventUi(def, eventUiBases), + instance: createEventInstance(def.defId, dateSpan.range), + range: dateSpan.range, + isStart: true, + isEnd: true + }; +} + +function compileViewDefs(defaultConfigs, overrideConfigs) { + var hash = {}; + var viewType; + for (viewType in defaultConfigs) { + ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs); + } + for (viewType in overrideConfigs) { + ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs); + } + return hash; +} +function ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs) { + if (hash[viewType]) { + return hash[viewType]; + } + var viewDef = buildViewDef(viewType, hash, defaultConfigs, overrideConfigs); + if (viewDef) { + hash[viewType] = viewDef; + } + return viewDef; +} +function buildViewDef(viewType, hash, defaultConfigs, overrideConfigs) { + var defaultConfig = defaultConfigs[viewType]; + var overrideConfig = overrideConfigs[viewType]; + var queryProp = function (name) { + return (defaultConfig && defaultConfig[name] !== null) ? defaultConfig[name] : + ((overrideConfig && overrideConfig[name] !== null) ? overrideConfig[name] : null); + }; + var theClass = queryProp('class'); + var superType = queryProp('superType'); + if (!superType && theClass) { + superType = + findViewNameBySubclass(theClass, overrideConfigs) || + findViewNameBySubclass(theClass, defaultConfigs); + } + var superDef = null; + if (superType) { + if (superType === viewType) { + throw new Error('Can\'t have a custom view type that references itself'); + } + superDef = ensureViewDef(superType, hash, defaultConfigs, overrideConfigs); + } + if (!theClass && superDef) { + theClass = superDef.class; + } + if (!theClass) { + return null; // don't throw a warning, might be settings for a single-unit view + } + return { + type: viewType, + class: theClass, + defaults: __assign({}, (superDef ? superDef.defaults : {}), (defaultConfig ? defaultConfig.options : {})), + overrides: __assign({}, (superDef ? superDef.overrides : {}), (overrideConfig ? overrideConfig.options : {})) + }; +} +function findViewNameBySubclass(viewSubclass, configs) { + var superProto = Object.getPrototypeOf(viewSubclass.prototype); + for (var viewType in configs) { + var parsed = configs[viewType]; + // need DIRECT subclass, so instanceof won't do it + if (parsed.class && parsed.class.prototype === superProto) { + return viewType; + } + } + return ''; +} + +function parseViewConfigs(inputs) { + return mapHash(inputs, parseViewConfig); +} +var VIEW_DEF_PROPS = { + type: String, + class: null +}; +function parseViewConfig(input) { + if (typeof input === 'function') { + input = { class: input }; + } + var options = {}; + var props = refineProps(input, VIEW_DEF_PROPS, {}, options); + return { + superType: props.type, + class: props.class, + options: options + }; +} + +function buildViewSpecs(defaultInputs, optionsManager) { + var defaultConfigs = parseViewConfigs(defaultInputs); + var overrideConfigs = parseViewConfigs(optionsManager.overrides.views); + var viewDefs = compileViewDefs(defaultConfigs, overrideConfigs); + return mapHash(viewDefs, function (viewDef) { + return buildViewSpec(viewDef, overrideConfigs, optionsManager); + }); +} +function buildViewSpec(viewDef, overrideConfigs, optionsManager) { + var durationInput = viewDef.overrides.duration || + viewDef.defaults.duration || + optionsManager.dynamicOverrides.duration || + optionsManager.overrides.duration; + var duration = null; + var durationUnit = ''; + var singleUnit = ''; + var singleUnitOverrides = {}; + if (durationInput) { + duration = createDuration(durationInput); + if (duration) { // valid? + var denom = greatestDurationDenominator(duration, !getWeeksFromInput(durationInput)); + durationUnit = denom.unit; + if (denom.value === 1) { + singleUnit = durationUnit; + singleUnitOverrides = overrideConfigs[durationUnit] ? overrideConfigs[durationUnit].options : {}; + } + } + } + var queryButtonText = function (options) { + var buttonTextMap = options.buttonText || {}; + var buttonTextKey = viewDef.defaults.buttonTextKey; + if (buttonTextKey != null && buttonTextMap[buttonTextKey] != null) { + return buttonTextMap[buttonTextKey]; + } + if (buttonTextMap[viewDef.type] != null) { + return buttonTextMap[viewDef.type]; + } + if (buttonTextMap[singleUnit] != null) { + return buttonTextMap[singleUnit]; + } + }; + return { + type: viewDef.type, + class: viewDef.class, + duration: duration, + durationUnit: durationUnit, + singleUnit: singleUnit, + options: __assign({}, globalDefaults, viewDef.defaults, optionsManager.dirDefaults, optionsManager.localeDefaults, optionsManager.overrides, singleUnitOverrides, viewDef.overrides, optionsManager.dynamicOverrides), + buttonTextOverride: queryButtonText(optionsManager.dynamicOverrides) || + queryButtonText(optionsManager.overrides) || // constructor-specified buttonText lookup hash takes precedence + viewDef.overrides.buttonText, + buttonTextDefault: queryButtonText(optionsManager.localeDefaults) || + queryButtonText(optionsManager.dirDefaults) || + viewDef.defaults.buttonText || + queryButtonText(globalDefaults) || + viewDef.type // fall back to given view name + }; +} + +var Toolbar = /** @class */ (function (_super) { + __extends(Toolbar, _super); + function Toolbar(context, extraClassName) { + var _this = _super.call(this, context) || this; + _this._renderLayout = memoizeRendering(_this.renderLayout, _this.unrenderLayout); + _this._updateTitle = memoizeRendering(_this.updateTitle, null, [_this._renderLayout]); + _this._updateActiveButton = memoizeRendering(_this.updateActiveButton, null, [_this._renderLayout]); + _this._updateToday = memoizeRendering(_this.updateToday, null, [_this._renderLayout]); + _this._updatePrev = memoizeRendering(_this.updatePrev, null, [_this._renderLayout]); + _this._updateNext = memoizeRendering(_this.updateNext, null, [_this._renderLayout]); + _this.el = createElement('div', { className: 'fc-toolbar ' + extraClassName }); + return _this; + } + Toolbar.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this._renderLayout.unrender(); // should unrender everything else + removeElement(this.el); + }; + Toolbar.prototype.render = function (props) { + this._renderLayout(props.layout); + this._updateTitle(props.title); + this._updateActiveButton(props.activeButton); + this._updateToday(props.isTodayEnabled); + this._updatePrev(props.isPrevEnabled); + this._updateNext(props.isNextEnabled); + }; + Toolbar.prototype.renderLayout = function (layout) { + var el = this.el; + this.viewsWithButtons = []; + appendToElement(el, this.renderSection('left', layout.left)); + appendToElement(el, this.renderSection('center', layout.center)); + appendToElement(el, this.renderSection('right', layout.right)); + }; + Toolbar.prototype.unrenderLayout = function () { + this.el.innerHTML = ''; + }; + Toolbar.prototype.renderSection = function (position, buttonStr) { + var _this = this; + var _a = this, theme = _a.theme, calendar = _a.calendar; + var optionsManager = calendar.optionsManager; + var viewSpecs = calendar.viewSpecs; + var sectionEl = createElement('div', { className: 'fc-' + position }); + var calendarCustomButtons = optionsManager.computed.customButtons || {}; + var calendarButtonTextOverrides = optionsManager.overrides.buttonText || {}; + var calendarButtonText = optionsManager.computed.buttonText || {}; + if (buttonStr) { + buttonStr.split(' ').forEach(function (buttonGroupStr, i) { + var groupChildren = []; + var isOnlyButtons = true; + var groupEl; + buttonGroupStr.split(',').forEach(function (buttonName, j) { + var customButtonProps; + var viewSpec; + var buttonClick; + var buttonIcon; // only one of these will be set + var buttonText; // " + var buttonInnerHtml; + var buttonClasses; + var buttonEl; + var buttonAriaAttr; + if (buttonName === 'title') { + groupChildren.push(htmlToElement('<h2> </h2>')); // we always want it to take up height + isOnlyButtons = false; + } + else { + if ((customButtonProps = calendarCustomButtons[buttonName])) { + buttonClick = function (ev) { + if (customButtonProps.click) { + customButtonProps.click.call(buttonEl, ev); + } + }; + (buttonIcon = theme.getCustomButtonIconClass(customButtonProps)) || + (buttonIcon = theme.getIconClass(buttonName)) || + (buttonText = customButtonProps.text); + } + else if ((viewSpec = viewSpecs[buttonName])) { + _this.viewsWithButtons.push(buttonName); + buttonClick = function () { + calendar.changeView(buttonName); + }; + (buttonText = viewSpec.buttonTextOverride) || + (buttonIcon = theme.getIconClass(buttonName)) || + (buttonText = viewSpec.buttonTextDefault); + } + else if (calendar[buttonName]) { // a calendar method + buttonClick = function () { + calendar[buttonName](); + }; + (buttonText = calendarButtonTextOverrides[buttonName]) || + (buttonIcon = theme.getIconClass(buttonName)) || + (buttonText = calendarButtonText[buttonName]); + // ^ everything else is considered default + } + if (buttonClick) { + buttonClasses = [ + 'fc-' + buttonName + '-button', + theme.getClass('button') + ]; + if (buttonText) { + buttonInnerHtml = htmlEscape(buttonText); + buttonAriaAttr = ''; + } + else if (buttonIcon) { + buttonInnerHtml = "<span class='" + buttonIcon + "'></span>"; + buttonAriaAttr = ' aria-label="' + buttonName + '"'; + } + buttonEl = htmlToElement(// type="button" so that it doesn't submit a form + '<button type="button" class="' + buttonClasses.join(' ') + '"' + + buttonAriaAttr + + '>' + buttonInnerHtml + '</button>'); + buttonEl.addEventListener('click', buttonClick); + groupChildren.push(buttonEl); + } + } + }); + if (groupChildren.length > 1) { + groupEl = document.createElement('div'); + var buttonGroupClassName = theme.getClass('buttonGroup'); + if (isOnlyButtons && buttonGroupClassName) { + groupEl.classList.add(buttonGroupClassName); + } + appendToElement(groupEl, groupChildren); + sectionEl.appendChild(groupEl); + } + else { + appendToElement(sectionEl, groupChildren); // 1 or 0 children + } + }); + } + return sectionEl; + }; + Toolbar.prototype.updateToday = function (isTodayEnabled) { + this.toggleButtonEnabled('today', isTodayEnabled); + }; + Toolbar.prototype.updatePrev = function (isPrevEnabled) { + this.toggleButtonEnabled('prev', isPrevEnabled); + }; + Toolbar.prototype.updateNext = function (isNextEnabled) { + this.toggleButtonEnabled('next', isNextEnabled); + }; + Toolbar.prototype.updateTitle = function (text) { + findElements(this.el, 'h2').forEach(function (titleEl) { + titleEl.innerText = text; + }); + }; + Toolbar.prototype.updateActiveButton = function (buttonName) { + var className = this.theme.getClass('buttonActive'); + findElements(this.el, 'button').forEach(function (buttonEl) { + if (buttonName && buttonEl.classList.contains('fc-' + buttonName + '-button')) { + buttonEl.classList.add(className); + } + else { + buttonEl.classList.remove(className); + } + }); + }; + Toolbar.prototype.toggleButtonEnabled = function (buttonName, bool) { + findElements(this.el, '.fc-' + buttonName + '-button').forEach(function (buttonEl) { + buttonEl.disabled = !bool; + }); + }; + return Toolbar; +}(Component)); + +var CalendarComponent = /** @class */ (function (_super) { + __extends(CalendarComponent, _super); + function CalendarComponent(context, el) { + var _this = _super.call(this, context) || this; + _this._renderToolbars = memoizeRendering(_this.renderToolbars); + _this.buildViewPropTransformers = memoize(buildViewPropTransformers); + _this.el = el; + prependToElement(el, _this.contentEl = createElement('div', { className: 'fc-view-container' })); + var calendar = _this.calendar; + for (var _i = 0, _a = calendar.pluginSystem.hooks.viewContainerModifiers; _i < _a.length; _i++) { + var modifyViewContainer = _a[_i]; + modifyViewContainer(_this.contentEl, calendar); + } + _this.toggleElClassNames(true); + _this.computeTitle = memoize(computeTitle); + _this.parseBusinessHours = memoize(function (input) { + return parseBusinessHours(input, _this.calendar); + }); + return _this; + } + CalendarComponent.prototype.destroy = function () { + if (this.header) { + this.header.destroy(); + } + if (this.footer) { + this.footer.destroy(); + } + if (this.view) { + this.view.destroy(); + } + removeElement(this.contentEl); + this.toggleElClassNames(false); + _super.prototype.destroy.call(this); + }; + CalendarComponent.prototype.toggleElClassNames = function (bool) { + var classList = this.el.classList; + var dirClassName = 'fc-' + this.opt('dir'); + var themeClassName = this.theme.getClass('widget'); + if (bool) { + classList.add('fc'); + classList.add(dirClassName); + classList.add(themeClassName); + } + else { + classList.remove('fc'); + classList.remove(dirClassName); + classList.remove(themeClassName); + } + }; + CalendarComponent.prototype.render = function (props) { + this.freezeHeight(); + var title = this.computeTitle(props.dateProfile, props.viewSpec.options); + this._renderToolbars(props.viewSpec, props.dateProfile, props.currentDate, props.dateProfileGenerator, title); + this.renderView(props, title); + this.updateSize(); + this.thawHeight(); + }; + CalendarComponent.prototype.renderToolbars = function (viewSpec, dateProfile, currentDate, dateProfileGenerator, title) { + var headerLayout = this.opt('header'); + var footerLayout = this.opt('footer'); + var now = this.calendar.getNow(); + var todayInfo = dateProfileGenerator.build(now); + var prevInfo = dateProfileGenerator.buildPrev(dateProfile, currentDate); + var nextInfo = dateProfileGenerator.buildNext(dateProfile, currentDate); + var toolbarProps = { + title: title, + activeButton: viewSpec.type, + isTodayEnabled: todayInfo.isValid && !rangeContainsMarker(dateProfile.currentRange, now), + isPrevEnabled: prevInfo.isValid, + isNextEnabled: nextInfo.isValid + }; + if (headerLayout) { + if (!this.header) { + this.header = new Toolbar(this.context, 'fc-header-toolbar'); + prependToElement(this.el, this.header.el); + } + this.header.receiveProps(__assign({ layout: headerLayout }, toolbarProps)); + } + else if (this.header) { + this.header.destroy(); + this.header = null; + } + if (footerLayout) { + if (!this.footer) { + this.footer = new Toolbar(this.context, 'fc-footer-toolbar'); + appendToElement(this.el, this.footer.el); + } + this.footer.receiveProps(__assign({ layout: footerLayout }, toolbarProps)); + } + else if (this.footer) { + this.footer.destroy(); + this.footer = null; + } + }; + CalendarComponent.prototype.renderView = function (props, title) { + var view = this.view; + var viewSpec = props.viewSpec, dateProfileGenerator = props.dateProfileGenerator; + if (!view || view.viewSpec !== viewSpec) { + if (view) { + view.destroy(); + } + view = this.view = new viewSpec['class']({ + calendar: this.calendar, + view: null, + dateEnv: this.dateEnv, + theme: this.theme, + options: viewSpec.options + }, viewSpec, dateProfileGenerator, this.contentEl); + } + else { + view.addScroll(view.queryScroll()); + } + view.title = title; // for the API + var viewProps = { + dateProfile: props.dateProfile, + businessHours: this.parseBusinessHours(viewSpec.options.businessHours), + eventStore: props.eventStore, + eventUiBases: props.eventUiBases, + dateSelection: props.dateSelection, + eventSelection: props.eventSelection, + eventDrag: props.eventDrag, + eventResize: props.eventResize + }; + var transformers = this.buildViewPropTransformers(this.calendar.pluginSystem.hooks.viewPropsTransformers); + for (var _i = 0, transformers_1 = transformers; _i < transformers_1.length; _i++) { + var transformer = transformers_1[_i]; + __assign(viewProps, transformer.transform(viewProps, viewSpec, props, view)); + } + view.receiveProps(viewProps); + }; + // Sizing + // ----------------------------------------------------------------------------------------------------------------- + CalendarComponent.prototype.updateSize = function (isResize) { + if (isResize === void 0) { isResize = false; } + var view = this.view; + if (isResize) { + view.addScroll(view.queryScroll()); + } + if (isResize || this.isHeightAuto == null) { + this.computeHeightVars(); + } + view.updateSize(isResize, this.viewHeight, this.isHeightAuto); + view.updateNowIndicator(); // we need to guarantee this will run after updateSize + view.popScroll(isResize); + }; + CalendarComponent.prototype.computeHeightVars = function () { + var calendar = this.calendar; // yuck. need to handle dynamic options + var heightInput = calendar.opt('height'); + var contentHeightInput = calendar.opt('contentHeight'); + this.isHeightAuto = heightInput === 'auto' || contentHeightInput === 'auto'; + if (typeof contentHeightInput === 'number') { // exists and not 'auto' + this.viewHeight = contentHeightInput; + } + else if (typeof contentHeightInput === 'function') { // exists and is a function + this.viewHeight = contentHeightInput(); + } + else if (typeof heightInput === 'number') { // exists and not 'auto' + this.viewHeight = heightInput - this.queryToolbarsHeight(); + } + else if (typeof heightInput === 'function') { // exists and is a function + this.viewHeight = heightInput() - this.queryToolbarsHeight(); + } + else if (heightInput === 'parent') { // set to height of parent element + var parentEl = this.el.parentNode; + this.viewHeight = parentEl.getBoundingClientRect().height - this.queryToolbarsHeight(); + } + else { + this.viewHeight = Math.round(this.contentEl.getBoundingClientRect().width / + Math.max(calendar.opt('aspectRatio'), .5)); + } + }; + CalendarComponent.prototype.queryToolbarsHeight = function () { + var height = 0; + if (this.header) { + height += computeHeightAndMargins(this.header.el); + } + if (this.footer) { + height += computeHeightAndMargins(this.footer.el); + } + return height; + }; + // Height "Freezing" + // ----------------------------------------------------------------------------------------------------------------- + CalendarComponent.prototype.freezeHeight = function () { + applyStyle(this.el, { + height: this.el.getBoundingClientRect().height, + overflow: 'hidden' + }); + }; + CalendarComponent.prototype.thawHeight = function () { + applyStyle(this.el, { + height: '', + overflow: '' + }); + }; + return CalendarComponent; +}(Component)); +// Title and Date Formatting +// ----------------------------------------------------------------------------------------------------------------- +// Computes what the title at the top of the calendar should be for this view +function computeTitle(dateProfile, viewOptions) { + var range; + // for views that span a large unit of time, show the proper interval, ignoring stray days before and after + if (/^(year|month)$/.test(dateProfile.currentRangeUnit)) { + range = dateProfile.currentRange; + } + else { // for day units or smaller, use the actual day range + range = dateProfile.activeRange; + } + return this.dateEnv.formatRange(range.start, range.end, createFormatter(viewOptions.titleFormat || computeTitleFormat(dateProfile), viewOptions.titleRangeSeparator), { isEndExclusive: dateProfile.isRangeAllDay }); +} +// Generates the format string that should be used to generate the title for the current date range. +// Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`. +function computeTitleFormat(dateProfile) { + var currentRangeUnit = dateProfile.currentRangeUnit; + if (currentRangeUnit === 'year') { + return { year: 'numeric' }; + } + else if (currentRangeUnit === 'month') { + return { year: 'numeric', month: 'long' }; // like "September 2014" + } + else { + var days = diffWholeDays(dateProfile.currentRange.start, dateProfile.currentRange.end); + if (days !== null && days > 1) { + // multi-day range. shorter, like "Sep 9 - 10 2014" + return { year: 'numeric', month: 'short', day: 'numeric' }; + } + else { + // one day. longer, like "September 9 2014" + return { year: 'numeric', month: 'long', day: 'numeric' }; + } + } +} +// Plugin +// ----------------------------------------------------------------------------------------------------------------- +function buildViewPropTransformers(theClasses) { + return theClasses.map(function (theClass) { + return new theClass(); + }); +} + +var Interaction = /** @class */ (function () { + function Interaction(settings) { + this.component = settings.component; + } + Interaction.prototype.destroy = function () { + }; + return Interaction; +}()); +function parseInteractionSettings(component, input) { + return { + component: component, + el: input.el, + useEventCenter: input.useEventCenter != null ? input.useEventCenter : true + }; +} +function interactionSettingsToStore(settings) { + var _a; + return _a = {}, + _a[settings.component.uid] = settings, + _a; +} +// global state +var interactionSettingsStore = {}; + +/* +Detects when the user clicks on an event within a DateComponent +*/ +var EventClicking = /** @class */ (function (_super) { + __extends(EventClicking, _super); + function EventClicking(settings) { + var _this = _super.call(this, settings) || this; + _this.handleSegClick = function (ev, segEl) { + var component = _this.component; + var seg = getElSeg(segEl); + if (seg && // might be the <div> surrounding the more link + component.isValidSegDownEl(ev.target)) { + // our way to simulate a link click for elements that can't be <a> tags + // grab before trigger fired in case trigger trashes DOM thru rerendering + var hasUrlContainer = elementClosest(ev.target, '.fc-has-url'); + var url = hasUrlContainer ? hasUrlContainer.querySelector('a[href]').href : ''; + component.publiclyTrigger('eventClick', [ + { + el: segEl, + event: new EventApi(component.calendar, seg.eventRange.def, seg.eventRange.instance), + jsEvent: ev, + view: component.view + } + ]); + if (url && !ev.defaultPrevented) { + window.location.href = url; + } + } + }; + var component = settings.component; + _this.destroy = listenBySelector(component.el, 'click', component.fgSegSelector + ',' + component.bgSegSelector, _this.handleSegClick); + return _this; + } + return EventClicking; +}(Interaction)); + +/* +Triggers events and adds/removes core classNames when the user's pointer +enters/leaves event-elements of a component. +*/ +var EventHovering = /** @class */ (function (_super) { + __extends(EventHovering, _super); + function EventHovering(settings) { + var _this = _super.call(this, settings) || this; + // for simulating an eventMouseLeave when the event el is destroyed while mouse is over it + _this.handleEventElRemove = function (el) { + if (el === _this.currentSegEl) { + _this.handleSegLeave(null, _this.currentSegEl); + } + }; + _this.handleSegEnter = function (ev, segEl) { + if (getElSeg(segEl)) { // TODO: better way to make sure not hovering over more+ link or its wrapper + segEl.classList.add('fc-allow-mouse-resize'); + _this.currentSegEl = segEl; + _this.triggerEvent('eventMouseEnter', ev, segEl); + } + }; + _this.handleSegLeave = function (ev, segEl) { + if (_this.currentSegEl) { + segEl.classList.remove('fc-allow-mouse-resize'); + _this.currentSegEl = null; + _this.triggerEvent('eventMouseLeave', ev, segEl); + } + }; + var component = settings.component; + _this.removeHoverListeners = listenToHoverBySelector(component.el, component.fgSegSelector + ',' + component.bgSegSelector, _this.handleSegEnter, _this.handleSegLeave); + component.calendar.on('eventElRemove', _this.handleEventElRemove); + return _this; + } + EventHovering.prototype.destroy = function () { + this.removeHoverListeners(); + this.component.calendar.off('eventElRemove', this.handleEventElRemove); + }; + EventHovering.prototype.triggerEvent = function (publicEvName, ev, segEl) { + var component = this.component; + var seg = getElSeg(segEl); + if (!ev || component.isValidSegDownEl(ev.target)) { + component.publiclyTrigger(publicEvName, [ + { + el: segEl, + event: new EventApi(this.component.calendar, seg.eventRange.def, seg.eventRange.instance), + jsEvent: ev, + view: component.view + } + ]); + } + }; + return EventHovering; +}(Interaction)); + +var StandardTheme = /** @class */ (function (_super) { + __extends(StandardTheme, _super); + function StandardTheme() { + return _super !== null && _super.apply(this, arguments) || this; + } + return StandardTheme; +}(Theme)); +StandardTheme.prototype.classes = { + widget: 'fc-unthemed', + widgetHeader: 'fc-widget-header', + widgetContent: 'fc-widget-content', + buttonGroup: 'fc-button-group', + button: 'fc-button fc-button-primary', + buttonActive: 'fc-button-active', + popoverHeader: 'fc-widget-header', + popoverContent: 'fc-widget-content', + // day grid + headerRow: 'fc-widget-header', + dayRow: 'fc-widget-content', + // list view + listView: 'fc-widget-content' +}; +StandardTheme.prototype.baseIconClass = 'fc-icon'; +StandardTheme.prototype.iconClasses = { + close: 'fc-icon-x', + prev: 'fc-icon-chevron-left', + next: 'fc-icon-chevron-right', + prevYear: 'fc-icon-chevrons-left', + nextYear: 'fc-icon-chevrons-right' +}; +StandardTheme.prototype.iconOverrideOption = 'buttonIcons'; +StandardTheme.prototype.iconOverrideCustomButtonOption = 'icon'; +StandardTheme.prototype.iconOverridePrefix = 'fc-icon-'; + +var Calendar = /** @class */ (function () { + function Calendar(el, overrides) { + var _this = this; + this.parseRawLocales = memoize(parseRawLocales); + this.buildLocale = memoize(buildLocale); + this.buildDateEnv = memoize(buildDateEnv); + this.buildTheme = memoize(buildTheme); + this.buildEventUiSingleBase = memoize(this._buildEventUiSingleBase); + this.buildSelectionConfig = memoize(this._buildSelectionConfig); + this.buildEventUiBySource = memoizeOutput(buildEventUiBySource, isPropsEqual); + this.buildEventUiBases = memoize(buildEventUiBases); + this.interactionsStore = {}; + this.actionQueue = []; + this.isReducing = false; + // isDisplaying: boolean = false // installed in DOM? accepting renders? + this.needsRerender = false; // needs a render? + this.needsFullRerender = false; + this.isRendering = false; // currently in the executeRender function? + this.renderingPauseDepth = 0; + this.buildDelayedRerender = memoize(buildDelayedRerender); + this.afterSizingTriggers = {}; + this.isViewUpdated = false; + this.isDatesUpdated = false; + this.isEventsUpdated = false; + this.el = el; + this.optionsManager = new OptionsManager(overrides || {}); + this.pluginSystem = new PluginSystem(); + // only do once. don't do in handleOptions. because can't remove plugins + this.addPluginInputs(this.optionsManager.computed.plugins || []); + this.handleOptions(this.optionsManager.computed); + this.publiclyTrigger('_init'); // for tests + this.hydrate(); + this.calendarInteractions = this.pluginSystem.hooks.calendarInteractions + .map(function (calendarInteractionClass) { + return new calendarInteractionClass(_this); + }); + } + Calendar.prototype.addPluginInputs = function (pluginInputs) { + var pluginDefs = refinePluginDefs(pluginInputs); + for (var _i = 0, pluginDefs_1 = pluginDefs; _i < pluginDefs_1.length; _i++) { + var pluginDef = pluginDefs_1[_i]; + this.pluginSystem.add(pluginDef); + } + }; + Object.defineProperty(Calendar.prototype, "view", { + // public API + get: function () { + return this.component ? this.component.view : null; + }, + enumerable: true, + configurable: true + }); + // Public API for rendering + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.render = function () { + if (!this.component) { + this.renderableEventStore = createEmptyEventStore(); + this.bindHandlers(); + this.executeRender(); + } + else { + this.requestRerender(true); + } + }; + Calendar.prototype.destroy = function () { + if (this.component) { + this.unbindHandlers(); + this.component.destroy(); // don't null-out. in case API needs access + this.component = null; // umm ??? + for (var _i = 0, _a = this.calendarInteractions; _i < _a.length; _i++) { + var interaction = _a[_i]; + interaction.destroy(); + } + this.publiclyTrigger('_destroyed'); + } + }; + // Handlers + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.bindHandlers = function () { + var _this = this; + // event delegation for nav links + this.removeNavLinkListener = listenBySelector(this.el, 'click', 'a[data-goto]', function (ev, anchorEl) { + var gotoOptions = anchorEl.getAttribute('data-goto'); + gotoOptions = gotoOptions ? JSON.parse(gotoOptions) : {}; + var dateEnv = _this.dateEnv; + var dateMarker = dateEnv.createMarker(gotoOptions.date); + var viewType = gotoOptions.type; + // property like "navLinkDayClick". might be a string or a function + var customAction = _this.viewOpt('navLink' + capitaliseFirstLetter(viewType) + 'Click'); + if (typeof customAction === 'function') { + customAction(dateEnv.toDate(dateMarker), ev); + } + else { + if (typeof customAction === 'string') { + viewType = customAction; + } + _this.zoomTo(dateMarker, viewType); + } + }); + if (this.opt('handleWindowResize')) { + window.addEventListener('resize', this.windowResizeProxy = debounce(// prevents rapid calls + this.windowResize.bind(this), this.opt('windowResizeDelay'))); + } + }; + Calendar.prototype.unbindHandlers = function () { + this.removeNavLinkListener(); + if (this.windowResizeProxy) { + window.removeEventListener('resize', this.windowResizeProxy); + this.windowResizeProxy = null; + } + }; + // Dispatcher + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.hydrate = function () { + var _this = this; + this.state = this.buildInitialState(); + var rawSources = this.opt('eventSources') || []; + var singleRawSource = this.opt('events'); + var sources = []; // parsed + if (singleRawSource) { + rawSources.unshift(singleRawSource); + } + for (var _i = 0, rawSources_1 = rawSources; _i < rawSources_1.length; _i++) { + var rawSource = rawSources_1[_i]; + var source = parseEventSource(rawSource, this); + if (source) { + sources.push(source); + } + } + this.batchRendering(function () { + _this.dispatch({ type: 'INIT' }); // pass in sources here? + _this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: sources }); + _this.dispatch({ + type: 'SET_VIEW_TYPE', + viewType: _this.opt('defaultView') || _this.pluginSystem.hooks.defaultView + }); + }); + }; + Calendar.prototype.buildInitialState = function () { + return { + viewType: null, + loadingLevel: 0, + eventSourceLoadingLevel: 0, + currentDate: this.getInitialDate(), + dateProfile: null, + eventSources: {}, + eventStore: createEmptyEventStore(), + dateSelection: null, + eventSelection: '', + eventDrag: null, + eventResize: null + }; + }; + Calendar.prototype.dispatch = function (action) { + this.actionQueue.push(action); + if (!this.isReducing) { + this.isReducing = true; + var oldState = this.state; + while (this.actionQueue.length) { + this.state = this.reduce(this.state, this.actionQueue.shift(), this); + } + var newState = this.state; + this.isReducing = false; + if (!oldState.loadingLevel && newState.loadingLevel) { + this.publiclyTrigger('loading', [true]); + } + else if (oldState.loadingLevel && !newState.loadingLevel) { + this.publiclyTrigger('loading', [false]); + } + var view = this.component && this.component.view; + if (oldState.eventStore !== newState.eventStore || this.needsFullRerender) { + if (oldState.eventStore) { + this.isEventsUpdated = true; + } + } + if (oldState.dateProfile !== newState.dateProfile || this.needsFullRerender) { + if (oldState.dateProfile && view) { // why would view be null!? + this.publiclyTrigger('datesDestroy', [ + { + view: view, + el: view.el + } + ]); + } + this.isDatesUpdated = true; + } + if (oldState.viewType !== newState.viewType || this.needsFullRerender) { + if (oldState.viewType && view) { // why would view be null!? + this.publiclyTrigger('viewSkeletonDestroy', [ + { + view: view, + el: view.el + } + ]); + } + this.isViewUpdated = true; + } + this.requestRerender(); + } + }; + Calendar.prototype.reduce = function (state, action, calendar) { + return reduce(state, action, calendar); + }; + // Render Queue + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.requestRerender = function (needsFull) { + if (needsFull === void 0) { needsFull = false; } + this.needsRerender = true; + this.needsFullRerender = this.needsFullRerender || needsFull; + this.delayedRerender(); // will call a debounced-version of tryRerender + }; + Calendar.prototype.tryRerender = function () { + if (this.component && // must be accepting renders + this.needsRerender && // indicates that a rerender was requested + !this.renderingPauseDepth && // not paused + !this.isRendering // not currently in the render loop + ) { + this.executeRender(); + } + }; + Calendar.prototype.batchRendering = function (func) { + this.renderingPauseDepth++; + func(); + this.renderingPauseDepth--; + if (this.needsRerender) { + this.requestRerender(); + } + }; + // Rendering + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.executeRender = function () { + var needsFullRerender = this.needsFullRerender; // save before clearing + // clear these BEFORE the render so that new values will accumulate during render + this.needsRerender = false; + this.needsFullRerender = false; + this.isRendering = true; + this.renderComponent(needsFullRerender); + this.isRendering = false; + // received a rerender request while rendering + if (this.needsRerender) { + this.delayedRerender(); + } + }; + /* + don't call this directly. use executeRender instead + */ + Calendar.prototype.renderComponent = function (needsFull) { + var _a = this, state = _a.state, component = _a.component; + var viewType = state.viewType; + var viewSpec = this.viewSpecs[viewType]; + var savedScroll = (needsFull && component) ? component.view.queryScroll() : null; + if (!viewSpec) { + throw new Error("View type \"" + viewType + "\" is not valid"); + } + // if event sources are still loading and progressive rendering hasn't been enabled, + // keep rendering the last fully loaded set of events + var renderableEventStore = this.renderableEventStore = + (state.eventSourceLoadingLevel && !this.opt('progressiveEventRendering')) ? + this.renderableEventStore : + state.eventStore; + var eventUiSingleBase = this.buildEventUiSingleBase(viewSpec.options); + var eventUiBySource = this.buildEventUiBySource(state.eventSources); + var eventUiBases = this.eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource); + if (needsFull || !component) { + if (component) { + component.freezeHeight(); // next component will unfreeze it + component.destroy(); + } + component = this.component = new CalendarComponent({ + calendar: this, + view: null, + dateEnv: this.dateEnv, + theme: this.theme, + options: this.optionsManager.computed + }, this.el); + this.isViewUpdated = true; + this.isDatesUpdated = true; + this.isEventsUpdated = true; + } + component.receiveProps(__assign({}, state, { viewSpec: viewSpec, dateProfile: state.dateProfile, dateProfileGenerator: this.dateProfileGenerators[viewType], eventStore: renderableEventStore, eventUiBases: eventUiBases, dateSelection: state.dateSelection, eventSelection: state.eventSelection, eventDrag: state.eventDrag, eventResize: state.eventResize })); + if (savedScroll) { + component.view.applyScroll(savedScroll, false); + } + if (this.isViewUpdated) { + this.isViewUpdated = false; + this.publiclyTrigger('viewSkeletonRender', [ + { + view: component.view, + el: component.view.el + } + ]); + } + if (this.isDatesUpdated) { + this.isDatesUpdated = false; + this.publiclyTrigger('datesRender', [ + { + view: component.view, + el: component.view.el + } + ]); + } + if (this.isEventsUpdated) { + this.isEventsUpdated = false; + } + this.releaseAfterSizingTriggers(); + }; + // Options + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.setOption = function (name, val) { + var _a; + this.mutateOptions((_a = {}, _a[name] = val, _a), [], true); + }; + Calendar.prototype.getOption = function (name) { + return this.optionsManager.computed[name]; + }; + Calendar.prototype.opt = function (name) { + return this.optionsManager.computed[name]; + }; + Calendar.prototype.viewOpt = function (name) { + return this.viewOpts()[name]; + }; + Calendar.prototype.viewOpts = function () { + return this.viewSpecs[this.state.viewType].options; + }; + /* + handles option changes (like a diff) + */ + Calendar.prototype.mutateOptions = function (updates, removals, isDynamic, deepEqual) { + var _this = this; + var changeHandlers = this.pluginSystem.hooks.optionChangeHandlers; + var normalUpdates = {}; + var specialUpdates = {}; + var oldDateEnv = this.dateEnv; // do this before handleOptions + var isTimeZoneDirty = false; + var isSizeDirty = false; + var anyDifficultOptions = Boolean(removals.length); + for (var name_1 in updates) { + if (changeHandlers[name_1]) { + specialUpdates[name_1] = updates[name_1]; + } + else { + normalUpdates[name_1] = updates[name_1]; + } + } + for (var name_2 in normalUpdates) { + if (/^(height|contentHeight|aspectRatio)$/.test(name_2)) { + isSizeDirty = true; + } + else if (/^(defaultDate|defaultView)$/.test(name_2)) ; + else { + anyDifficultOptions = true; + if (name_2 === 'timeZone') { + isTimeZoneDirty = true; + } + } + } + this.optionsManager.mutate(normalUpdates, removals, isDynamic); + if (anyDifficultOptions) { + this.handleOptions(this.optionsManager.computed); + this.needsFullRerender = true; + } + this.batchRendering(function () { + if (anyDifficultOptions) { + if (isTimeZoneDirty) { + _this.dispatch({ + type: 'CHANGE_TIMEZONE', + oldDateEnv: oldDateEnv + }); + } + /* HACK + has the same effect as calling this.requestRerender(true) + but recomputes the state's dateProfile + */ + _this.dispatch({ + type: 'SET_VIEW_TYPE', + viewType: _this.state.viewType + }); + } + else if (isSizeDirty) { + _this.updateSize(); + } + // special updates + if (deepEqual) { + for (var name_3 in specialUpdates) { + changeHandlers[name_3](specialUpdates[name_3], _this, deepEqual); + } + } + }); + }; + /* + rebuilds things based off of a complete set of refined options + */ + Calendar.prototype.handleOptions = function (options) { + var _this = this; + var pluginHooks = this.pluginSystem.hooks; + this.defaultAllDayEventDuration = createDuration(options.defaultAllDayEventDuration); + this.defaultTimedEventDuration = createDuration(options.defaultTimedEventDuration); + this.delayedRerender = this.buildDelayedRerender(options.rerenderDelay); + this.theme = this.buildTheme(options); + var available = this.parseRawLocales(options.locales); + this.availableRawLocales = available.map; + var locale = this.buildLocale(options.locale || available.defaultCode, available.map); + this.dateEnv = this.buildDateEnv(locale, options.timeZone, pluginHooks.namedTimeZonedImpl, options.firstDay, options.weekNumberCalculation, options.weekLabel, pluginHooks.cmdFormatter); + this.selectionConfig = this.buildSelectionConfig(options); // needs dateEnv. do after :( + // ineffecient to do every time? + this.viewSpecs = buildViewSpecs(pluginHooks.views, this.optionsManager); + // ineffecient to do every time? + this.dateProfileGenerators = mapHash(this.viewSpecs, function (viewSpec) { + return new viewSpec.class.prototype.dateProfileGeneratorClass(viewSpec, _this); + }); + }; + Calendar.prototype.getAvailableLocaleCodes = function () { + return Object.keys(this.availableRawLocales); + }; + Calendar.prototype._buildSelectionConfig = function (rawOpts) { + return processScopedUiProps('select', rawOpts, this); + }; + Calendar.prototype._buildEventUiSingleBase = function (rawOpts) { + if (rawOpts.editable) { // so 'editable' affected events + rawOpts = __assign({}, rawOpts, { eventEditable: true }); + } + return processScopedUiProps('event', rawOpts, this); + }; + // Trigger + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.hasPublicHandlers = function (name) { + return this.hasHandlers(name) || + this.opt(name); // handler specified in options + }; + Calendar.prototype.publiclyTrigger = function (name, args) { + var optHandler = this.opt(name); + this.triggerWith(name, this, args); + if (optHandler) { + return optHandler.apply(this, args); + } + }; + Calendar.prototype.publiclyTriggerAfterSizing = function (name, args) { + var afterSizingTriggers = this.afterSizingTriggers; + (afterSizingTriggers[name] || (afterSizingTriggers[name] = [])).push(args); + }; + Calendar.prototype.releaseAfterSizingTriggers = function () { + var afterSizingTriggers = this.afterSizingTriggers; + for (var name_4 in afterSizingTriggers) { + for (var _i = 0, _a = afterSizingTriggers[name_4]; _i < _a.length; _i++) { + var args = _a[_i]; + this.publiclyTrigger(name_4, args); + } + } + this.afterSizingTriggers = {}; + }; + // View + // ----------------------------------------------------------------------------------------------------------------- + // Returns a boolean about whether the view is okay to instantiate at some point + Calendar.prototype.isValidViewType = function (viewType) { + return Boolean(this.viewSpecs[viewType]); + }; + Calendar.prototype.changeView = function (viewType, dateOrRange) { + var dateMarker = null; + if (dateOrRange) { + if (dateOrRange.start && dateOrRange.end) { // a range + this.optionsManager.mutate({ visibleRange: dateOrRange }, []); // will not rerender + this.handleOptions(this.optionsManager.computed); // ...but yuck + } + else { // a date + dateMarker = this.dateEnv.createMarker(dateOrRange); // just like gotoDate + } + } + this.unselect(); + this.dispatch({ + type: 'SET_VIEW_TYPE', + viewType: viewType, + dateMarker: dateMarker + }); + }; + // Forces navigation to a view for the given date. + // `viewType` can be a specific view name or a generic one like "week" or "day". + // needs to change + Calendar.prototype.zoomTo = function (dateMarker, viewType) { + var spec; + viewType = viewType || 'day'; // day is default zoom + spec = this.viewSpecs[viewType] || + this.getUnitViewSpec(viewType); + this.unselect(); + if (spec) { + this.dispatch({ + type: 'SET_VIEW_TYPE', + viewType: spec.type, + dateMarker: dateMarker + }); + } + else { + this.dispatch({ + type: 'SET_DATE', + dateMarker: dateMarker + }); + } + }; + // Given a duration singular unit, like "week" or "day", finds a matching view spec. + // Preference is given to views that have corresponding buttons. + Calendar.prototype.getUnitViewSpec = function (unit) { + var component = this.component; + var viewTypes = []; + var i; + var spec; + // put views that have buttons first. there will be duplicates, but oh + if (component.header) { + viewTypes.push.apply(viewTypes, component.header.viewsWithButtons); + } + if (component.footer) { + viewTypes.push.apply(viewTypes, component.footer.viewsWithButtons); + } + for (var viewType in this.viewSpecs) { + viewTypes.push(viewType); + } + for (i = 0; i < viewTypes.length; i++) { + spec = this.viewSpecs[viewTypes[i]]; + if (spec) { + if (spec.singleUnit === unit) { + return spec; + } + } + } + }; + // Current Date + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.getInitialDate = function () { + var defaultDateInput = this.opt('defaultDate'); + // compute the initial ambig-timezone date + if (defaultDateInput != null) { + return this.dateEnv.createMarker(defaultDateInput); + } + else { + return this.getNow(); // getNow already returns unzoned + } + }; + Calendar.prototype.prev = function () { + this.unselect(); + this.dispatch({ type: 'PREV' }); + }; + Calendar.prototype.next = function () { + this.unselect(); + this.dispatch({ type: 'NEXT' }); + }; + Calendar.prototype.prevYear = function () { + this.unselect(); + this.dispatch({ + type: 'SET_DATE', + dateMarker: this.dateEnv.addYears(this.state.currentDate, -1) + }); + }; + Calendar.prototype.nextYear = function () { + this.unselect(); + this.dispatch({ + type: 'SET_DATE', + dateMarker: this.dateEnv.addYears(this.state.currentDate, 1) + }); + }; + Calendar.prototype.today = function () { + this.unselect(); + this.dispatch({ + type: 'SET_DATE', + dateMarker: this.getNow() + }); + }; + Calendar.prototype.gotoDate = function (zonedDateInput) { + this.unselect(); + this.dispatch({ + type: 'SET_DATE', + dateMarker: this.dateEnv.createMarker(zonedDateInput) + }); + }; + Calendar.prototype.incrementDate = function (deltaInput) { + var delta = createDuration(deltaInput); + if (delta) { // else, warn about invalid input? + this.unselect(); + this.dispatch({ + type: 'SET_DATE', + dateMarker: this.dateEnv.add(this.state.currentDate, delta) + }); + } + }; + // for external API + Calendar.prototype.getDate = function () { + return this.dateEnv.toDate(this.state.currentDate); + }; + // Date Formatting Utils + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.formatDate = function (d, formatter) { + var dateEnv = this.dateEnv; + return dateEnv.format(dateEnv.createMarker(d), createFormatter(formatter)); + }; + // `settings` is for formatter AND isEndExclusive + Calendar.prototype.formatRange = function (d0, d1, settings) { + var dateEnv = this.dateEnv; + return dateEnv.formatRange(dateEnv.createMarker(d0), dateEnv.createMarker(d1), createFormatter(settings, this.opt('defaultRangeSeparator')), settings); + }; + Calendar.prototype.formatIso = function (d, omitTime) { + var dateEnv = this.dateEnv; + return dateEnv.formatIso(dateEnv.createMarker(d), { omitTime: omitTime }); + }; + // Sizing + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.windowResize = function (ev) { + if (!this.isHandlingWindowResize && + this.component && // why? + ev.target === window // not a jqui resize event + ) { + this.isHandlingWindowResize = true; + this.updateSize(); + this.publiclyTrigger('windowResize', [this.view]); + this.isHandlingWindowResize = false; + } + }; + Calendar.prototype.updateSize = function () { + if (this.component) { // when? + this.component.updateSize(true); + } + }; + // Component Registration + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.registerInteractiveComponent = function (component, settingsInput) { + var settings = parseInteractionSettings(component, settingsInput); + var DEFAULT_INTERACTIONS = [ + EventClicking, + EventHovering + ]; + var interactionClasses = DEFAULT_INTERACTIONS.concat(this.pluginSystem.hooks.componentInteractions); + var interactions = interactionClasses.map(function (interactionClass) { + return new interactionClass(settings); + }); + this.interactionsStore[component.uid] = interactions; + interactionSettingsStore[component.uid] = settings; + }; + Calendar.prototype.unregisterInteractiveComponent = function (component) { + for (var _i = 0, _a = this.interactionsStore[component.uid]; _i < _a.length; _i++) { + var listener = _a[_i]; + listener.destroy(); + } + delete this.interactionsStore[component.uid]; + delete interactionSettingsStore[component.uid]; + }; + // Date Selection / Event Selection / DayClick + // ----------------------------------------------------------------------------------------------------------------- + // this public method receives start/end dates in any format, with any timezone + // NOTE: args were changed from v3 + Calendar.prototype.select = function (dateOrObj, endDate) { + var selectionInput; + if (endDate == null) { + if (dateOrObj.start != null) { + selectionInput = dateOrObj; + } + else { + selectionInput = { + start: dateOrObj, + end: null + }; + } + } + else { + selectionInput = { + start: dateOrObj, + end: endDate + }; + } + var selection = parseDateSpan(selectionInput, this.dateEnv, createDuration({ days: 1 }) // TODO: cache this? + ); + if (selection) { // throw parse error otherwise? + this.dispatch({ type: 'SELECT_DATES', selection: selection }); + this.triggerDateSelect(selection); + } + }; + // public method + Calendar.prototype.unselect = function (pev) { + if (this.state.dateSelection) { + this.dispatch({ type: 'UNSELECT_DATES' }); + this.triggerDateUnselect(pev); + } + }; + Calendar.prototype.triggerDateSelect = function (selection, pev) { + var arg = __assign({}, this.buildDateSpanApi(selection), { jsEvent: pev ? pev.origEvent : null, view: this.view }); + this.publiclyTrigger('select', [arg]); + }; + Calendar.prototype.triggerDateUnselect = function (pev) { + this.publiclyTrigger('unselect', [ + { + jsEvent: pev ? pev.origEvent : null, + view: this.view + } + ]); + }; + // TODO: receive pev? + Calendar.prototype.triggerDateClick = function (dateSpan, dayEl, view, ev) { + var arg = __assign({}, this.buildDatePointApi(dateSpan), { dayEl: dayEl, jsEvent: ev, // Is this always a mouse event? See #4655 + view: view }); + this.publiclyTrigger('dateClick', [arg]); + }; + Calendar.prototype.buildDatePointApi = function (dateSpan) { + var props = {}; + for (var _i = 0, _a = this.pluginSystem.hooks.datePointTransforms; _i < _a.length; _i++) { + var transform = _a[_i]; + __assign(props, transform(dateSpan, this)); + } + __assign(props, buildDatePointApi(dateSpan, this.dateEnv)); + return props; + }; + Calendar.prototype.buildDateSpanApi = function (dateSpan) { + var props = {}; + for (var _i = 0, _a = this.pluginSystem.hooks.dateSpanTransforms; _i < _a.length; _i++) { + var transform = _a[_i]; + __assign(props, transform(dateSpan, this)); + } + __assign(props, buildDateSpanApi(dateSpan, this.dateEnv)); + return props; + }; + // Date Utils + // ----------------------------------------------------------------------------------------------------------------- + // Returns a DateMarker for the current date, as defined by the client's computer or from the `now` option + Calendar.prototype.getNow = function () { + var now = this.opt('now'); + if (typeof now === 'function') { + now = now(); + } + if (now == null) { + return this.dateEnv.createNowMarker(); + } + return this.dateEnv.createMarker(now); + }; + // Event-Date Utilities + // ----------------------------------------------------------------------------------------------------------------- + // Given an event's allDay status and start date, return what its fallback end date should be. + // TODO: rename to computeDefaultEventEnd + Calendar.prototype.getDefaultEventEnd = function (allDay, marker) { + var end = marker; + if (allDay) { + end = startOfDay(end); + end = this.dateEnv.add(end, this.defaultAllDayEventDuration); + } + else { + end = this.dateEnv.add(end, this.defaultTimedEventDuration); + } + return end; + }; + // Public Events API + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.addEvent = function (eventInput, sourceInput) { + if (eventInput instanceof EventApi) { + var def = eventInput._def; + var instance = eventInput._instance; + // not already present? don't want to add an old snapshot + if (!this.state.eventStore.defs[def.defId]) { + this.dispatch({ + type: 'ADD_EVENTS', + eventStore: eventTupleToStore({ def: def, instance: instance }) // TODO: better util for two args? + }); + } + return eventInput; + } + var sourceId; + if (sourceInput instanceof EventSourceApi) { + sourceId = sourceInput.internalEventSource.sourceId; + } + else if (sourceInput != null) { + var sourceApi = this.getEventSourceById(sourceInput); // TODO: use an internal function + if (!sourceApi) { + console.warn('Could not find an event source with ID "' + sourceInput + '"'); // TODO: test + return null; + } + else { + sourceId = sourceApi.internalEventSource.sourceId; + } + } + var tuple = parseEvent(eventInput, sourceId, this); + if (tuple) { + this.dispatch({ + type: 'ADD_EVENTS', + eventStore: eventTupleToStore(tuple) + }); + return new EventApi(this, tuple.def, tuple.def.recurringDef ? null : tuple.instance); + } + return null; + }; + // TODO: optimize + Calendar.prototype.getEventById = function (id) { + var _a = this.state.eventStore, defs = _a.defs, instances = _a.instances; + id = String(id); + for (var defId in defs) { + var def = defs[defId]; + if (def.publicId === id) { + if (def.recurringDef) { + return new EventApi(this, def, null); + } + else { + for (var instanceId in instances) { + var instance = instances[instanceId]; + if (instance.defId === def.defId) { + return new EventApi(this, def, instance); + } + } + } + } + } + return null; + }; + Calendar.prototype.getEvents = function () { + var _a = this.state.eventStore, defs = _a.defs, instances = _a.instances; + var eventApis = []; + for (var id in instances) { + var instance = instances[id]; + var def = defs[instance.defId]; + eventApis.push(new EventApi(this, def, instance)); + } + return eventApis; + }; + Calendar.prototype.removeAllEvents = function () { + this.dispatch({ type: 'REMOVE_ALL_EVENTS' }); + }; + Calendar.prototype.rerenderEvents = function () { + this.dispatch({ type: 'RESET_EVENTS' }); + }; + // Public Event Sources API + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.getEventSources = function () { + var sourceHash = this.state.eventSources; + var sourceApis = []; + for (var internalId in sourceHash) { + sourceApis.push(new EventSourceApi(this, sourceHash[internalId])); + } + return sourceApis; + }; + Calendar.prototype.getEventSourceById = function (id) { + var sourceHash = this.state.eventSources; + id = String(id); + for (var sourceId in sourceHash) { + if (sourceHash[sourceId].publicId === id) { + return new EventSourceApi(this, sourceHash[sourceId]); + } + } + return null; + }; + Calendar.prototype.addEventSource = function (sourceInput) { + if (sourceInput instanceof EventSourceApi) { + // not already present? don't want to add an old snapshot + if (!this.state.eventSources[sourceInput.internalEventSource.sourceId]) { + this.dispatch({ + type: 'ADD_EVENT_SOURCES', + sources: [sourceInput.internalEventSource] + }); + } + return sourceInput; + } + var eventSource = parseEventSource(sourceInput, this); + if (eventSource) { // TODO: error otherwise? + this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: [eventSource] }); + return new EventSourceApi(this, eventSource); + } + return null; + }; + Calendar.prototype.removeAllEventSources = function () { + this.dispatch({ type: 'REMOVE_ALL_EVENT_SOURCES' }); + }; + Calendar.prototype.refetchEvents = function () { + this.dispatch({ type: 'FETCH_EVENT_SOURCES' }); + }; + // Scroll + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.scrollToTime = function (timeInput) { + var duration = createDuration(timeInput); + if (duration) { + this.component.view.scrollToDuration(duration); + } + }; + return Calendar; +}()); +EmitterMixin.mixInto(Calendar); +// for memoizers +// ----------------------------------------------------------------------------------------------------------------- +function buildDateEnv(locale, timeZone, namedTimeZoneImpl, firstDay, weekNumberCalculation, weekLabel, cmdFormatter) { + return new DateEnv({ + calendarSystem: 'gregory', + timeZone: timeZone, + namedTimeZoneImpl: namedTimeZoneImpl, + locale: locale, + weekNumberCalculation: weekNumberCalculation, + firstDay: firstDay, + weekLabel: weekLabel, + cmdFormatter: cmdFormatter + }); +} +function buildTheme(calendarOptions) { + var themeClass = this.pluginSystem.hooks.themeClasses[calendarOptions.themeSystem] || StandardTheme; + return new themeClass(calendarOptions); +} +function buildDelayedRerender(wait) { + var func = this.tryRerender.bind(this); + if (wait != null) { + func = debounce(func, wait); + } + return func; +} +function buildEventUiBySource(eventSources) { + return mapHash(eventSources, function (eventSource) { + return eventSource.ui; + }); +} +function buildEventUiBases(eventDefs, eventUiSingleBase, eventUiBySource) { + var eventUiBases = { '': eventUiSingleBase }; + for (var defId in eventDefs) { + var def = eventDefs[defId]; + if (def.sourceId && eventUiBySource[def.sourceId]) { + eventUiBases[defId] = eventUiBySource[def.sourceId]; + } + } + return eventUiBases; +} + +var View = /** @class */ (function (_super) { + __extends(View, _super); + function View(context, viewSpec, dateProfileGenerator, parentEl) { + var _this = _super.call(this, context, createElement('div', { className: 'fc-view fc-' + viewSpec.type + '-view' }), true // isView (HACK) + ) || this; + _this.renderDatesMem = memoizeRendering(_this.renderDatesWrap, _this.unrenderDatesWrap); + _this.renderBusinessHoursMem = memoizeRendering(_this.renderBusinessHours, _this.unrenderBusinessHours, [_this.renderDatesMem]); + _this.renderDateSelectionMem = memoizeRendering(_this.renderDateSelectionWrap, _this.unrenderDateSelectionWrap, [_this.renderDatesMem]); + _this.renderEventsMem = memoizeRendering(_this.renderEvents, _this.unrenderEvents, [_this.renderDatesMem]); + _this.renderEventSelectionMem = memoizeRendering(_this.renderEventSelectionWrap, _this.unrenderEventSelectionWrap, [_this.renderEventsMem]); + _this.renderEventDragMem = memoizeRendering(_this.renderEventDragWrap, _this.unrenderEventDragWrap, [_this.renderDatesMem]); + _this.renderEventResizeMem = memoizeRendering(_this.renderEventResizeWrap, _this.unrenderEventResizeWrap, [_this.renderDatesMem]); + _this.viewSpec = viewSpec; + _this.dateProfileGenerator = dateProfileGenerator; + _this.type = viewSpec.type; + _this.eventOrderSpecs = parseFieldSpecs(_this.opt('eventOrder')); + _this.nextDayThreshold = createDuration(_this.opt('nextDayThreshold')); + parentEl.appendChild(_this.el); + _this.initialize(); + return _this; + } + View.prototype.initialize = function () { + }; + Object.defineProperty(View.prototype, "activeStart", { + // Date Setting/Unsetting + // ----------------------------------------------------------------------------------------------------------------- + get: function () { + return this.dateEnv.toDate(this.props.dateProfile.activeRange.start); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(View.prototype, "activeEnd", { + get: function () { + return this.dateEnv.toDate(this.props.dateProfile.activeRange.end); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(View.prototype, "currentStart", { + get: function () { + return this.dateEnv.toDate(this.props.dateProfile.currentRange.start); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(View.prototype, "currentEnd", { + get: function () { + return this.dateEnv.toDate(this.props.dateProfile.currentRange.end); + }, + enumerable: true, + configurable: true + }); + // General Rendering + // ----------------------------------------------------------------------------------------------------------------- + View.prototype.render = function (props) { + this.renderDatesMem(props.dateProfile); + this.renderBusinessHoursMem(props.businessHours); + this.renderDateSelectionMem(props.dateSelection); + this.renderEventsMem(props.eventStore); + this.renderEventSelectionMem(props.eventSelection); + this.renderEventDragMem(props.eventDrag); + this.renderEventResizeMem(props.eventResize); + }; + View.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.renderDatesMem.unrender(); // should unrender everything else + }; + // Sizing + // ----------------------------------------------------------------------------------------------------------------- + View.prototype.updateSize = function (isResize, viewHeight, isAuto) { + var calendar = this.calendar; + if (isResize || // HACKS... + calendar.isViewUpdated || + calendar.isDatesUpdated || + calendar.isEventsUpdated) { + // sort of the catch-all sizing + // anything that might cause dimension changes + this.updateBaseSize(isResize, viewHeight, isAuto); + } + }; + View.prototype.updateBaseSize = function (isResize, viewHeight, isAuto) { + }; + // Date Rendering + // ----------------------------------------------------------------------------------------------------------------- + View.prototype.renderDatesWrap = function (dateProfile) { + this.renderDates(dateProfile); + this.addScroll({ + duration: createDuration(this.opt('scrollTime')) + }); + this.startNowIndicator(dateProfile); // shouldn't render yet because updateSize will be called soon + }; + View.prototype.unrenderDatesWrap = function () { + this.stopNowIndicator(); + this.unrenderDates(); + }; + View.prototype.renderDates = function (dateProfile) { }; + View.prototype.unrenderDates = function () { }; + // Business Hours + // ----------------------------------------------------------------------------------------------------------------- + View.prototype.renderBusinessHours = function (businessHours) { }; + View.prototype.unrenderBusinessHours = function () { }; + // Date Selection + // ----------------------------------------------------------------------------------------------------------------- + View.prototype.renderDateSelectionWrap = function (selection) { + if (selection) { + this.renderDateSelection(selection); + } + }; + View.prototype.unrenderDateSelectionWrap = function (selection) { + if (selection) { + this.unrenderDateSelection(selection); + } + }; + View.prototype.renderDateSelection = function (selection) { }; + View.prototype.unrenderDateSelection = function (selection) { }; + // Event Rendering + // ----------------------------------------------------------------------------------------------------------------- + View.prototype.renderEvents = function (eventStore) { }; + View.prototype.unrenderEvents = function () { }; + // util for subclasses + View.prototype.sliceEvents = function (eventStore, allDay) { + var props = this.props; + return sliceEventStore(eventStore, props.eventUiBases, props.dateProfile.activeRange, allDay ? this.nextDayThreshold : null).fg; + }; + View.prototype.computeEventDraggable = function (eventDef, eventUi) { + var transformers = this.calendar.pluginSystem.hooks.isDraggableTransformers; + var val = eventUi.startEditable; + for (var _i = 0, transformers_1 = transformers; _i < transformers_1.length; _i++) { + var transformer = transformers_1[_i]; + val = transformer(val, eventDef, eventUi, this); + } + return val; + }; + View.prototype.computeEventStartResizable = function (eventDef, eventUi) { + return eventUi.durationEditable && this.opt('eventResizableFromStart'); + }; + View.prototype.computeEventEndResizable = function (eventDef, eventUi) { + return eventUi.durationEditable; + }; + // Event Selection + // ----------------------------------------------------------------------------------------------------------------- + View.prototype.renderEventSelectionWrap = function (instanceId) { + if (instanceId) { + this.renderEventSelection(instanceId); + } + }; + View.prototype.unrenderEventSelectionWrap = function (instanceId) { + if (instanceId) { + this.unrenderEventSelection(instanceId); + } + }; + View.prototype.renderEventSelection = function (instanceId) { }; + View.prototype.unrenderEventSelection = function (instanceId) { }; + // Event Drag + // ----------------------------------------------------------------------------------------------------------------- + View.prototype.renderEventDragWrap = function (state) { + if (state) { + this.renderEventDrag(state); + } + }; + View.prototype.unrenderEventDragWrap = function (state) { + if (state) { + this.unrenderEventDrag(state); + } + }; + View.prototype.renderEventDrag = function (state) { }; + View.prototype.unrenderEventDrag = function (state) { }; + // Event Resize + // ----------------------------------------------------------------------------------------------------------------- + View.prototype.renderEventResizeWrap = function (state) { + if (state) { + this.renderEventResize(state); + } + }; + View.prototype.unrenderEventResizeWrap = function (state) { + if (state) { + this.unrenderEventResize(state); + } + }; + View.prototype.renderEventResize = function (state) { }; + View.prototype.unrenderEventResize = function (state) { }; + /* Now Indicator + ------------------------------------------------------------------------------------------------------------------*/ + // Immediately render the current time indicator and begins re-rendering it at an interval, + // which is defined by this.getNowIndicatorUnit(). + // TODO: somehow do this for the current whole day's background too + View.prototype.startNowIndicator = function (dateProfile) { + var _this = this; + var dateEnv = this.dateEnv; + var unit; + var update; + var delay; // ms wait value + if (this.opt('nowIndicator')) { + unit = this.getNowIndicatorUnit(dateProfile); + if (unit) { + update = this.updateNowIndicator.bind(this); + this.initialNowDate = this.calendar.getNow(); + this.initialNowQueriedMs = new Date().valueOf(); + // wait until the beginning of the next interval + delay = dateEnv.add(dateEnv.startOf(this.initialNowDate, unit), createDuration(1, unit)).valueOf() - this.initialNowDate.valueOf(); + // TODO: maybe always use setTimeout, waiting until start of next unit + this.nowIndicatorTimeoutID = setTimeout(function () { + _this.nowIndicatorTimeoutID = null; + update(); + if (unit === 'second') { + delay = 1000; // every second + } + else { + delay = 1000 * 60; // otherwise, every minute + } + _this.nowIndicatorIntervalID = setInterval(update, delay); // update every interval + }, delay); + } + // rendering will be initiated in updateSize + } + }; + // rerenders the now indicator, computing the new current time from the amount of time that has passed + // since the initial getNow call. + View.prototype.updateNowIndicator = function () { + if (this.props.dateProfile && // a way to determine if dates were rendered yet + this.initialNowDate // activated before? + ) { + this.unrenderNowIndicator(); // won't unrender if unnecessary + this.renderNowIndicator(addMs(this.initialNowDate, new Date().valueOf() - this.initialNowQueriedMs)); + this.isNowIndicatorRendered = true; + } + }; + // Immediately unrenders the view's current time indicator and stops any re-rendering timers. + // Won't cause side effects if indicator isn't rendered. + View.prototype.stopNowIndicator = function () { + if (this.isNowIndicatorRendered) { + if (this.nowIndicatorTimeoutID) { + clearTimeout(this.nowIndicatorTimeoutID); + this.nowIndicatorTimeoutID = null; + } + if (this.nowIndicatorIntervalID) { + clearInterval(this.nowIndicatorIntervalID); + this.nowIndicatorIntervalID = null; + } + this.unrenderNowIndicator(); + this.isNowIndicatorRendered = false; + } + }; + View.prototype.getNowIndicatorUnit = function (dateProfile) { + // subclasses should implement + }; + // Renders a current time indicator at the given datetime + View.prototype.renderNowIndicator = function (date) { + // SUBCLASSES MUST PASS TO CHILDREN! + }; + // Undoes the rendering actions from renderNowIndicator + View.prototype.unrenderNowIndicator = function () { + // SUBCLASSES MUST PASS TO CHILDREN! + }; + /* Scroller + ------------------------------------------------------------------------------------------------------------------*/ + View.prototype.addScroll = function (scroll) { + var queuedScroll = this.queuedScroll || (this.queuedScroll = {}); + __assign(queuedScroll, scroll); + }; + View.prototype.popScroll = function (isResize) { + this.applyQueuedScroll(isResize); + this.queuedScroll = null; + }; + View.prototype.applyQueuedScroll = function (isResize) { + this.applyScroll(this.queuedScroll || {}, isResize); + }; + View.prototype.queryScroll = function () { + var scroll = {}; + if (this.props.dateProfile) { // dates rendered yet? + __assign(scroll, this.queryDateScroll()); + } + return scroll; + }; + View.prototype.applyScroll = function (scroll, isResize) { + var duration = scroll.duration; + if (duration != null) { + delete scroll.duration; + if (this.props.dateProfile) { // dates rendered yet? + __assign(scroll, this.computeDateScroll(duration)); + } + } + if (this.props.dateProfile) { // dates rendered yet? + this.applyDateScroll(scroll); + } + }; + View.prototype.computeDateScroll = function (duration) { + return {}; // subclasses must implement + }; + View.prototype.queryDateScroll = function () { + return {}; // subclasses must implement + }; + View.prototype.applyDateScroll = function (scroll) { + // subclasses must implement + }; + // for API + View.prototype.scrollToDuration = function (duration) { + this.applyScroll({ duration: duration }, false); + }; + return View; +}(DateComponent)); +EmitterMixin.mixInto(View); +View.prototype.usesMinMaxTime = false; +View.prototype.dateProfileGeneratorClass = DateProfileGenerator; + +var FgEventRenderer = /** @class */ (function () { + function FgEventRenderer(context) { + this.segs = []; + this.isSizeDirty = false; + this.context = context; + } + FgEventRenderer.prototype.renderSegs = function (segs, mirrorInfo) { + this.rangeUpdated(); // called too frequently :( + // render an `.el` on each seg + // returns a subset of the segs. segs that were actually rendered + segs = this.renderSegEls(segs, mirrorInfo); + this.segs = segs; + this.attachSegs(segs, mirrorInfo); + this.isSizeDirty = true; + this.context.view.triggerRenderedSegs(this.segs, Boolean(mirrorInfo)); + }; + FgEventRenderer.prototype.unrender = function (_segs, mirrorInfo) { + this.context.view.triggerWillRemoveSegs(this.segs, Boolean(mirrorInfo)); + this.detachSegs(this.segs); + this.segs = []; + }; + // Updates values that rely on options and also relate to range + FgEventRenderer.prototype.rangeUpdated = function () { + var options = this.context.options; + var displayEventTime; + var displayEventEnd; + this.eventTimeFormat = createFormatter(options.eventTimeFormat || this.computeEventTimeFormat(), options.defaultRangeSeparator); + displayEventTime = options.displayEventTime; + if (displayEventTime == null) { + displayEventTime = this.computeDisplayEventTime(); // might be based off of range + } + displayEventEnd = options.displayEventEnd; + if (displayEventEnd == null) { + displayEventEnd = this.computeDisplayEventEnd(); // might be based off of range + } + this.displayEventTime = displayEventTime; + this.displayEventEnd = displayEventEnd; + }; + // Renders and assigns an `el` property for each foreground event segment. + // Only returns segments that successfully rendered. + FgEventRenderer.prototype.renderSegEls = function (segs, mirrorInfo) { + var html = ''; + var i; + if (segs.length) { // don't build an empty html string + // build a large concatenation of event segment HTML + for (i = 0; i < segs.length; i++) { + html += this.renderSegHtml(segs[i], mirrorInfo); + } + // Grab individual elements from the combined HTML string. Use each as the default rendering. + // Then, compute the 'el' for each segment. An el might be null if the eventRender callback returned false. + htmlToElements(html).forEach(function (el, i) { + var seg = segs[i]; + if (el) { + seg.el = el; + } + }); + segs = filterSegsViaEls(this.context.view, segs, Boolean(mirrorInfo)); + } + return segs; + }; + // Generic utility for generating the HTML classNames for an event segment's element + FgEventRenderer.prototype.getSegClasses = function (seg, isDraggable, isResizable, mirrorInfo) { + var classes = [ + 'fc-event', + seg.isStart ? 'fc-start' : 'fc-not-start', + seg.isEnd ? 'fc-end' : 'fc-not-end' + ].concat(seg.eventRange.ui.classNames); + if (isDraggable) { + classes.push('fc-draggable'); + } + if (isResizable) { + classes.push('fc-resizable'); + } + if (mirrorInfo) { + classes.push('fc-mirror'); + if (mirrorInfo.isDragging) { + classes.push('fc-dragging'); + } + if (mirrorInfo.isResizing) { + classes.push('fc-resizing'); + } + } + return classes; + }; + // Compute the text that should be displayed on an event's element. + // `range` can be the Event object itself, or something range-like, with at least a `start`. + // If event times are disabled, or the event has no time, will return a blank string. + // If not specified, formatter will default to the eventTimeFormat setting, + // and displayEnd will default to the displayEventEnd setting. + FgEventRenderer.prototype.getTimeText = function (eventRange, formatter, displayEnd) { + var def = eventRange.def, instance = eventRange.instance; + return this._getTimeText(instance.range.start, def.hasEnd ? instance.range.end : null, def.allDay, formatter, displayEnd, instance.forcedStartTzo, instance.forcedEndTzo); + }; + FgEventRenderer.prototype._getTimeText = function (start, end, allDay, formatter, displayEnd, forcedStartTzo, forcedEndTzo) { + var dateEnv = this.context.dateEnv; + if (formatter == null) { + formatter = this.eventTimeFormat; + } + if (displayEnd == null) { + displayEnd = this.displayEventEnd; + } + if (this.displayEventTime && !allDay) { + if (displayEnd && end) { + return dateEnv.formatRange(start, end, formatter, { + forcedStartTzo: forcedStartTzo, + forcedEndTzo: forcedEndTzo + }); + } + else { + return dateEnv.format(start, formatter, { + forcedTzo: forcedStartTzo + }); + } + } + return ''; + }; + FgEventRenderer.prototype.computeEventTimeFormat = function () { + return { + hour: 'numeric', + minute: '2-digit', + omitZeroMinute: true + }; + }; + FgEventRenderer.prototype.computeDisplayEventTime = function () { + return true; + }; + FgEventRenderer.prototype.computeDisplayEventEnd = function () { + return true; + }; + // Utility for generating event skin-related CSS properties + FgEventRenderer.prototype.getSkinCss = function (ui) { + return { + 'background-color': ui.backgroundColor, + 'border-color': ui.borderColor, + color: ui.textColor + }; + }; + FgEventRenderer.prototype.sortEventSegs = function (segs) { + var specs = this.context.view.eventOrderSpecs; + var objs = segs.map(buildSegCompareObj); + objs.sort(function (obj0, obj1) { + return compareByFieldSpecs(obj0, obj1, specs); + }); + return objs.map(function (c) { + return c._seg; + }); + }; + FgEventRenderer.prototype.computeSizes = function (force) { + if (force || this.isSizeDirty) { + this.computeSegSizes(this.segs); + } + }; + FgEventRenderer.prototype.assignSizes = function (force) { + if (force || this.isSizeDirty) { + this.assignSegSizes(this.segs); + this.isSizeDirty = false; + } + }; + FgEventRenderer.prototype.computeSegSizes = function (segs) { + }; + FgEventRenderer.prototype.assignSegSizes = function (segs) { + }; + // Manipulation on rendered segs + FgEventRenderer.prototype.hideByHash = function (hash) { + if (hash) { + for (var _i = 0, _a = this.segs; _i < _a.length; _i++) { + var seg = _a[_i]; + if (hash[seg.eventRange.instance.instanceId]) { + seg.el.style.visibility = 'hidden'; + } + } + } + }; + FgEventRenderer.prototype.showByHash = function (hash) { + if (hash) { + for (var _i = 0, _a = this.segs; _i < _a.length; _i++) { + var seg = _a[_i]; + if (hash[seg.eventRange.instance.instanceId]) { + seg.el.style.visibility = ''; + } + } + } + }; + FgEventRenderer.prototype.selectByInstanceId = function (instanceId) { + if (instanceId) { + for (var _i = 0, _a = this.segs; _i < _a.length; _i++) { + var seg = _a[_i]; + var eventInstance = seg.eventRange.instance; + if (eventInstance && eventInstance.instanceId === instanceId && + seg.el // necessary? + ) { + seg.el.classList.add('fc-selected'); + } + } + } + }; + FgEventRenderer.prototype.unselectByInstanceId = function (instanceId) { + if (instanceId) { + for (var _i = 0, _a = this.segs; _i < _a.length; _i++) { + var seg = _a[_i]; + if (seg.el) { // necessary? + seg.el.classList.remove('fc-selected'); + } + } + } + }; + return FgEventRenderer; +}()); +// returns a object with all primitive props that can be compared +function buildSegCompareObj(seg) { + var eventDef = seg.eventRange.def; + var range = seg.eventRange.instance.range; + var start = range.start ? range.start.valueOf() : 0; // TODO: better support for open-range events + var end = range.end ? range.end.valueOf() : 0; // " + return __assign({}, eventDef.extendedProps, eventDef, { id: eventDef.publicId, start: start, + end: end, duration: end - start, allDay: Number(eventDef.allDay), _seg: seg // for later retrieval + }); +} + +var FillRenderer = /** @class */ (function () { + function FillRenderer(context) { + this.fillSegTag = 'div'; + this.dirtySizeFlags = {}; + this.context = context; + this.containerElsByType = {}; + this.segsByType = {}; + } + FillRenderer.prototype.getSegsByType = function (type) { + return this.segsByType[type] || []; + }; + FillRenderer.prototype.renderSegs = function (type, segs) { + var _a; + var renderedSegs = this.renderSegEls(type, segs); // assignes `.el` to each seg. returns successfully rendered segs + var containerEls = this.attachSegs(type, renderedSegs); + if (containerEls) { + (_a = (this.containerElsByType[type] || (this.containerElsByType[type] = []))).push.apply(_a, containerEls); + } + this.segsByType[type] = renderedSegs; + if (type === 'bgEvent') { + this.context.view.triggerRenderedSegs(renderedSegs, false); // isMirror=false + } + this.dirtySizeFlags[type] = true; + }; + // Unrenders a specific type of fill that is currently rendered on the grid + FillRenderer.prototype.unrender = function (type) { + var segs = this.segsByType[type]; + if (segs) { + if (type === 'bgEvent') { + this.context.view.triggerWillRemoveSegs(segs, false); // isMirror=false + } + this.detachSegs(type, segs); + } + }; + // Renders and assigns an `el` property for each fill segment. Generic enough to work with different types. + // Only returns segments that successfully rendered. + FillRenderer.prototype.renderSegEls = function (type, segs) { + var _this = this; + var html = ''; + var i; + if (segs.length) { + // build a large concatenation of segment HTML + for (i = 0; i < segs.length; i++) { + html += this.renderSegHtml(type, segs[i]); + } + // Grab individual elements from the combined HTML string. Use each as the default rendering. + // Then, compute the 'el' for each segment. + htmlToElements(html).forEach(function (el, i) { + var seg = segs[i]; + if (el) { + seg.el = el; + } + }); + if (type === 'bgEvent') { + segs = filterSegsViaEls(this.context.view, segs, false // isMirror. background events can never be mirror elements + ); + } + // correct element type? (would be bad if a non-TD were inserted into a table for example) + segs = segs.filter(function (seg) { + return elementMatches(seg.el, _this.fillSegTag); + }); + } + return segs; + }; + // Builds the HTML needed for one fill segment. Generic enough to work with different types. + FillRenderer.prototype.renderSegHtml = function (type, seg) { + var css = null; + var classNames = []; + if (type !== 'highlight' && type !== 'businessHours') { + css = { + 'background-color': seg.eventRange.ui.backgroundColor + }; + } + if (type !== 'highlight') { + classNames = classNames.concat(seg.eventRange.ui.classNames); + } + if (type === 'businessHours') { + classNames.push('fc-bgevent'); + } + else { + classNames.push('fc-' + type.toLowerCase()); + } + return '<' + this.fillSegTag + + (classNames.length ? ' class="' + classNames.join(' ') + '"' : '') + + (css ? ' style="' + cssToStr(css) + '"' : '') + + '></' + this.fillSegTag + '>'; + }; + FillRenderer.prototype.detachSegs = function (type, segs) { + var containerEls = this.containerElsByType[type]; + if (containerEls) { + containerEls.forEach(removeElement); + delete this.containerElsByType[type]; + } + }; + FillRenderer.prototype.computeSizes = function (force) { + for (var type in this.segsByType) { + if (force || this.dirtySizeFlags[type]) { + this.computeSegSizes(this.segsByType[type]); + } + } + }; + FillRenderer.prototype.assignSizes = function (force) { + for (var type in this.segsByType) { + if (force || this.dirtySizeFlags[type]) { + this.assignSegSizes(this.segsByType[type]); + } + } + this.dirtySizeFlags = {}; + }; + FillRenderer.prototype.computeSegSizes = function (segs) { + }; + FillRenderer.prototype.assignSegSizes = function (segs) { + }; + return FillRenderer; +}()); + +var NamedTimeZoneImpl = /** @class */ (function () { + function NamedTimeZoneImpl(timeZoneName) { + this.timeZoneName = timeZoneName; + } + return NamedTimeZoneImpl; +}()); + +/* +An abstraction for a dragging interaction originating on an event. +Does higher-level things than PointerDragger, such as possibly: +- a "mirror" that moves with the pointer +- a minimum number of pixels or other criteria for a true drag to begin + +subclasses must emit: +- pointerdown +- dragstart +- dragmove +- pointerup +- dragend +*/ +var ElementDragging = /** @class */ (function () { + function ElementDragging(el) { + this.emitter = new EmitterMixin(); + } + ElementDragging.prototype.destroy = function () { + }; + ElementDragging.prototype.setMirrorIsVisible = function (bool) { + // optional if subclass doesn't want to support a mirror + }; + ElementDragging.prototype.setMirrorNeedsRevert = function (bool) { + // optional if subclass doesn't want to support a mirror + }; + ElementDragging.prototype.setAutoScrollEnabled = function (bool) { + // optional + }; + return ElementDragging; +}()); + +function formatDate(dateInput, settings) { + if (settings === void 0) { settings = {}; } + var dateEnv = buildDateEnv$1(settings); + var formatter = createFormatter(settings); + var dateMeta = dateEnv.createMarkerMeta(dateInput); + if (!dateMeta) { // TODO: warning? + return ''; + } + return dateEnv.format(dateMeta.marker, formatter, { + forcedTzo: dateMeta.forcedTzo + }); +} +function formatRange(startInput, endInput, settings // mixture of env and formatter settings +) { + var dateEnv = buildDateEnv$1(typeof settings === 'object' && settings ? settings : {}); // pass in if non-null object + var formatter = createFormatter(settings, globalDefaults.defaultRangeSeparator); + var startMeta = dateEnv.createMarkerMeta(startInput); + var endMeta = dateEnv.createMarkerMeta(endInput); + if (!startMeta || !endMeta) { // TODO: warning? + return ''; + } + return dateEnv.formatRange(startMeta.marker, endMeta.marker, formatter, { + forcedStartTzo: startMeta.forcedTzo, + forcedEndTzo: endMeta.forcedTzo, + isEndExclusive: settings.isEndExclusive + }); +} +// TODO: more DRY and optimized +function buildDateEnv$1(settings) { + var locale = buildLocale(settings.locale || 'en', parseRawLocales([]).map); // TODO: don't hardcode 'en' everywhere + // ensure required settings + settings = __assign({ timeZone: globalDefaults.timeZone, calendarSystem: 'gregory' }, settings, { locale: locale }); + return new DateEnv(settings); +} + +var DRAG_META_PROPS = { + startTime: createDuration, + duration: createDuration, + create: Boolean, + sourceId: String +}; +var DRAG_META_DEFAULTS = { + create: true +}; +function parseDragMeta(raw) { + var leftoverProps = {}; + var refined = refineProps(raw, DRAG_META_PROPS, DRAG_META_DEFAULTS, leftoverProps); + refined.leftoverProps = leftoverProps; + return refined; +} + +// Computes a default column header formatting string if `colFormat` is not explicitly defined +function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) { + // if more than one week row, or if there are a lot of columns with not much space, + // put just the day numbers will be in each cell + if (!datesRepDistinctDays || dayCnt > 10) { + return { weekday: 'short' }; // "Sat" + } + else if (dayCnt > 1) { + return { weekday: 'short', month: 'numeric', day: 'numeric', omitCommas: true }; // "Sat 11/12" + } + else { + return { weekday: 'long' }; // "Saturday" + } +} +function renderDateCell(dateMarker, dateProfile, datesRepDistinctDays, colCnt, colHeadFormat, context, colspan, otherAttrs) { + var view = context.view, dateEnv = context.dateEnv, theme = context.theme, options = context.options; + var isDateValid = rangeContainsMarker(dateProfile.activeRange, dateMarker); // TODO: called too frequently. cache somehow. + var classNames = [ + 'fc-day-header', + theme.getClass('widgetHeader') + ]; + var innerHtml; + if (typeof options.columnHeaderHtml === 'function') { + innerHtml = options.columnHeaderHtml(dateEnv.toDate(dateMarker)); + } + else if (typeof options.columnHeaderText === 'function') { + innerHtml = htmlEscape(options.columnHeaderText(dateEnv.toDate(dateMarker))); + } + else { + innerHtml = htmlEscape(dateEnv.format(dateMarker, colHeadFormat)); + } + // if only one row of days, the classNames on the header can represent the specific days beneath + if (datesRepDistinctDays) { + classNames = classNames.concat( + // includes the day-of-week class + // noThemeHighlight=true (don't highlight the header) + getDayClasses(dateMarker, dateProfile, context, true)); + } + else { + classNames.push('fc-' + DAY_IDS[dateMarker.getUTCDay()]); // only add the day-of-week class + } + return '' + + '<th class="' + classNames.join(' ') + '"' + + ((isDateValid && datesRepDistinctDays) ? + ' data-date="' + dateEnv.formatIso(dateMarker, { omitTime: true }) + '"' : + '') + + (colspan > 1 ? + ' colspan="' + colspan + '"' : + '') + + (otherAttrs ? + ' ' + otherAttrs : + '') + + '>' + + (isDateValid ? + // don't make a link if the heading could represent multiple days, or if there's only one day (forceOff) + buildGotoAnchorHtml(view, { date: dateMarker, forceOff: !datesRepDistinctDays || colCnt === 1 }, innerHtml) : + // if not valid, display text, but no link + innerHtml) + + '</th>'; +} + +var DayHeader = /** @class */ (function (_super) { + __extends(DayHeader, _super); + function DayHeader(context, parentEl) { + var _this = _super.call(this, context) || this; + parentEl.innerHTML = ''; // because might be nbsp + parentEl.appendChild(_this.el = htmlToElement('<div class="fc-row ' + _this.theme.getClass('headerRow') + '">' + + '<table class="' + _this.theme.getClass('tableGrid') + '">' + + '<thead></thead>' + + '</table>' + + '</div>')); + _this.thead = _this.el.querySelector('thead'); + return _this; + } + DayHeader.prototype.destroy = function () { + removeElement(this.el); + }; + DayHeader.prototype.render = function (props) { + var dates = props.dates, datesRepDistinctDays = props.datesRepDistinctDays; + var parts = []; + if (props.renderIntroHtml) { + parts.push(props.renderIntroHtml()); + } + var colHeadFormat = createFormatter(this.opt('columnHeaderFormat') || + computeFallbackHeaderFormat(datesRepDistinctDays, dates.length)); + for (var _i = 0, dates_1 = dates; _i < dates_1.length; _i++) { + var date = dates_1[_i]; + parts.push(renderDateCell(date, props.dateProfile, datesRepDistinctDays, dates.length, colHeadFormat, this.context)); + } + if (this.isRtl) { + parts.reverse(); + } + this.thead.innerHTML = '<tr>' + parts.join('') + '</tr>'; + }; + return DayHeader; +}(Component)); + +var DaySeries = /** @class */ (function () { + function DaySeries(range, dateProfileGenerator) { + var date = range.start; + var end = range.end; + var indices = []; + var dates = []; + var dayIndex = -1; + while (date < end) { // loop each day from start to end + if (dateProfileGenerator.isHiddenDay(date)) { + indices.push(dayIndex + 0.5); // mark that it's between indices + } + else { + dayIndex++; + indices.push(dayIndex); + dates.push(date); + } + date = addDays(date, 1); + } + this.dates = dates; + this.indices = indices; + this.cnt = dates.length; + } + DaySeries.prototype.sliceRange = function (range) { + var firstIndex = this.getDateDayIndex(range.start); // inclusive first index + var lastIndex = this.getDateDayIndex(addDays(range.end, -1)); // inclusive last index + var clippedFirstIndex = Math.max(0, firstIndex); + var clippedLastIndex = Math.min(this.cnt - 1, lastIndex); + // deal with in-between indices + clippedFirstIndex = Math.ceil(clippedFirstIndex); // in-between starts round to next cell + clippedLastIndex = Math.floor(clippedLastIndex); // in-between ends round to prev cell + if (clippedFirstIndex <= clippedLastIndex) { + return { + firstIndex: clippedFirstIndex, + lastIndex: clippedLastIndex, + isStart: firstIndex === clippedFirstIndex, + isEnd: lastIndex === clippedLastIndex + }; + } + else { + return null; + } + }; + // Given a date, returns its chronolocial cell-index from the first cell of the grid. + // If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets. + // If before the first offset, returns a negative number. + // If after the last offset, returns an offset past the last cell offset. + // Only works for *start* dates of cells. Will not work for exclusive end dates for cells. + DaySeries.prototype.getDateDayIndex = function (date) { + var indices = this.indices; + var dayOffset = Math.floor(diffDays(this.dates[0], date)); + if (dayOffset < 0) { + return indices[0] - 1; + } + else if (dayOffset >= indices.length) { + return indices[indices.length - 1] + 1; + } + else { + return indices[dayOffset]; + } + }; + return DaySeries; +}()); + +var DayTable = /** @class */ (function () { + function DayTable(daySeries, breakOnWeeks) { + var dates = daySeries.dates; + var daysPerRow; + var firstDay; + var rowCnt; + if (breakOnWeeks) { + // count columns until the day-of-week repeats + firstDay = dates[0].getUTCDay(); + for (daysPerRow = 1; daysPerRow < dates.length; daysPerRow++) { + if (dates[daysPerRow].getUTCDay() === firstDay) { + break; + } + } + rowCnt = Math.ceil(dates.length / daysPerRow); + } + else { + rowCnt = 1; + daysPerRow = dates.length; + } + this.rowCnt = rowCnt; + this.colCnt = daysPerRow; + this.daySeries = daySeries; + this.cells = this.buildCells(); + this.headerDates = this.buildHeaderDates(); + } + DayTable.prototype.buildCells = function () { + var rows = []; + for (var row = 0; row < this.rowCnt; row++) { + var cells = []; + for (var col = 0; col < this.colCnt; col++) { + cells.push(this.buildCell(row, col)); + } + rows.push(cells); + } + return rows; + }; + DayTable.prototype.buildCell = function (row, col) { + return { + date: this.daySeries.dates[row * this.colCnt + col] + }; + }; + DayTable.prototype.buildHeaderDates = function () { + var dates = []; + for (var col = 0; col < this.colCnt; col++) { + dates.push(this.cells[0][col].date); + } + return dates; + }; + DayTable.prototype.sliceRange = function (range) { + var colCnt = this.colCnt; + var seriesSeg = this.daySeries.sliceRange(range); + var segs = []; + if (seriesSeg) { + var firstIndex = seriesSeg.firstIndex, lastIndex = seriesSeg.lastIndex; + var index = firstIndex; + while (index <= lastIndex) { + var row = Math.floor(index / colCnt); + var nextIndex = Math.min((row + 1) * colCnt, lastIndex + 1); + segs.push({ + row: row, + firstCol: index % colCnt, + lastCol: (nextIndex - 1) % colCnt, + isStart: seriesSeg.isStart && index === firstIndex, + isEnd: seriesSeg.isEnd && (nextIndex - 1) === lastIndex + }); + index = nextIndex; + } + } + return segs; + }; + return DayTable; +}()); + +var Slicer = /** @class */ (function () { + function Slicer() { + this.sliceBusinessHours = memoize(this._sliceBusinessHours); + this.sliceDateSelection = memoize(this._sliceDateSpan); + this.sliceEventStore = memoize(this._sliceEventStore); + this.sliceEventDrag = memoize(this._sliceInteraction); + this.sliceEventResize = memoize(this._sliceInteraction); + } + Slicer.prototype.sliceProps = function (props, dateProfile, nextDayThreshold, component) { + var extraArgs = []; + for (var _i = 4; _i < arguments.length; _i++) { + extraArgs[_i - 4] = arguments[_i]; + } + var eventUiBases = props.eventUiBases; + var eventSegs = this.sliceEventStore.apply(this, [props.eventStore, eventUiBases, dateProfile, nextDayThreshold, component].concat(extraArgs)); + return { + dateSelectionSegs: this.sliceDateSelection.apply(this, [props.dateSelection, eventUiBases, component].concat(extraArgs)), + businessHourSegs: this.sliceBusinessHours.apply(this, [props.businessHours, dateProfile, nextDayThreshold, component].concat(extraArgs)), + fgEventSegs: eventSegs.fg, + bgEventSegs: eventSegs.bg, + eventDrag: this.sliceEventDrag.apply(this, [props.eventDrag, eventUiBases, dateProfile, nextDayThreshold, component].concat(extraArgs)), + eventResize: this.sliceEventResize.apply(this, [props.eventResize, eventUiBases, dateProfile, nextDayThreshold, component].concat(extraArgs)), + eventSelection: props.eventSelection + }; // TODO: give interactionSegs? + }; + Slicer.prototype.sliceNowDate = function (// does not memoize + date, component) { + var extraArgs = []; + for (var _i = 2; _i < arguments.length; _i++) { + extraArgs[_i - 2] = arguments[_i]; + } + return this._sliceDateSpan.apply(this, [{ range: { start: date, end: addMs(date, 1) }, allDay: false }, + {}, + component].concat(extraArgs)); + }; + Slicer.prototype._sliceBusinessHours = function (businessHours, dateProfile, nextDayThreshold, component) { + var extraArgs = []; + for (var _i = 4; _i < arguments.length; _i++) { + extraArgs[_i - 4] = arguments[_i]; + } + if (!businessHours) { + return []; + } + return this._sliceEventStore.apply(this, [expandRecurring(businessHours, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), component.calendar), + {}, + dateProfile, + nextDayThreshold, + component].concat(extraArgs)).bg; + }; + Slicer.prototype._sliceEventStore = function (eventStore, eventUiBases, dateProfile, nextDayThreshold, component) { + var extraArgs = []; + for (var _i = 5; _i < arguments.length; _i++) { + extraArgs[_i - 5] = arguments[_i]; + } + if (eventStore) { + var rangeRes = sliceEventStore(eventStore, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold); + return { + bg: this.sliceEventRanges(rangeRes.bg, component, extraArgs), + fg: this.sliceEventRanges(rangeRes.fg, component, extraArgs) + }; + } + else { + return { bg: [], fg: [] }; + } + }; + Slicer.prototype._sliceInteraction = function (interaction, eventUiBases, dateProfile, nextDayThreshold, component) { + var extraArgs = []; + for (var _i = 5; _i < arguments.length; _i++) { + extraArgs[_i - 5] = arguments[_i]; + } + if (!interaction) { + return null; + } + var rangeRes = sliceEventStore(interaction.mutatedEvents, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold); + return { + segs: this.sliceEventRanges(rangeRes.fg, component, extraArgs), + affectedInstances: interaction.affectedEvents.instances, + isEvent: interaction.isEvent, + sourceSeg: interaction.origSeg + }; + }; + Slicer.prototype._sliceDateSpan = function (dateSpan, eventUiBases, component) { + var extraArgs = []; + for (var _i = 3; _i < arguments.length; _i++) { + extraArgs[_i - 3] = arguments[_i]; + } + if (!dateSpan) { + return []; + } + var eventRange = fabricateEventRange(dateSpan, eventUiBases, component.calendar); + var segs = this.sliceRange.apply(this, [dateSpan.range].concat(extraArgs)); + for (var _a = 0, segs_1 = segs; _a < segs_1.length; _a++) { + var seg = segs_1[_a]; + seg.component = component; + seg.eventRange = eventRange; + } + return segs; + }; + /* + "complete" seg means it has component and eventRange + */ + Slicer.prototype.sliceEventRanges = function (eventRanges, component, // TODO: kill + extraArgs) { + var segs = []; + for (var _i = 0, eventRanges_1 = eventRanges; _i < eventRanges_1.length; _i++) { + var eventRange = eventRanges_1[_i]; + segs.push.apply(segs, this.sliceEventRange(eventRange, component, extraArgs)); + } + return segs; + }; + /* + "complete" seg means it has component and eventRange + */ + Slicer.prototype.sliceEventRange = function (eventRange, component, // TODO: kill + extraArgs) { + var segs = this.sliceRange.apply(this, [eventRange.range].concat(extraArgs)); + for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { + var seg = segs_2[_i]; + seg.component = component; + seg.eventRange = eventRange; + seg.isStart = eventRange.isStart && seg.isStart; + seg.isEnd = eventRange.isEnd && seg.isEnd; + } + return segs; + }; + return Slicer; +}()); +/* +for incorporating minTime/maxTime if appropriate +TODO: should be part of DateProfile! +TimelineDateProfile already does this btw +*/ +function computeActiveRange(dateProfile, isComponentAllDay) { + var range = dateProfile.activeRange; + if (isComponentAllDay) { + return range; + } + return { + start: addMs(range.start, dateProfile.minTime.milliseconds), + end: addMs(range.end, dateProfile.maxTime.milliseconds - 864e5) // 864e5 = ms in a day + }; +} + +// exports +// -------------------------------------------------------------------------------------------------- +var version = '4.3.1'; + +export { Calendar, Component, DateComponent, DateEnv, DateProfileGenerator, DayHeader, DaySeries, DayTable, ElementDragging, ElementScrollController, EmitterMixin, EventApi, FgEventRenderer, FillRenderer, Interaction, Mixin, NamedTimeZoneImpl, PositionCache, ScrollComponent, ScrollController, Slicer, Splitter, Theme, View, WindowScrollController, addDays, addDurations, addMs, addWeeks, allowContextMenu, allowSelection, appendToElement, applyAll, applyMutationToEventStore, applyStyle, applyStyleProp, asRoughMinutes, asRoughMs, asRoughSeconds, buildGotoAnchorHtml, buildSegCompareObj, capitaliseFirstLetter, combineEventUis, compareByFieldSpec, compareByFieldSpecs, compareNumbers, compensateScroll, computeClippingRect, computeEdges, computeFallbackHeaderFormat, computeHeightAndMargins, computeInnerRect, computeRect, computeVisibleDayRange, config, constrainPoint, createDuration, createElement, createEmptyEventStore, createEventInstance, createFormatter, createPlugin, cssToStr, debounce, diffDates, diffDayAndTime, diffDays, diffPoints, diffWeeks, diffWholeDays, diffWholeWeeks, disableCursor, distributeHeight, elementClosest, elementMatches, enableCursor, eventTupleToStore, filterEventStoreDefs, filterHash, findChildren, findElements, flexibleCompare, forceClassName, formatDate, formatIsoTimeString, formatRange, getAllDayHtml, getClippingParents, getDayClasses, getElSeg, getRectCenter, getRelevantEvents, globalDefaults, greatestDurationDenominator, hasBgRendering, htmlEscape, htmlToElement, insertAfterElement, interactionSettingsStore, interactionSettingsToStore, intersectRanges, intersectRects, isArraysEqual, isDateSpansEqual, isInt, isInteractionValid, isMultiDayRange, isPropsEqual, isPropsValid, isSingleDay, isValidDate, listenBySelector, mapHash, matchCellWidths, memoize, memoizeOutput, memoizeRendering, mergeEventStores, multiplyDuration, padStart, parseBusinessHours, parseDragMeta, parseEventDef, parseFieldSpecs, parse as parseMarker, pointInsideRect, prependToElement, preventContextMenu, preventDefault, preventSelection, processScopedUiProps, rangeContainsMarker, rangeContainsRange, rangesEqual, rangesIntersect, refineProps, removeElement, removeExact, renderDateCell, requestJson, sliceEventStore, startOfDay, subtractInnerElHeight, translateRect, uncompensateScroll, undistributeHeight, unpromisify, version, whenTransitionDone, wholeDivideDurations }; diff --git a/AKPlan/static/AKPlan/fullcalendar/core/main.js b/AKPlan/static/AKPlan/fullcalendar/core/main.js new file mode 100644 index 00000000..ec0808d0 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/main.js @@ -0,0 +1,8717 @@ +/*! +FullCalendar Core Package v4.3.1 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (global = global || self, factory(global.FullCalendar = {})); +}(this, function (exports) { 'use strict'; + + // Creating + // ---------------------------------------------------------------------------------------------------------------- + var elementPropHash = { + className: true, + colSpan: true, + rowSpan: true + }; + var containerTagHash = { + '<tr': 'tbody', + '<td': 'tr' + }; + function createElement(tagName, attrs, content) { + var el = document.createElement(tagName); + if (attrs) { + for (var attrName in attrs) { + if (attrName === 'style') { + applyStyle(el, attrs[attrName]); + } + else if (elementPropHash[attrName]) { + el[attrName] = attrs[attrName]; + } + else { + el.setAttribute(attrName, attrs[attrName]); + } + } + } + if (typeof content === 'string') { + el.innerHTML = content; // shortcut. no need to process HTML in any way + } + else if (content != null) { + appendToElement(el, content); + } + return el; + } + function htmlToElement(html) { + html = html.trim(); + var container = document.createElement(computeContainerTag(html)); + container.innerHTML = html; + return container.firstChild; + } + function htmlToElements(html) { + return Array.prototype.slice.call(htmlToNodeList(html)); + } + function htmlToNodeList(html) { + html = html.trim(); + var container = document.createElement(computeContainerTag(html)); + container.innerHTML = html; + return container.childNodes; + } + // assumes html already trimmed and tag names are lowercase + function computeContainerTag(html) { + return containerTagHash[html.substr(0, 3) // faster than using regex + ] || 'div'; + } + function appendToElement(el, content) { + var childNodes = normalizeContent(content); + for (var i = 0; i < childNodes.length; i++) { + el.appendChild(childNodes[i]); + } + } + function prependToElement(parent, content) { + var newEls = normalizeContent(content); + var afterEl = parent.firstChild || null; // if no firstChild, will append to end, but that's okay, b/c there were no children + for (var i = 0; i < newEls.length; i++) { + parent.insertBefore(newEls[i], afterEl); + } + } + function insertAfterElement(refEl, content) { + var newEls = normalizeContent(content); + var afterEl = refEl.nextSibling || null; + for (var i = 0; i < newEls.length; i++) { + refEl.parentNode.insertBefore(newEls[i], afterEl); + } + } + function normalizeContent(content) { + var els; + if (typeof content === 'string') { + els = htmlToElements(content); + } + else if (content instanceof Node) { + els = [content]; + } + else { // Node[] or NodeList + els = Array.prototype.slice.call(content); + } + return els; + } + function removeElement(el) { + if (el.parentNode) { + el.parentNode.removeChild(el); + } + } + // Querying + // ---------------------------------------------------------------------------------------------------------------- + // from https://developer.mozilla.org/en-US/docs/Web/API/Element/closest + var matchesMethod = Element.prototype.matches || + Element.prototype.matchesSelector || + Element.prototype.msMatchesSelector; + var closestMethod = Element.prototype.closest || function (selector) { + // polyfill + var el = this; + if (!document.documentElement.contains(el)) { + return null; + } + do { + if (elementMatches(el, selector)) { + return el; + } + el = el.parentElement || el.parentNode; + } while (el !== null && el.nodeType === 1); + return null; + }; + function elementClosest(el, selector) { + return closestMethod.call(el, selector); + } + function elementMatches(el, selector) { + return matchesMethod.call(el, selector); + } + // accepts multiple subject els + // returns a real array. good for methods like forEach + function findElements(container, selector) { + var containers = container instanceof HTMLElement ? [container] : container; + var allMatches = []; + for (var i = 0; i < containers.length; i++) { + var matches = containers[i].querySelectorAll(selector); + for (var j = 0; j < matches.length; j++) { + allMatches.push(matches[j]); + } + } + return allMatches; + } + // accepts multiple subject els + // only queries direct child elements + function findChildren(parent, selector) { + var parents = parent instanceof HTMLElement ? [parent] : parent; + var allMatches = []; + for (var i = 0; i < parents.length; i++) { + var childNodes = parents[i].children; // only ever elements + for (var j = 0; j < childNodes.length; j++) { + var childNode = childNodes[j]; + if (!selector || elementMatches(childNode, selector)) { + allMatches.push(childNode); + } + } + } + return allMatches; + } + // Attributes + // ---------------------------------------------------------------------------------------------------------------- + function forceClassName(el, className, bool) { + if (bool) { + el.classList.add(className); + } + else { + el.classList.remove(className); + } + } + // Style + // ---------------------------------------------------------------------------------------------------------------- + var PIXEL_PROP_RE = /(top|left|right|bottom|width|height)$/i; + function applyStyle(el, props) { + for (var propName in props) { + applyStyleProp(el, propName, props[propName]); + } + } + function applyStyleProp(el, name, val) { + if (val == null) { + el.style[name] = ''; + } + else if (typeof val === 'number' && PIXEL_PROP_RE.test(name)) { + el.style[name] = val + 'px'; + } + else { + el.style[name] = val; + } + } + + function pointInsideRect(point, rect) { + return point.left >= rect.left && + point.left < rect.right && + point.top >= rect.top && + point.top < rect.bottom; + } + // Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false + function intersectRects(rect1, rect2) { + var res = { + left: Math.max(rect1.left, rect2.left), + right: Math.min(rect1.right, rect2.right), + top: Math.max(rect1.top, rect2.top), + bottom: Math.min(rect1.bottom, rect2.bottom) + }; + if (res.left < res.right && res.top < res.bottom) { + return res; + } + return false; + } + function translateRect(rect, deltaX, deltaY) { + return { + left: rect.left + deltaX, + right: rect.right + deltaX, + top: rect.top + deltaY, + bottom: rect.bottom + deltaY + }; + } + // Returns a new point that will have been moved to reside within the given rectangle + function constrainPoint(point, rect) { + return { + left: Math.min(Math.max(point.left, rect.left), rect.right), + top: Math.min(Math.max(point.top, rect.top), rect.bottom) + }; + } + // Returns a point that is the center of the given rectangle + function getRectCenter(rect) { + return { + left: (rect.left + rect.right) / 2, + top: (rect.top + rect.bottom) / 2 + }; + } + // Subtracts point2's coordinates from point1's coordinates, returning a delta + function diffPoints(point1, point2) { + return { + left: point1.left - point2.left, + top: point1.top - point2.top + }; + } + + // Logic for determining if, when the element is right-to-left, the scrollbar appears on the left side + var isRtlScrollbarOnLeft = null; + function getIsRtlScrollbarOnLeft() { + if (isRtlScrollbarOnLeft === null) { + isRtlScrollbarOnLeft = computeIsRtlScrollbarOnLeft(); + } + return isRtlScrollbarOnLeft; + } + function computeIsRtlScrollbarOnLeft() { + var outerEl = createElement('div', { + style: { + position: 'absolute', + top: -1000, + left: 0, + border: 0, + padding: 0, + overflow: 'scroll', + direction: 'rtl' + } + }, '<div></div>'); + document.body.appendChild(outerEl); + var innerEl = outerEl.firstChild; + var res = innerEl.getBoundingClientRect().left > outerEl.getBoundingClientRect().left; + removeElement(outerEl); + return res; + } + // The scrollbar width computations in computeEdges are sometimes flawed when it comes to + // retina displays, rounding, and IE11. Massage them into a usable value. + function sanitizeScrollbarWidth(width) { + width = Math.max(0, width); // no negatives + width = Math.round(width); + return width; + } + + function computeEdges(el, getPadding) { + if (getPadding === void 0) { getPadding = false; } + var computedStyle = window.getComputedStyle(el); + var borderLeft = parseInt(computedStyle.borderLeftWidth, 10) || 0; + var borderRight = parseInt(computedStyle.borderRightWidth, 10) || 0; + var borderTop = parseInt(computedStyle.borderTopWidth, 10) || 0; + var borderBottom = parseInt(computedStyle.borderBottomWidth, 10) || 0; + // must use offset(Width|Height) because compatible with client(Width|Height) + var scrollbarLeftRight = sanitizeScrollbarWidth(el.offsetWidth - el.clientWidth - borderLeft - borderRight); + var scrollbarBottom = sanitizeScrollbarWidth(el.offsetHeight - el.clientHeight - borderTop - borderBottom); + var res = { + borderLeft: borderLeft, + borderRight: borderRight, + borderTop: borderTop, + borderBottom: borderBottom, + scrollbarBottom: scrollbarBottom, + scrollbarLeft: 0, + scrollbarRight: 0 + }; + if (getIsRtlScrollbarOnLeft() && computedStyle.direction === 'rtl') { // is the scrollbar on the left side? + res.scrollbarLeft = scrollbarLeftRight; + } + else { + res.scrollbarRight = scrollbarLeftRight; + } + if (getPadding) { + res.paddingLeft = parseInt(computedStyle.paddingLeft, 10) || 0; + res.paddingRight = parseInt(computedStyle.paddingRight, 10) || 0; + res.paddingTop = parseInt(computedStyle.paddingTop, 10) || 0; + res.paddingBottom = parseInt(computedStyle.paddingBottom, 10) || 0; + } + return res; + } + function computeInnerRect(el, goWithinPadding) { + if (goWithinPadding === void 0) { goWithinPadding = false; } + var outerRect = computeRect(el); + var edges = computeEdges(el, goWithinPadding); + var res = { + left: outerRect.left + edges.borderLeft + edges.scrollbarLeft, + right: outerRect.right - edges.borderRight - edges.scrollbarRight, + top: outerRect.top + edges.borderTop, + bottom: outerRect.bottom - edges.borderBottom - edges.scrollbarBottom + }; + if (goWithinPadding) { + res.left += edges.paddingLeft; + res.right -= edges.paddingRight; + res.top += edges.paddingTop; + res.bottom -= edges.paddingBottom; + } + return res; + } + function computeRect(el) { + var rect = el.getBoundingClientRect(); + return { + left: rect.left + window.pageXOffset, + top: rect.top + window.pageYOffset, + right: rect.right + window.pageXOffset, + bottom: rect.bottom + window.pageYOffset + }; + } + function computeViewportRect() { + return { + left: window.pageXOffset, + right: window.pageXOffset + document.documentElement.clientWidth, + top: window.pageYOffset, + bottom: window.pageYOffset + document.documentElement.clientHeight + }; + } + function computeHeightAndMargins(el) { + return el.getBoundingClientRect().height + computeVMargins(el); + } + function computeVMargins(el) { + var computed = window.getComputedStyle(el); + return parseInt(computed.marginTop, 10) + + parseInt(computed.marginBottom, 10); + } + // does not return window + function getClippingParents(el) { + var parents = []; + while (el instanceof HTMLElement) { // will stop when gets to document or null + var computedStyle = window.getComputedStyle(el); + if (computedStyle.position === 'fixed') { + break; + } + if ((/(auto|scroll)/).test(computedStyle.overflow + computedStyle.overflowY + computedStyle.overflowX)) { + parents.push(el); + } + el = el.parentNode; + } + return parents; + } + function computeClippingRect(el) { + return getClippingParents(el) + .map(function (el) { + return computeInnerRect(el); + }) + .concat(computeViewportRect()) + .reduce(function (rect0, rect1) { + return intersectRects(rect0, rect1) || rect1; // should always intersect + }); + } + + // Stops a mouse/touch event from doing it's native browser action + function preventDefault(ev) { + ev.preventDefault(); + } + // Event Delegation + // ---------------------------------------------------------------------------------------------------------------- + function listenBySelector(container, eventType, selector, handler) { + function realHandler(ev) { + var matchedChild = elementClosest(ev.target, selector); + if (matchedChild) { + handler.call(matchedChild, ev, matchedChild); + } + } + container.addEventListener(eventType, realHandler); + return function () { + container.removeEventListener(eventType, realHandler); + }; + } + function listenToHoverBySelector(container, selector, onMouseEnter, onMouseLeave) { + var currentMatchedChild; + return listenBySelector(container, 'mouseover', selector, function (ev, matchedChild) { + if (matchedChild !== currentMatchedChild) { + currentMatchedChild = matchedChild; + onMouseEnter(ev, matchedChild); + var realOnMouseLeave_1 = function (ev) { + currentMatchedChild = null; + onMouseLeave(ev, matchedChild); + matchedChild.removeEventListener('mouseleave', realOnMouseLeave_1); + }; + // listen to the next mouseleave, and then unattach + matchedChild.addEventListener('mouseleave', realOnMouseLeave_1); + } + }); + } + // Animation + // ---------------------------------------------------------------------------------------------------------------- + var transitionEventNames = [ + 'webkitTransitionEnd', + 'otransitionend', + 'oTransitionEnd', + 'msTransitionEnd', + 'transitionend' + ]; + // triggered only when the next single subsequent transition finishes + function whenTransitionDone(el, callback) { + var realCallback = function (ev) { + callback(ev); + transitionEventNames.forEach(function (eventName) { + el.removeEventListener(eventName, realCallback); + }); + }; + transitionEventNames.forEach(function (eventName) { + el.addEventListener(eventName, realCallback); // cross-browser way to determine when the transition finishes + }); + } + + var DAY_IDS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']; + // Adding + function addWeeks(m, n) { + var a = dateToUtcArray(m); + a[2] += n * 7; + return arrayToUtcDate(a); + } + function addDays(m, n) { + var a = dateToUtcArray(m); + a[2] += n; + return arrayToUtcDate(a); + } + function addMs(m, n) { + var a = dateToUtcArray(m); + a[6] += n; + return arrayToUtcDate(a); + } + // Diffing (all return floats) + function diffWeeks(m0, m1) { + return diffDays(m0, m1) / 7; + } + function diffDays(m0, m1) { + return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60 * 24); + } + function diffHours(m0, m1) { + return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60); + } + function diffMinutes(m0, m1) { + return (m1.valueOf() - m0.valueOf()) / (1000 * 60); + } + function diffSeconds(m0, m1) { + return (m1.valueOf() - m0.valueOf()) / 1000; + } + function diffDayAndTime(m0, m1) { + var m0day = startOfDay(m0); + var m1day = startOfDay(m1); + return { + years: 0, + months: 0, + days: Math.round(diffDays(m0day, m1day)), + milliseconds: (m1.valueOf() - m1day.valueOf()) - (m0.valueOf() - m0day.valueOf()) + }; + } + // Diffing Whole Units + function diffWholeWeeks(m0, m1) { + var d = diffWholeDays(m0, m1); + if (d !== null && d % 7 === 0) { + return d / 7; + } + return null; + } + function diffWholeDays(m0, m1) { + if (timeAsMs(m0) === timeAsMs(m1)) { + return Math.round(diffDays(m0, m1)); + } + return null; + } + // Start-Of + function startOfDay(m) { + return arrayToUtcDate([ + m.getUTCFullYear(), + m.getUTCMonth(), + m.getUTCDate() + ]); + } + function startOfHour(m) { + return arrayToUtcDate([ + m.getUTCFullYear(), + m.getUTCMonth(), + m.getUTCDate(), + m.getUTCHours() + ]); + } + function startOfMinute(m) { + return arrayToUtcDate([ + m.getUTCFullYear(), + m.getUTCMonth(), + m.getUTCDate(), + m.getUTCHours(), + m.getUTCMinutes() + ]); + } + function startOfSecond(m) { + return arrayToUtcDate([ + m.getUTCFullYear(), + m.getUTCMonth(), + m.getUTCDate(), + m.getUTCHours(), + m.getUTCMinutes(), + m.getUTCSeconds() + ]); + } + // Week Computation + function weekOfYear(marker, dow, doy) { + var y = marker.getUTCFullYear(); + var w = weekOfGivenYear(marker, y, dow, doy); + if (w < 1) { + return weekOfGivenYear(marker, y - 1, dow, doy); + } + var nextW = weekOfGivenYear(marker, y + 1, dow, doy); + if (nextW >= 1) { + return Math.min(w, nextW); + } + return w; + } + function weekOfGivenYear(marker, year, dow, doy) { + var firstWeekStart = arrayToUtcDate([year, 0, 1 + firstWeekOffset(year, dow, doy)]); + var dayStart = startOfDay(marker); + var days = Math.round(diffDays(firstWeekStart, dayStart)); + return Math.floor(days / 7) + 1; // zero-indexed + } + // start-of-first-week - start-of-year + function firstWeekOffset(year, dow, doy) { + // first-week day -- which january is always in the first week (4 for iso, 1 for other) + var fwd = 7 + dow - doy; + // first-week day local weekday -- which local weekday is fwd + var fwdlw = (7 + arrayToUtcDate([year, 0, fwd]).getUTCDay() - dow) % 7; + return -fwdlw + fwd - 1; + } + // Array Conversion + function dateToLocalArray(date) { + return [ + date.getFullYear(), + date.getMonth(), + date.getDate(), + date.getHours(), + date.getMinutes(), + date.getSeconds(), + date.getMilliseconds() + ]; + } + function arrayToLocalDate(a) { + return new Date(a[0], a[1] || 0, a[2] == null ? 1 : a[2], // day of month + a[3] || 0, a[4] || 0, a[5] || 0); + } + function dateToUtcArray(date) { + return [ + date.getUTCFullYear(), + date.getUTCMonth(), + date.getUTCDate(), + date.getUTCHours(), + date.getUTCMinutes(), + date.getUTCSeconds(), + date.getUTCMilliseconds() + ]; + } + function arrayToUtcDate(a) { + // according to web standards (and Safari), a month index is required. + // massage if only given a year. + if (a.length === 1) { + a = a.concat([0]); + } + return new Date(Date.UTC.apply(Date, a)); + } + // Other Utils + function isValidDate(m) { + return !isNaN(m.valueOf()); + } + function timeAsMs(m) { + return m.getUTCHours() * 1000 * 60 * 60 + + m.getUTCMinutes() * 1000 * 60 + + m.getUTCSeconds() * 1000 + + m.getUTCMilliseconds(); + } + + var INTERNAL_UNITS = ['years', 'months', 'days', 'milliseconds']; + var PARSE_RE = /^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/; + // Parsing and Creation + function createDuration(input, unit) { + var _a; + if (typeof input === 'string') { + return parseString(input); + } + else if (typeof input === 'object' && input) { // non-null object + return normalizeObject(input); + } + else if (typeof input === 'number') { + return normalizeObject((_a = {}, _a[unit || 'milliseconds'] = input, _a)); + } + else { + return null; + } + } + function parseString(s) { + var m = PARSE_RE.exec(s); + if (m) { + var sign = m[1] ? -1 : 1; + return { + years: 0, + months: 0, + days: sign * (m[2] ? parseInt(m[2], 10) : 0), + milliseconds: sign * ((m[3] ? parseInt(m[3], 10) : 0) * 60 * 60 * 1000 + // hours + (m[4] ? parseInt(m[4], 10) : 0) * 60 * 1000 + // minutes + (m[5] ? parseInt(m[5], 10) : 0) * 1000 + // seconds + (m[6] ? parseInt(m[6], 10) : 0) // ms + ) + }; + } + return null; + } + function normalizeObject(obj) { + return { + years: obj.years || obj.year || 0, + months: obj.months || obj.month || 0, + days: (obj.days || obj.day || 0) + + getWeeksFromInput(obj) * 7, + milliseconds: (obj.hours || obj.hour || 0) * 60 * 60 * 1000 + // hours + (obj.minutes || obj.minute || 0) * 60 * 1000 + // minutes + (obj.seconds || obj.second || 0) * 1000 + // seconds + (obj.milliseconds || obj.millisecond || obj.ms || 0) // ms + }; + } + function getWeeksFromInput(obj) { + return obj.weeks || obj.week || 0; + } + // Equality + function durationsEqual(d0, d1) { + return d0.years === d1.years && + d0.months === d1.months && + d0.days === d1.days && + d0.milliseconds === d1.milliseconds; + } + function isSingleDay(dur) { + return dur.years === 0 && dur.months === 0 && dur.days === 1 && dur.milliseconds === 0; + } + // Simple Math + function addDurations(d0, d1) { + return { + years: d0.years + d1.years, + months: d0.months + d1.months, + days: d0.days + d1.days, + milliseconds: d0.milliseconds + d1.milliseconds + }; + } + function subtractDurations(d1, d0) { + return { + years: d1.years - d0.years, + months: d1.months - d0.months, + days: d1.days - d0.days, + milliseconds: d1.milliseconds - d0.milliseconds + }; + } + function multiplyDuration(d, n) { + return { + years: d.years * n, + months: d.months * n, + days: d.days * n, + milliseconds: d.milliseconds * n + }; + } + // Conversions + // "Rough" because they are based on average-case Gregorian months/years + function asRoughYears(dur) { + return asRoughDays(dur) / 365; + } + function asRoughMonths(dur) { + return asRoughDays(dur) / 30; + } + function asRoughDays(dur) { + return asRoughMs(dur) / 864e5; + } + function asRoughMinutes(dur) { + return asRoughMs(dur) / (1000 * 60); + } + function asRoughSeconds(dur) { + return asRoughMs(dur) / 1000; + } + function asRoughMs(dur) { + return dur.years * (365 * 864e5) + + dur.months * (30 * 864e5) + + dur.days * 864e5 + + dur.milliseconds; + } + // Advanced Math + function wholeDivideDurations(numerator, denominator) { + var res = null; + for (var i = 0; i < INTERNAL_UNITS.length; i++) { + var unit = INTERNAL_UNITS[i]; + if (denominator[unit]) { + var localRes = numerator[unit] / denominator[unit]; + if (!isInt(localRes) || (res !== null && res !== localRes)) { + return null; + } + res = localRes; + } + else if (numerator[unit]) { + // needs to divide by something but can't! + return null; + } + } + return res; + } + function greatestDurationDenominator(dur, dontReturnWeeks) { + var ms = dur.milliseconds; + if (ms) { + if (ms % 1000 !== 0) { + return { unit: 'millisecond', value: ms }; + } + if (ms % (1000 * 60) !== 0) { + return { unit: 'second', value: ms / 1000 }; + } + if (ms % (1000 * 60 * 60) !== 0) { + return { unit: 'minute', value: ms / (1000 * 60) }; + } + if (ms) { + return { unit: 'hour', value: ms / (1000 * 60 * 60) }; + } + } + if (dur.days) { + if (!dontReturnWeeks && dur.days % 7 === 0) { + return { unit: 'week', value: dur.days / 7 }; + } + return { unit: 'day', value: dur.days }; + } + if (dur.months) { + return { unit: 'month', value: dur.months }; + } + if (dur.years) { + return { unit: 'year', value: dur.years }; + } + return { unit: 'millisecond', value: 0 }; + } + + /* FullCalendar-specific DOM Utilities + ----------------------------------------------------------------------------------------------------------------------*/ + // Given the scrollbar widths of some other container, create borders/margins on rowEls in order to match the left + // and right space that was offset by the scrollbars. A 1-pixel border first, then margin beyond that. + function compensateScroll(rowEl, scrollbarWidths) { + if (scrollbarWidths.left) { + applyStyle(rowEl, { + borderLeftWidth: 1, + marginLeft: scrollbarWidths.left - 1 + }); + } + if (scrollbarWidths.right) { + applyStyle(rowEl, { + borderRightWidth: 1, + marginRight: scrollbarWidths.right - 1 + }); + } + } + // Undoes compensateScroll and restores all borders/margins + function uncompensateScroll(rowEl) { + applyStyle(rowEl, { + marginLeft: '', + marginRight: '', + borderLeftWidth: '', + borderRightWidth: '' + }); + } + // Make the mouse cursor express that an event is not allowed in the current area + function disableCursor() { + document.body.classList.add('fc-not-allowed'); + } + // Returns the mouse cursor to its original look + function enableCursor() { + document.body.classList.remove('fc-not-allowed'); + } + // Given a total available height to fill, have `els` (essentially child rows) expand to accomodate. + // By default, all elements that are shorter than the recommended height are expanded uniformly, not considering + // any other els that are already too tall. if `shouldRedistribute` is on, it considers these tall rows and + // reduces the available height. + function distributeHeight(els, availableHeight, shouldRedistribute) { + // *FLOORING NOTE*: we floor in certain places because zoom can give inaccurate floating-point dimensions, + // and it is better to be shorter than taller, to avoid creating unnecessary scrollbars. + var minOffset1 = Math.floor(availableHeight / els.length); // for non-last element + var minOffset2 = Math.floor(availableHeight - minOffset1 * (els.length - 1)); // for last element *FLOORING NOTE* + var flexEls = []; // elements that are allowed to expand. array of DOM nodes + var flexOffsets = []; // amount of vertical space it takes up + var flexHeights = []; // actual css height + var usedHeight = 0; + undistributeHeight(els); // give all elements their natural height + // find elements that are below the recommended height (expandable). + // important to query for heights in a single first pass (to avoid reflow oscillation). + els.forEach(function (el, i) { + var minOffset = i === els.length - 1 ? minOffset2 : minOffset1; + var naturalHeight = el.getBoundingClientRect().height; + var naturalOffset = naturalHeight + computeVMargins(el); + if (naturalOffset < minOffset) { + flexEls.push(el); + flexOffsets.push(naturalOffset); + flexHeights.push(naturalHeight); + } + else { + // this element stretches past recommended height (non-expandable). mark the space as occupied. + usedHeight += naturalOffset; + } + }); + // readjust the recommended height to only consider the height available to non-maxed-out rows. + if (shouldRedistribute) { + availableHeight -= usedHeight; + minOffset1 = Math.floor(availableHeight / flexEls.length); + minOffset2 = Math.floor(availableHeight - minOffset1 * (flexEls.length - 1)); // *FLOORING NOTE* + } + // assign heights to all expandable elements + flexEls.forEach(function (el, i) { + var minOffset = i === flexEls.length - 1 ? minOffset2 : minOffset1; + var naturalOffset = flexOffsets[i]; + var naturalHeight = flexHeights[i]; + var newHeight = minOffset - (naturalOffset - naturalHeight); // subtract the margin/padding + if (naturalOffset < minOffset) { // we check this again because redistribution might have changed things + el.style.height = newHeight + 'px'; + } + }); + } + // Undoes distrubuteHeight, restoring all els to their natural height + function undistributeHeight(els) { + els.forEach(function (el) { + el.style.height = ''; + }); + } + // Given `els`, a set of <td> cells, find the cell with the largest natural width and set the widths of all the + // cells to be that width. + // PREREQUISITE: if you want a cell to take up width, it needs to have a single inner element w/ display:inline + function matchCellWidths(els) { + var maxInnerWidth = 0; + els.forEach(function (el) { + var innerEl = el.firstChild; // hopefully an element + if (innerEl instanceof HTMLElement) { + var innerWidth_1 = innerEl.getBoundingClientRect().width; + if (innerWidth_1 > maxInnerWidth) { + maxInnerWidth = innerWidth_1; + } + } + }); + maxInnerWidth++; // sometimes not accurate of width the text needs to stay on one line. insurance + els.forEach(function (el) { + el.style.width = maxInnerWidth + 'px'; + }); + return maxInnerWidth; + } + // Given one element that resides inside another, + // Subtracts the height of the inner element from the outer element. + function subtractInnerElHeight(outerEl, innerEl) { + // effin' IE8/9/10/11 sometimes returns 0 for dimensions. this weird hack was the only thing that worked + var reflowStyleProps = { + position: 'relative', + left: -1 // ensure reflow in case the el was already relative. negative is less likely to cause new scroll + }; + applyStyle(outerEl, reflowStyleProps); + applyStyle(innerEl, reflowStyleProps); + var diff = // grab the dimensions + outerEl.getBoundingClientRect().height - + innerEl.getBoundingClientRect().height; + // undo hack + var resetStyleProps = { position: '', left: '' }; + applyStyle(outerEl, resetStyleProps); + applyStyle(innerEl, resetStyleProps); + return diff; + } + /* Selection + ----------------------------------------------------------------------------------------------------------------------*/ + function preventSelection(el) { + el.classList.add('fc-unselectable'); + el.addEventListener('selectstart', preventDefault); + } + function allowSelection(el) { + el.classList.remove('fc-unselectable'); + el.removeEventListener('selectstart', preventDefault); + } + /* Context Menu + ----------------------------------------------------------------------------------------------------------------------*/ + function preventContextMenu(el) { + el.addEventListener('contextmenu', preventDefault); + } + function allowContextMenu(el) { + el.removeEventListener('contextmenu', preventDefault); + } + /* Object Ordering by Field + ----------------------------------------------------------------------------------------------------------------------*/ + function parseFieldSpecs(input) { + var specs = []; + var tokens = []; + var i; + var token; + if (typeof input === 'string') { + tokens = input.split(/\s*,\s*/); + } + else if (typeof input === 'function') { + tokens = [input]; + } + else if (Array.isArray(input)) { + tokens = input; + } + for (i = 0; i < tokens.length; i++) { + token = tokens[i]; + if (typeof token === 'string') { + specs.push(token.charAt(0) === '-' ? + { field: token.substring(1), order: -1 } : + { field: token, order: 1 }); + } + else if (typeof token === 'function') { + specs.push({ func: token }); + } + } + return specs; + } + function compareByFieldSpecs(obj0, obj1, fieldSpecs) { + var i; + var cmp; + for (i = 0; i < fieldSpecs.length; i++) { + cmp = compareByFieldSpec(obj0, obj1, fieldSpecs[i]); + if (cmp) { + return cmp; + } + } + return 0; + } + function compareByFieldSpec(obj0, obj1, fieldSpec) { + if (fieldSpec.func) { + return fieldSpec.func(obj0, obj1); + } + return flexibleCompare(obj0[fieldSpec.field], obj1[fieldSpec.field]) + * (fieldSpec.order || 1); + } + function flexibleCompare(a, b) { + if (!a && !b) { + return 0; + } + if (b == null) { + return -1; + } + if (a == null) { + return 1; + } + if (typeof a === 'string' || typeof b === 'string') { + return String(a).localeCompare(String(b)); + } + return a - b; + } + /* String Utilities + ----------------------------------------------------------------------------------------------------------------------*/ + function capitaliseFirstLetter(str) { + return str.charAt(0).toUpperCase() + str.slice(1); + } + function padStart(val, len) { + var s = String(val); + return '000'.substr(0, len - s.length) + s; + } + /* Number Utilities + ----------------------------------------------------------------------------------------------------------------------*/ + function compareNumbers(a, b) { + return a - b; + } + function isInt(n) { + return n % 1 === 0; + } + /* Weird Utilities + ----------------------------------------------------------------------------------------------------------------------*/ + function applyAll(functions, thisObj, args) { + if (typeof functions === 'function') { // supplied a single function + functions = [functions]; + } + if (functions) { + var i = void 0; + var ret = void 0; + for (i = 0; i < functions.length; i++) { + ret = functions[i].apply(thisObj, args) || ret; + } + return ret; + } + } + function firstDefined() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + for (var i = 0; i < args.length; i++) { + if (args[i] !== undefined) { + return args[i]; + } + } + } + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + // https://github.com/jashkenas/underscore/blob/1.6.0/underscore.js#L714 + function debounce(func, wait) { + var timeout; + var args; + var context; + var timestamp; + var result; + var later = function () { + var last = new Date().valueOf() - timestamp; + if (last < wait) { + timeout = setTimeout(later, wait - last); + } + else { + timeout = null; + result = func.apply(context, args); + context = args = null; + } + }; + return function () { + context = this; + args = arguments; + timestamp = new Date().valueOf(); + if (!timeout) { + timeout = setTimeout(later, wait); + } + return result; + }; + } + // Number and Boolean are only types that defaults or not computed for + // TODO: write more comments + function refineProps(rawProps, processors, defaults, leftoverProps) { + if (defaults === void 0) { defaults = {}; } + var refined = {}; + for (var key in processors) { + var processor = processors[key]; + if (rawProps[key] !== undefined) { + // found + if (processor === Function) { + refined[key] = typeof rawProps[key] === 'function' ? rawProps[key] : null; + } + else if (processor) { // a refining function? + refined[key] = processor(rawProps[key]); + } + else { + refined[key] = rawProps[key]; + } + } + else if (defaults[key] !== undefined) { + // there's an explicit default + refined[key] = defaults[key]; + } + else { + // must compute a default + if (processor === String) { + refined[key] = ''; // empty string is default for String + } + else if (!processor || processor === Number || processor === Boolean || processor === Function) { + refined[key] = null; // assign null for other non-custom processor funcs + } + else { + refined[key] = processor(null); // run the custom processor func + } + } + } + if (leftoverProps) { + for (var key in rawProps) { + if (processors[key] === undefined) { + leftoverProps[key] = rawProps[key]; + } + } + } + return refined; + } + /* Date stuff that doesn't belong in datelib core + ----------------------------------------------------------------------------------------------------------------------*/ + // given a timed range, computes an all-day range that has the same exact duration, + // but whose start time is aligned with the start of the day. + function computeAlignedDayRange(timedRange) { + var dayCnt = Math.floor(diffDays(timedRange.start, timedRange.end)) || 1; + var start = startOfDay(timedRange.start); + var end = addDays(start, dayCnt); + return { start: start, end: end }; + } + // given a timed range, computes an all-day range based on how for the end date bleeds into the next day + // TODO: give nextDayThreshold a default arg + function computeVisibleDayRange(timedRange, nextDayThreshold) { + if (nextDayThreshold === void 0) { nextDayThreshold = createDuration(0); } + var startDay = null; + var endDay = null; + if (timedRange.end) { + endDay = startOfDay(timedRange.end); + var endTimeMS = timedRange.end.valueOf() - endDay.valueOf(); // # of milliseconds into `endDay` + // If the end time is actually inclusively part of the next day and is equal to or + // beyond the next day threshold, adjust the end to be the exclusive end of `endDay`. + // Otherwise, leaving it as inclusive will cause it to exclude `endDay`. + if (endTimeMS && endTimeMS >= asRoughMs(nextDayThreshold)) { + endDay = addDays(endDay, 1); + } + } + if (timedRange.start) { + startDay = startOfDay(timedRange.start); // the beginning of the day the range starts + // If end is within `startDay` but not past nextDayThreshold, assign the default duration of one day. + if (endDay && endDay <= startDay) { + endDay = addDays(startDay, 1); + } + } + return { start: startDay, end: endDay }; + } + // spans from one day into another? + function isMultiDayRange(range) { + var visibleRange = computeVisibleDayRange(range); + return diffDays(visibleRange.start, visibleRange.end) > 1; + } + function diffDates(date0, date1, dateEnv, largeUnit) { + if (largeUnit === 'year') { + return createDuration(dateEnv.diffWholeYears(date0, date1), 'year'); + } + else if (largeUnit === 'month') { + return createDuration(dateEnv.diffWholeMonths(date0, date1), 'month'); + } + else { + return diffDayAndTime(date0, date1); // returns a duration + } + } + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + function parseRecurring(eventInput, allDayDefault, dateEnv, recurringTypes, leftovers) { + for (var i = 0; i < recurringTypes.length; i++) { + var localLeftovers = {}; + var parsed = recurringTypes[i].parse(eventInput, localLeftovers, dateEnv); + if (parsed) { + var allDay = localLeftovers.allDay; + delete localLeftovers.allDay; // remove from leftovers + if (allDay == null) { + allDay = allDayDefault; + if (allDay == null) { + allDay = parsed.allDayGuess; + if (allDay == null) { + allDay = false; + } + } + } + __assign(leftovers, localLeftovers); + return { + allDay: allDay, + duration: parsed.duration, + typeData: parsed.typeData, + typeId: i + }; + } + } + return null; + } + /* + Event MUST have a recurringDef + */ + function expandRecurringRanges(eventDef, duration, framingRange, dateEnv, recurringTypes) { + var typeDef = recurringTypes[eventDef.recurringDef.typeId]; + var markers = typeDef.expand(eventDef.recurringDef.typeData, { + start: dateEnv.subtract(framingRange.start, duration), + end: framingRange.end + }, dateEnv); + // the recurrence plugins don't guarantee that all-day events are start-of-day, so we have to + if (eventDef.allDay) { + markers = markers.map(startOfDay); + } + return markers; + } + + var hasOwnProperty = Object.prototype.hasOwnProperty; + // Merges an array of objects into a single object. + // The second argument allows for an array of property names who's object values will be merged together. + function mergeProps(propObjs, complexProps) { + var dest = {}; + var i; + var name; + var complexObjs; + var j; + var val; + var props; + if (complexProps) { + for (i = 0; i < complexProps.length; i++) { + name = complexProps[i]; + complexObjs = []; + // collect the trailing object values, stopping when a non-object is discovered + for (j = propObjs.length - 1; j >= 0; j--) { + val = propObjs[j][name]; + if (typeof val === 'object' && val) { // non-null object + complexObjs.unshift(val); + } + else if (val !== undefined) { + dest[name] = val; // if there were no objects, this value will be used + break; + } + } + // if the trailing values were objects, use the merged value + if (complexObjs.length) { + dest[name] = mergeProps(complexObjs); + } + } + } + // copy values into the destination, going from last to first + for (i = propObjs.length - 1; i >= 0; i--) { + props = propObjs[i]; + for (name in props) { + if (!(name in dest)) { // if already assigned by previous props or complex props, don't reassign + dest[name] = props[name]; + } + } + } + return dest; + } + function filterHash(hash, func) { + var filtered = {}; + for (var key in hash) { + if (func(hash[key], key)) { + filtered[key] = hash[key]; + } + } + return filtered; + } + function mapHash(hash, func) { + var newHash = {}; + for (var key in hash) { + newHash[key] = func(hash[key], key); + } + return newHash; + } + function arrayToHash(a) { + var hash = {}; + for (var _i = 0, a_1 = a; _i < a_1.length; _i++) { + var item = a_1[_i]; + hash[item] = true; + } + return hash; + } + function hashValuesToArray(obj) { + var a = []; + for (var key in obj) { + a.push(obj[key]); + } + return a; + } + function isPropsEqual(obj0, obj1) { + for (var key in obj0) { + if (hasOwnProperty.call(obj0, key)) { + if (!(key in obj1)) { + return false; + } + } + } + for (var key in obj1) { + if (hasOwnProperty.call(obj1, key)) { + if (obj0[key] !== obj1[key]) { + return false; + } + } + } + return true; + } + + function parseEvents(rawEvents, sourceId, calendar, allowOpenRange) { + var eventStore = createEmptyEventStore(); + for (var _i = 0, rawEvents_1 = rawEvents; _i < rawEvents_1.length; _i++) { + var rawEvent = rawEvents_1[_i]; + var tuple = parseEvent(rawEvent, sourceId, calendar, allowOpenRange); + if (tuple) { + eventTupleToStore(tuple, eventStore); + } + } + return eventStore; + } + function eventTupleToStore(tuple, eventStore) { + if (eventStore === void 0) { eventStore = createEmptyEventStore(); } + eventStore.defs[tuple.def.defId] = tuple.def; + if (tuple.instance) { + eventStore.instances[tuple.instance.instanceId] = tuple.instance; + } + return eventStore; + } + function expandRecurring(eventStore, framingRange, calendar) { + var dateEnv = calendar.dateEnv; + var defs = eventStore.defs, instances = eventStore.instances; + // remove existing recurring instances + instances = filterHash(instances, function (instance) { + return !defs[instance.defId].recurringDef; + }); + for (var defId in defs) { + var def = defs[defId]; + if (def.recurringDef) { + var duration = def.recurringDef.duration; + if (!duration) { + duration = def.allDay ? + calendar.defaultAllDayEventDuration : + calendar.defaultTimedEventDuration; + } + var starts = expandRecurringRanges(def, duration, framingRange, calendar.dateEnv, calendar.pluginSystem.hooks.recurringTypes); + for (var _i = 0, starts_1 = starts; _i < starts_1.length; _i++) { + var start = starts_1[_i]; + var instance = createEventInstance(defId, { + start: start, + end: dateEnv.add(start, duration) + }); + instances[instance.instanceId] = instance; + } + } + } + return { defs: defs, instances: instances }; + } + // retrieves events that have the same groupId as the instance specified by `instanceId` + // or they are the same as the instance. + // why might instanceId not be in the store? an event from another calendar? + function getRelevantEvents(eventStore, instanceId) { + var instance = eventStore.instances[instanceId]; + if (instance) { + var def_1 = eventStore.defs[instance.defId]; + // get events/instances with same group + var newStore = filterEventStoreDefs(eventStore, function (lookDef) { + return isEventDefsGrouped(def_1, lookDef); + }); + // add the original + // TODO: wish we could use eventTupleToStore or something like it + newStore.defs[def_1.defId] = def_1; + newStore.instances[instance.instanceId] = instance; + return newStore; + } + return createEmptyEventStore(); + } + function isEventDefsGrouped(def0, def1) { + return Boolean(def0.groupId && def0.groupId === def1.groupId); + } + function transformRawEvents(rawEvents, eventSource, calendar) { + var calEachTransform = calendar.opt('eventDataTransform'); + var sourceEachTransform = eventSource ? eventSource.eventDataTransform : null; + if (sourceEachTransform) { + rawEvents = transformEachRawEvent(rawEvents, sourceEachTransform); + } + if (calEachTransform) { + rawEvents = transformEachRawEvent(rawEvents, calEachTransform); + } + return rawEvents; + } + function transformEachRawEvent(rawEvents, func) { + var refinedEvents; + if (!func) { + refinedEvents = rawEvents; + } + else { + refinedEvents = []; + for (var _i = 0, rawEvents_2 = rawEvents; _i < rawEvents_2.length; _i++) { + var rawEvent = rawEvents_2[_i]; + var refinedEvent = func(rawEvent); + if (refinedEvent) { + refinedEvents.push(refinedEvent); + } + else if (refinedEvent == null) { + refinedEvents.push(rawEvent); + } // if a different falsy value, do nothing + } + } + return refinedEvents; + } + function createEmptyEventStore() { + return { defs: {}, instances: {} }; + } + function mergeEventStores(store0, store1) { + return { + defs: __assign({}, store0.defs, store1.defs), + instances: __assign({}, store0.instances, store1.instances) + }; + } + function filterEventStoreDefs(eventStore, filterFunc) { + var defs = filterHash(eventStore.defs, filterFunc); + var instances = filterHash(eventStore.instances, function (instance) { + return defs[instance.defId]; // still exists? + }); + return { defs: defs, instances: instances }; + } + + function parseRange(input, dateEnv) { + var start = null; + var end = null; + if (input.start) { + start = dateEnv.createMarker(input.start); + } + if (input.end) { + end = dateEnv.createMarker(input.end); + } + if (!start && !end) { + return null; + } + if (start && end && end < start) { + return null; + } + return { start: start, end: end }; + } + // SIDE-EFFECT: will mutate ranges. + // Will return a new array result. + function invertRanges(ranges, constraintRange) { + var invertedRanges = []; + var start = constraintRange.start; // the end of the previous range. the start of the new range + var i; + var dateRange; + // ranges need to be in order. required for our date-walking algorithm + ranges.sort(compareRanges); + for (i = 0; i < ranges.length; i++) { + dateRange = ranges[i]; + // add the span of time before the event (if there is any) + if (dateRange.start > start) { // compare millisecond time (skip any ambig logic) + invertedRanges.push({ start: start, end: dateRange.start }); + } + if (dateRange.end > start) { + start = dateRange.end; + } + } + // add the span of time after the last event (if there is any) + if (start < constraintRange.end) { // compare millisecond time (skip any ambig logic) + invertedRanges.push({ start: start, end: constraintRange.end }); + } + return invertedRanges; + } + function compareRanges(range0, range1) { + return range0.start.valueOf() - range1.start.valueOf(); // earlier ranges go first + } + function intersectRanges(range0, range1) { + var start = range0.start; + var end = range0.end; + var newRange = null; + if (range1.start !== null) { + if (start === null) { + start = range1.start; + } + else { + start = new Date(Math.max(start.valueOf(), range1.start.valueOf())); + } + } + if (range1.end != null) { + if (end === null) { + end = range1.end; + } + else { + end = new Date(Math.min(end.valueOf(), range1.end.valueOf())); + } + } + if (start === null || end === null || start < end) { + newRange = { start: start, end: end }; + } + return newRange; + } + function rangesEqual(range0, range1) { + return (range0.start === null ? null : range0.start.valueOf()) === (range1.start === null ? null : range1.start.valueOf()) && + (range0.end === null ? null : range0.end.valueOf()) === (range1.end === null ? null : range1.end.valueOf()); + } + function rangesIntersect(range0, range1) { + return (range0.end === null || range1.start === null || range0.end > range1.start) && + (range0.start === null || range1.end === null || range0.start < range1.end); + } + function rangeContainsRange(outerRange, innerRange) { + return (outerRange.start === null || (innerRange.start !== null && innerRange.start >= outerRange.start)) && + (outerRange.end === null || (innerRange.end !== null && innerRange.end <= outerRange.end)); + } + function rangeContainsMarker(range, date) { + return (range.start === null || date >= range.start) && + (range.end === null || date < range.end); + } + // If the given date is not within the given range, move it inside. + // (If it's past the end, make it one millisecond before the end). + function constrainMarkerToRange(date, range) { + if (range.start != null && date < range.start) { + return range.start; + } + if (range.end != null && date >= range.end) { + return new Date(range.end.valueOf() - 1); + } + return date; + } + + function removeExact(array, exactVal) { + var removeCnt = 0; + var i = 0; + while (i < array.length) { + if (array[i] === exactVal) { + array.splice(i, 1); + removeCnt++; + } + else { + i++; + } + } + return removeCnt; + } + function isArraysEqual(a0, a1) { + var len = a0.length; + var i; + if (len !== a1.length) { // not array? or not same length? + return false; + } + for (i = 0; i < len; i++) { + if (a0[i] !== a1[i]) { + return false; + } + } + return true; + } + + function memoize(workerFunc) { + var args; + var res; + return function () { + if (!args || !isArraysEqual(args, arguments)) { + args = arguments; + res = workerFunc.apply(this, arguments); + } + return res; + }; + } + /* + always executes the workerFunc, but if the result is equal to the previous result, + return the previous result instead. + */ + function memoizeOutput(workerFunc, equalityFunc) { + var cachedRes = null; + return function () { + var newRes = workerFunc.apply(this, arguments); + if (cachedRes === null || !(cachedRes === newRes || equalityFunc(cachedRes, newRes))) { + cachedRes = newRes; + } + return cachedRes; + }; + } + + var EXTENDED_SETTINGS_AND_SEVERITIES = { + week: 3, + separator: 0, + omitZeroMinute: 0, + meridiem: 0, + omitCommas: 0 + }; + var STANDARD_DATE_PROP_SEVERITIES = { + timeZoneName: 7, + era: 6, + year: 5, + month: 4, + day: 2, + weekday: 2, + hour: 1, + minute: 1, + second: 1 + }; + var MERIDIEM_RE = /\s*([ap])\.?m\.?/i; // eats up leading spaces too + var COMMA_RE = /,/g; // we need re for globalness + var MULTI_SPACE_RE = /\s+/g; + var LTR_RE = /\u200e/g; // control character + var UTC_RE = /UTC|GMT/; + var NativeFormatter = /** @class */ (function () { + function NativeFormatter(formatSettings) { + var standardDateProps = {}; + var extendedSettings = {}; + var severity = 0; + for (var name_1 in formatSettings) { + if (name_1 in EXTENDED_SETTINGS_AND_SEVERITIES) { + extendedSettings[name_1] = formatSettings[name_1]; + severity = Math.max(EXTENDED_SETTINGS_AND_SEVERITIES[name_1], severity); + } + else { + standardDateProps[name_1] = formatSettings[name_1]; + if (name_1 in STANDARD_DATE_PROP_SEVERITIES) { + severity = Math.max(STANDARD_DATE_PROP_SEVERITIES[name_1], severity); + } + } + } + this.standardDateProps = standardDateProps; + this.extendedSettings = extendedSettings; + this.severity = severity; + this.buildFormattingFunc = memoize(buildFormattingFunc); + } + NativeFormatter.prototype.format = function (date, context) { + return this.buildFormattingFunc(this.standardDateProps, this.extendedSettings, context)(date); + }; + NativeFormatter.prototype.formatRange = function (start, end, context) { + var _a = this, standardDateProps = _a.standardDateProps, extendedSettings = _a.extendedSettings; + var diffSeverity = computeMarkerDiffSeverity(start.marker, end.marker, context.calendarSystem); + if (!diffSeverity) { + return this.format(start, context); + } + var biggestUnitForPartial = diffSeverity; + if (biggestUnitForPartial > 1 && // the two dates are different in a way that's larger scale than time + (standardDateProps.year === 'numeric' || standardDateProps.year === '2-digit') && + (standardDateProps.month === 'numeric' || standardDateProps.month === '2-digit') && + (standardDateProps.day === 'numeric' || standardDateProps.day === '2-digit')) { + biggestUnitForPartial = 1; // make it look like the dates are only different in terms of time + } + var full0 = this.format(start, context); + var full1 = this.format(end, context); + if (full0 === full1) { + return full0; + } + var partialDateProps = computePartialFormattingOptions(standardDateProps, biggestUnitForPartial); + var partialFormattingFunc = buildFormattingFunc(partialDateProps, extendedSettings, context); + var partial0 = partialFormattingFunc(start); + var partial1 = partialFormattingFunc(end); + var insertion = findCommonInsertion(full0, partial0, full1, partial1); + var separator = extendedSettings.separator || ''; + if (insertion) { + return insertion.before + partial0 + separator + partial1 + insertion.after; + } + return full0 + separator + full1; + }; + NativeFormatter.prototype.getLargestUnit = function () { + switch (this.severity) { + case 7: + case 6: + case 5: + return 'year'; + case 4: + return 'month'; + case 3: + return 'week'; + default: + return 'day'; + } + }; + return NativeFormatter; + }()); + function buildFormattingFunc(standardDateProps, extendedSettings, context) { + var standardDatePropCnt = Object.keys(standardDateProps).length; + if (standardDatePropCnt === 1 && standardDateProps.timeZoneName === 'short') { + return function (date) { + return formatTimeZoneOffset(date.timeZoneOffset); + }; + } + if (standardDatePropCnt === 0 && extendedSettings.week) { + return function (date) { + return formatWeekNumber(context.computeWeekNumber(date.marker), context.weekLabel, context.locale, extendedSettings.week); + }; + } + return buildNativeFormattingFunc(standardDateProps, extendedSettings, context); + } + function buildNativeFormattingFunc(standardDateProps, extendedSettings, context) { + standardDateProps = __assign({}, standardDateProps); // copy + extendedSettings = __assign({}, extendedSettings); // copy + sanitizeSettings(standardDateProps, extendedSettings); + standardDateProps.timeZone = 'UTC'; // we leverage the only guaranteed timeZone for our UTC markers + var normalFormat = new Intl.DateTimeFormat(context.locale.codes, standardDateProps); + var zeroFormat; // needed? + if (extendedSettings.omitZeroMinute) { + var zeroProps = __assign({}, standardDateProps); + delete zeroProps.minute; // seconds and ms were already considered in sanitizeSettings + zeroFormat = new Intl.DateTimeFormat(context.locale.codes, zeroProps); + } + return function (date) { + var marker = date.marker; + var format; + if (zeroFormat && !marker.getUTCMinutes()) { + format = zeroFormat; + } + else { + format = normalFormat; + } + var s = format.format(marker); + return postProcess(s, date, standardDateProps, extendedSettings, context); + }; + } + function sanitizeSettings(standardDateProps, extendedSettings) { + // deal with a browser inconsistency where formatting the timezone + // requires that the hour/minute be present. + if (standardDateProps.timeZoneName) { + if (!standardDateProps.hour) { + standardDateProps.hour = '2-digit'; + } + if (!standardDateProps.minute) { + standardDateProps.minute = '2-digit'; + } + } + // only support short timezone names + if (standardDateProps.timeZoneName === 'long') { + standardDateProps.timeZoneName = 'short'; + } + // if requesting to display seconds, MUST display minutes + if (extendedSettings.omitZeroMinute && (standardDateProps.second || standardDateProps.millisecond)) { + delete extendedSettings.omitZeroMinute; + } + } + function postProcess(s, date, standardDateProps, extendedSettings, context) { + s = s.replace(LTR_RE, ''); // remove left-to-right control chars. do first. good for other regexes + if (standardDateProps.timeZoneName === 'short') { + s = injectTzoStr(s, (context.timeZone === 'UTC' || date.timeZoneOffset == null) ? + 'UTC' : // important to normalize for IE, which does "GMT" + formatTimeZoneOffset(date.timeZoneOffset)); + } + if (extendedSettings.omitCommas) { + s = s.replace(COMMA_RE, '').trim(); + } + if (extendedSettings.omitZeroMinute) { + s = s.replace(':00', ''); // zeroFormat doesn't always achieve this + } + // ^ do anything that might create adjacent spaces before this point, + // because MERIDIEM_RE likes to eat up loading spaces + if (extendedSettings.meridiem === false) { + s = s.replace(MERIDIEM_RE, '').trim(); + } + else if (extendedSettings.meridiem === 'narrow') { // a/p + s = s.replace(MERIDIEM_RE, function (m0, m1) { + return m1.toLocaleLowerCase(); + }); + } + else if (extendedSettings.meridiem === 'short') { // am/pm + s = s.replace(MERIDIEM_RE, function (m0, m1) { + return m1.toLocaleLowerCase() + 'm'; + }); + } + else if (extendedSettings.meridiem === 'lowercase') { // other meridiem transformers already converted to lowercase + s = s.replace(MERIDIEM_RE, function (m0) { + return m0.toLocaleLowerCase(); + }); + } + s = s.replace(MULTI_SPACE_RE, ' '); + s = s.trim(); + return s; + } + function injectTzoStr(s, tzoStr) { + var replaced = false; + s = s.replace(UTC_RE, function () { + replaced = true; + return tzoStr; + }); + // IE11 doesn't include UTC/GMT in the original string, so append to end + if (!replaced) { + s += ' ' + tzoStr; + } + return s; + } + function formatWeekNumber(num, weekLabel, locale, display) { + var parts = []; + if (display === 'narrow') { + parts.push(weekLabel); + } + else if (display === 'short') { + parts.push(weekLabel, ' '); + } + // otherwise, considered 'numeric' + parts.push(locale.simpleNumberFormat.format(num)); + if (locale.options.isRtl) { // TODO: use control characters instead? + parts.reverse(); + } + return parts.join(''); + } + // Range Formatting Utils + // 0 = exactly the same + // 1 = different by time + // and bigger + function computeMarkerDiffSeverity(d0, d1, ca) { + if (ca.getMarkerYear(d0) !== ca.getMarkerYear(d1)) { + return 5; + } + if (ca.getMarkerMonth(d0) !== ca.getMarkerMonth(d1)) { + return 4; + } + if (ca.getMarkerDay(d0) !== ca.getMarkerDay(d1)) { + return 2; + } + if (timeAsMs(d0) !== timeAsMs(d1)) { + return 1; + } + return 0; + } + function computePartialFormattingOptions(options, biggestUnit) { + var partialOptions = {}; + for (var name_2 in options) { + if (!(name_2 in STANDARD_DATE_PROP_SEVERITIES) || // not a date part prop (like timeZone) + STANDARD_DATE_PROP_SEVERITIES[name_2] <= biggestUnit) { + partialOptions[name_2] = options[name_2]; + } + } + return partialOptions; + } + function findCommonInsertion(full0, partial0, full1, partial1) { + var i0 = 0; + while (i0 < full0.length) { + var found0 = full0.indexOf(partial0, i0); + if (found0 === -1) { + break; + } + var before0 = full0.substr(0, found0); + i0 = found0 + partial0.length; + var after0 = full0.substr(i0); + var i1 = 0; + while (i1 < full1.length) { + var found1 = full1.indexOf(partial1, i1); + if (found1 === -1) { + break; + } + var before1 = full1.substr(0, found1); + i1 = found1 + partial1.length; + var after1 = full1.substr(i1); + if (before0 === before1 && after0 === after1) { + return { + before: before0, + after: after0 + }; + } + } + } + return null; + } + + /* + TODO: fix the terminology of "formatter" vs "formatting func" + */ + /* + At the time of instantiation, this object does not know which cmd-formatting system it will use. + It receives this at the time of formatting, as a setting. + */ + var CmdFormatter = /** @class */ (function () { + function CmdFormatter(cmdStr, separator) { + this.cmdStr = cmdStr; + this.separator = separator; + } + CmdFormatter.prototype.format = function (date, context) { + return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(date, null, context, this.separator)); + }; + CmdFormatter.prototype.formatRange = function (start, end, context) { + return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(start, end, context, this.separator)); + }; + return CmdFormatter; + }()); + + var FuncFormatter = /** @class */ (function () { + function FuncFormatter(func) { + this.func = func; + } + FuncFormatter.prototype.format = function (date, context) { + return this.func(createVerboseFormattingArg(date, null, context)); + }; + FuncFormatter.prototype.formatRange = function (start, end, context) { + return this.func(createVerboseFormattingArg(start, end, context)); + }; + return FuncFormatter; + }()); + + // Formatter Object Creation + function createFormatter(input, defaultSeparator) { + if (typeof input === 'object' && input) { // non-null object + if (typeof defaultSeparator === 'string') { + input = __assign({ separator: defaultSeparator }, input); + } + return new NativeFormatter(input); + } + else if (typeof input === 'string') { + return new CmdFormatter(input, defaultSeparator); + } + else if (typeof input === 'function') { + return new FuncFormatter(input); + } + } + // String Utils + // timeZoneOffset is in minutes + function buildIsoString(marker, timeZoneOffset, stripZeroTime) { + if (stripZeroTime === void 0) { stripZeroTime = false; } + var s = marker.toISOString(); + s = s.replace('.000', ''); + if (stripZeroTime) { + s = s.replace('T00:00:00Z', ''); + } + if (s.length > 10) { // time part wasn't stripped, can add timezone info + if (timeZoneOffset == null) { + s = s.replace('Z', ''); + } + else if (timeZoneOffset !== 0) { + s = s.replace('Z', formatTimeZoneOffset(timeZoneOffset, true)); + } + // otherwise, its UTC-0 and we want to keep the Z + } + return s; + } + function formatIsoTimeString(marker) { + return padStart(marker.getUTCHours(), 2) + ':' + + padStart(marker.getUTCMinutes(), 2) + ':' + + padStart(marker.getUTCSeconds(), 2); + } + function formatTimeZoneOffset(minutes, doIso) { + if (doIso === void 0) { doIso = false; } + var sign = minutes < 0 ? '-' : '+'; + var abs = Math.abs(minutes); + var hours = Math.floor(abs / 60); + var mins = Math.round(abs % 60); + if (doIso) { + return sign + padStart(hours, 2) + ':' + padStart(mins, 2); + } + else { + return 'GMT' + sign + hours + (mins ? ':' + padStart(mins, 2) : ''); + } + } + // Arg Utils + function createVerboseFormattingArg(start, end, context, separator) { + var startInfo = expandZonedMarker(start, context.calendarSystem); + var endInfo = end ? expandZonedMarker(end, context.calendarSystem) : null; + return { + date: startInfo, + start: startInfo, + end: endInfo, + timeZone: context.timeZone, + localeCodes: context.locale.codes, + separator: separator + }; + } + function expandZonedMarker(dateInfo, calendarSystem) { + var a = calendarSystem.markerToArray(dateInfo.marker); + return { + marker: dateInfo.marker, + timeZoneOffset: dateInfo.timeZoneOffset, + array: a, + year: a[0], + month: a[1], + day: a[2], + hour: a[3], + minute: a[4], + second: a[5], + millisecond: a[6] + }; + } + + var EventSourceApi = /** @class */ (function () { + function EventSourceApi(calendar, internalEventSource) { + this.calendar = calendar; + this.internalEventSource = internalEventSource; + } + EventSourceApi.prototype.remove = function () { + this.calendar.dispatch({ + type: 'REMOVE_EVENT_SOURCE', + sourceId: this.internalEventSource.sourceId + }); + }; + EventSourceApi.prototype.refetch = function () { + this.calendar.dispatch({ + type: 'FETCH_EVENT_SOURCES', + sourceIds: [this.internalEventSource.sourceId] + }); + }; + Object.defineProperty(EventSourceApi.prototype, "id", { + get: function () { + return this.internalEventSource.publicId; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventSourceApi.prototype, "url", { + // only relevant to json-feed event sources + get: function () { + return this.internalEventSource.meta.url; + }, + enumerable: true, + configurable: true + }); + return EventSourceApi; + }()); + + var EventApi = /** @class */ (function () { + function EventApi(calendar, def, instance) { + this._calendar = calendar; + this._def = def; + this._instance = instance || null; + } + /* + TODO: make event struct more responsible for this + */ + EventApi.prototype.setProp = function (name, val) { + var _a, _b; + if (name in DATE_PROPS) ; + else if (name in NON_DATE_PROPS) { + if (typeof NON_DATE_PROPS[name] === 'function') { + val = NON_DATE_PROPS[name](val); + } + this.mutate({ + standardProps: (_a = {}, _a[name] = val, _a) + }); + } + else if (name in UNSCOPED_EVENT_UI_PROPS) { + var ui = void 0; + if (typeof UNSCOPED_EVENT_UI_PROPS[name] === 'function') { + val = UNSCOPED_EVENT_UI_PROPS[name](val); + } + if (name === 'color') { + ui = { backgroundColor: val, borderColor: val }; + } + else if (name === 'editable') { + ui = { startEditable: val, durationEditable: val }; + } + else { + ui = (_b = {}, _b[name] = val, _b); + } + this.mutate({ + standardProps: { ui: ui } + }); + } + }; + EventApi.prototype.setExtendedProp = function (name, val) { + var _a; + this.mutate({ + extendedProps: (_a = {}, _a[name] = val, _a) + }); + }; + EventApi.prototype.setStart = function (startInput, options) { + if (options === void 0) { options = {}; } + var dateEnv = this._calendar.dateEnv; + var start = dateEnv.createMarker(startInput); + if (start && this._instance) { // TODO: warning if parsed bad + var instanceRange = this._instance.range; + var startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity); // what if parsed bad!? + if (options.maintainDuration) { + this.mutate({ datesDelta: startDelta }); + } + else { + this.mutate({ startDelta: startDelta }); + } + } + }; + EventApi.prototype.setEnd = function (endInput, options) { + if (options === void 0) { options = {}; } + var dateEnv = this._calendar.dateEnv; + var end; + if (endInput != null) { + end = dateEnv.createMarker(endInput); + if (!end) { + return; // TODO: warning if parsed bad + } + } + if (this._instance) { + if (end) { + var endDelta = diffDates(this._instance.range.end, end, dateEnv, options.granularity); + this.mutate({ endDelta: endDelta }); + } + else { + this.mutate({ standardProps: { hasEnd: false } }); + } + } + }; + EventApi.prototype.setDates = function (startInput, endInput, options) { + if (options === void 0) { options = {}; } + var dateEnv = this._calendar.dateEnv; + var standardProps = { allDay: options.allDay }; + var start = dateEnv.createMarker(startInput); + var end; + if (!start) { + return; // TODO: warning if parsed bad + } + if (endInput != null) { + end = dateEnv.createMarker(endInput); + if (!end) { // TODO: warning if parsed bad + return; + } + } + if (this._instance) { + var instanceRange = this._instance.range; + // when computing the diff for an event being converted to all-day, + // compute diff off of the all-day values the way event-mutation does. + if (options.allDay === true) { + instanceRange = computeAlignedDayRange(instanceRange); + } + var startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity); + if (end) { + var endDelta = diffDates(instanceRange.end, end, dateEnv, options.granularity); + if (durationsEqual(startDelta, endDelta)) { + this.mutate({ datesDelta: startDelta, standardProps: standardProps }); + } + else { + this.mutate({ startDelta: startDelta, endDelta: endDelta, standardProps: standardProps }); + } + } + else { // means "clear the end" + standardProps.hasEnd = false; + this.mutate({ datesDelta: startDelta, standardProps: standardProps }); + } + } + }; + EventApi.prototype.moveStart = function (deltaInput) { + var delta = createDuration(deltaInput); + if (delta) { // TODO: warning if parsed bad + this.mutate({ startDelta: delta }); + } + }; + EventApi.prototype.moveEnd = function (deltaInput) { + var delta = createDuration(deltaInput); + if (delta) { // TODO: warning if parsed bad + this.mutate({ endDelta: delta }); + } + }; + EventApi.prototype.moveDates = function (deltaInput) { + var delta = createDuration(deltaInput); + if (delta) { // TODO: warning if parsed bad + this.mutate({ datesDelta: delta }); + } + }; + EventApi.prototype.setAllDay = function (allDay, options) { + if (options === void 0) { options = {}; } + var standardProps = { allDay: allDay }; + var maintainDuration = options.maintainDuration; + if (maintainDuration == null) { + maintainDuration = this._calendar.opt('allDayMaintainDuration'); + } + if (this._def.allDay !== allDay) { + standardProps.hasEnd = maintainDuration; + } + this.mutate({ standardProps: standardProps }); + }; + EventApi.prototype.formatRange = function (formatInput) { + var dateEnv = this._calendar.dateEnv; + var instance = this._instance; + var formatter = createFormatter(formatInput, this._calendar.opt('defaultRangeSeparator')); + if (this._def.hasEnd) { + return dateEnv.formatRange(instance.range.start, instance.range.end, formatter, { + forcedStartTzo: instance.forcedStartTzo, + forcedEndTzo: instance.forcedEndTzo + }); + } + else { + return dateEnv.format(instance.range.start, formatter, { + forcedTzo: instance.forcedStartTzo + }); + } + }; + EventApi.prototype.mutate = function (mutation) { + var def = this._def; + var instance = this._instance; + if (instance) { + this._calendar.dispatch({ + type: 'MUTATE_EVENTS', + instanceId: instance.instanceId, + mutation: mutation, + fromApi: true + }); + var eventStore = this._calendar.state.eventStore; + this._def = eventStore.defs[def.defId]; + this._instance = eventStore.instances[instance.instanceId]; + } + }; + EventApi.prototype.remove = function () { + this._calendar.dispatch({ + type: 'REMOVE_EVENT_DEF', + defId: this._def.defId + }); + }; + Object.defineProperty(EventApi.prototype, "source", { + get: function () { + var sourceId = this._def.sourceId; + if (sourceId) { + return new EventSourceApi(this._calendar, this._calendar.state.eventSources[sourceId]); + } + return null; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "start", { + get: function () { + return this._instance ? + this._calendar.dateEnv.toDate(this._instance.range.start) : + null; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "end", { + get: function () { + return (this._instance && this._def.hasEnd) ? + this._calendar.dateEnv.toDate(this._instance.range.end) : + null; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "id", { + // computable props that all access the def + // TODO: find a TypeScript-compatible way to do this at scale + get: function () { return this._def.publicId; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "groupId", { + get: function () { return this._def.groupId; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "allDay", { + get: function () { return this._def.allDay; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "title", { + get: function () { return this._def.title; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "url", { + get: function () { return this._def.url; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "rendering", { + get: function () { return this._def.rendering; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "startEditable", { + get: function () { return this._def.ui.startEditable; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "durationEditable", { + get: function () { return this._def.ui.durationEditable; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "constraint", { + get: function () { return this._def.ui.constraints[0] || null; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "overlap", { + get: function () { return this._def.ui.overlap; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "allow", { + get: function () { return this._def.ui.allows[0] || null; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "backgroundColor", { + get: function () { return this._def.ui.backgroundColor; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "borderColor", { + get: function () { return this._def.ui.borderColor; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "textColor", { + get: function () { return this._def.ui.textColor; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "classNames", { + // NOTE: user can't modify these because Object.freeze was called in event-def parsing + get: function () { return this._def.ui.classNames; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(EventApi.prototype, "extendedProps", { + get: function () { return this._def.extendedProps; }, + enumerable: true, + configurable: true + }); + return EventApi; + }()); + + /* + Specifying nextDayThreshold signals that all-day ranges should be sliced. + */ + function sliceEventStore(eventStore, eventUiBases, framingRange, nextDayThreshold) { + var inverseBgByGroupId = {}; + var inverseBgByDefId = {}; + var defByGroupId = {}; + var bgRanges = []; + var fgRanges = []; + var eventUis = compileEventUis(eventStore.defs, eventUiBases); + for (var defId in eventStore.defs) { + var def = eventStore.defs[defId]; + if (def.rendering === 'inverse-background') { + if (def.groupId) { + inverseBgByGroupId[def.groupId] = []; + if (!defByGroupId[def.groupId]) { + defByGroupId[def.groupId] = def; + } + } + else { + inverseBgByDefId[defId] = []; + } + } + } + for (var instanceId in eventStore.instances) { + var instance = eventStore.instances[instanceId]; + var def = eventStore.defs[instance.defId]; + var ui = eventUis[def.defId]; + var origRange = instance.range; + var normalRange = (!def.allDay && nextDayThreshold) ? + computeVisibleDayRange(origRange, nextDayThreshold) : + origRange; + var slicedRange = intersectRanges(normalRange, framingRange); + if (slicedRange) { + if (def.rendering === 'inverse-background') { + if (def.groupId) { + inverseBgByGroupId[def.groupId].push(slicedRange); + } + else { + inverseBgByDefId[instance.defId].push(slicedRange); + } + } + else { + (def.rendering === 'background' ? bgRanges : fgRanges).push({ + def: def, + ui: ui, + instance: instance, + range: slicedRange, + isStart: normalRange.start && normalRange.start.valueOf() === slicedRange.start.valueOf(), + isEnd: normalRange.end && normalRange.end.valueOf() === slicedRange.end.valueOf() + }); + } + } + } + for (var groupId in inverseBgByGroupId) { // BY GROUP + var ranges = inverseBgByGroupId[groupId]; + var invertedRanges = invertRanges(ranges, framingRange); + for (var _i = 0, invertedRanges_1 = invertedRanges; _i < invertedRanges_1.length; _i++) { + var invertedRange = invertedRanges_1[_i]; + var def = defByGroupId[groupId]; + var ui = eventUis[def.defId]; + bgRanges.push({ + def: def, + ui: ui, + instance: null, + range: invertedRange, + isStart: false, + isEnd: false + }); + } + } + for (var defId in inverseBgByDefId) { + var ranges = inverseBgByDefId[defId]; + var invertedRanges = invertRanges(ranges, framingRange); + for (var _a = 0, invertedRanges_2 = invertedRanges; _a < invertedRanges_2.length; _a++) { + var invertedRange = invertedRanges_2[_a]; + bgRanges.push({ + def: eventStore.defs[defId], + ui: eventUis[defId], + instance: null, + range: invertedRange, + isStart: false, + isEnd: false + }); + } + } + return { bg: bgRanges, fg: fgRanges }; + } + function hasBgRendering(def) { + return def.rendering === 'background' || def.rendering === 'inverse-background'; + } + function filterSegsViaEls(view, segs, isMirror) { + if (view.hasPublicHandlers('eventRender')) { + segs = segs.filter(function (seg) { + var custom = view.publiclyTrigger('eventRender', [ + { + event: new EventApi(view.calendar, seg.eventRange.def, seg.eventRange.instance), + isMirror: isMirror, + isStart: seg.isStart, + isEnd: seg.isEnd, + // TODO: include seg.range once all components consistently generate it + el: seg.el, + view: view + } + ]); + if (custom === false) { // means don't render at all + return false; + } + else if (custom && custom !== true) { + seg.el = custom; + } + return true; + }); + } + for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { + var seg = segs_1[_i]; + setElSeg(seg.el, seg); + } + return segs; + } + function setElSeg(el, seg) { + el.fcSeg = seg; + } + function getElSeg(el) { + return el.fcSeg || null; + } + // event ui computation + function compileEventUis(eventDefs, eventUiBases) { + return mapHash(eventDefs, function (eventDef) { + return compileEventUi(eventDef, eventUiBases); + }); + } + function compileEventUi(eventDef, eventUiBases) { + var uis = []; + if (eventUiBases['']) { + uis.push(eventUiBases['']); + } + if (eventUiBases[eventDef.defId]) { + uis.push(eventUiBases[eventDef.defId]); + } + uis.push(eventDef.ui); + return combineEventUis(uis); + } + + // applies the mutation to ALL defs/instances within the event store + function applyMutationToEventStore(eventStore, eventConfigBase, mutation, calendar) { + var eventConfigs = compileEventUis(eventStore.defs, eventConfigBase); + var dest = createEmptyEventStore(); + for (var defId in eventStore.defs) { + var def = eventStore.defs[defId]; + dest.defs[defId] = applyMutationToEventDef(def, eventConfigs[defId], mutation, calendar.pluginSystem.hooks.eventDefMutationAppliers, calendar); + } + for (var instanceId in eventStore.instances) { + var instance = eventStore.instances[instanceId]; + var def = dest.defs[instance.defId]; // important to grab the newly modified def + dest.instances[instanceId] = applyMutationToEventInstance(instance, def, eventConfigs[instance.defId], mutation, calendar); + } + return dest; + } + function applyMutationToEventDef(eventDef, eventConfig, mutation, appliers, calendar) { + var standardProps = mutation.standardProps || {}; + // if hasEnd has not been specified, guess a good value based on deltas. + // if duration will change, there's no way the default duration will persist, + // and thus, we need to mark the event as having a real end + if (standardProps.hasEnd == null && + eventConfig.durationEditable && + (mutation.startDelta || mutation.endDelta)) { + standardProps.hasEnd = true; // TODO: is this mutation okay? + } + var copy = __assign({}, eventDef, standardProps, { ui: __assign({}, eventDef.ui, standardProps.ui) }); + if (mutation.extendedProps) { + copy.extendedProps = __assign({}, copy.extendedProps, mutation.extendedProps); + } + for (var _i = 0, appliers_1 = appliers; _i < appliers_1.length; _i++) { + var applier = appliers_1[_i]; + applier(copy, mutation, calendar); + } + if (!copy.hasEnd && calendar.opt('forceEventDuration')) { + copy.hasEnd = true; + } + return copy; + } + function applyMutationToEventInstance(eventInstance, eventDef, // must first be modified by applyMutationToEventDef + eventConfig, mutation, calendar) { + var dateEnv = calendar.dateEnv; + var forceAllDay = mutation.standardProps && mutation.standardProps.allDay === true; + var clearEnd = mutation.standardProps && mutation.standardProps.hasEnd === false; + var copy = __assign({}, eventInstance); + if (forceAllDay) { + copy.range = computeAlignedDayRange(copy.range); + } + if (mutation.datesDelta && eventConfig.startEditable) { + copy.range = { + start: dateEnv.add(copy.range.start, mutation.datesDelta), + end: dateEnv.add(copy.range.end, mutation.datesDelta) + }; + } + if (mutation.startDelta && eventConfig.durationEditable) { + copy.range = { + start: dateEnv.add(copy.range.start, mutation.startDelta), + end: copy.range.end + }; + } + if (mutation.endDelta && eventConfig.durationEditable) { + copy.range = { + start: copy.range.start, + end: dateEnv.add(copy.range.end, mutation.endDelta) + }; + } + if (clearEnd) { + copy.range = { + start: copy.range.start, + end: calendar.getDefaultEventEnd(eventDef.allDay, copy.range.start) + }; + } + // in case event was all-day but the supplied deltas were not + // better util for this? + if (eventDef.allDay) { + copy.range = { + start: startOfDay(copy.range.start), + end: startOfDay(copy.range.end) + }; + } + // handle invalid durations + if (copy.range.end < copy.range.start) { + copy.range.end = calendar.getDefaultEventEnd(eventDef.allDay, copy.range.start); + } + return copy; + } + + function reduceEventStore (eventStore, action, eventSources, dateProfile, calendar) { + switch (action.type) { + case 'RECEIVE_EVENTS': // raw + return receiveRawEvents(eventStore, eventSources[action.sourceId], action.fetchId, action.fetchRange, action.rawEvents, calendar); + case 'ADD_EVENTS': // already parsed, but not expanded + return addEvent(eventStore, action.eventStore, // new ones + dateProfile ? dateProfile.activeRange : null, calendar); + case 'MERGE_EVENTS': // already parsed and expanded + return mergeEventStores(eventStore, action.eventStore); + case 'PREV': // TODO: how do we track all actions that affect dateProfile :( + case 'NEXT': + case 'SET_DATE': + case 'SET_VIEW_TYPE': + if (dateProfile) { + return expandRecurring(eventStore, dateProfile.activeRange, calendar); + } + else { + return eventStore; + } + case 'CHANGE_TIMEZONE': + return rezoneDates(eventStore, action.oldDateEnv, calendar.dateEnv); + case 'MUTATE_EVENTS': + return applyMutationToRelated(eventStore, action.instanceId, action.mutation, action.fromApi, calendar); + case 'REMOVE_EVENT_INSTANCES': + return excludeInstances(eventStore, action.instances); + case 'REMOVE_EVENT_DEF': + return filterEventStoreDefs(eventStore, function (eventDef) { + return eventDef.defId !== action.defId; + }); + case 'REMOVE_EVENT_SOURCE': + return excludeEventsBySourceId(eventStore, action.sourceId); + case 'REMOVE_ALL_EVENT_SOURCES': + return filterEventStoreDefs(eventStore, function (eventDef) { + return !eventDef.sourceId; // only keep events with no source id + }); + case 'REMOVE_ALL_EVENTS': + return createEmptyEventStore(); + case 'RESET_EVENTS': + return { + defs: eventStore.defs, + instances: eventStore.instances + }; + default: + return eventStore; + } + } + function receiveRawEvents(eventStore, eventSource, fetchId, fetchRange, rawEvents, calendar) { + if (eventSource && // not already removed + fetchId === eventSource.latestFetchId // TODO: wish this logic was always in event-sources + ) { + var subset = parseEvents(transformRawEvents(rawEvents, eventSource, calendar), eventSource.sourceId, calendar); + if (fetchRange) { + subset = expandRecurring(subset, fetchRange, calendar); + } + return mergeEventStores(excludeEventsBySourceId(eventStore, eventSource.sourceId), subset); + } + return eventStore; + } + function addEvent(eventStore, subset, expandRange, calendar) { + if (expandRange) { + subset = expandRecurring(subset, expandRange, calendar); + } + return mergeEventStores(eventStore, subset); + } + function rezoneDates(eventStore, oldDateEnv, newDateEnv) { + var defs = eventStore.defs; + var instances = mapHash(eventStore.instances, function (instance) { + var def = defs[instance.defId]; + if (def.allDay || def.recurringDef) { + return instance; // isn't dependent on timezone + } + else { + return __assign({}, instance, { range: { + start: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.start, instance.forcedStartTzo)), + end: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.end, instance.forcedEndTzo)) + }, forcedStartTzo: newDateEnv.canComputeOffset ? null : instance.forcedStartTzo, forcedEndTzo: newDateEnv.canComputeOffset ? null : instance.forcedEndTzo }); + } + }); + return { defs: defs, instances: instances }; + } + function applyMutationToRelated(eventStore, instanceId, mutation, fromApi, calendar) { + var relevant = getRelevantEvents(eventStore, instanceId); + var eventConfigBase = fromApi ? + { '': { + startEditable: true, + durationEditable: true, + constraints: [], + overlap: null, + allows: [], + backgroundColor: '', + borderColor: '', + textColor: '', + classNames: [] + } } : + calendar.eventUiBases; + relevant = applyMutationToEventStore(relevant, eventConfigBase, mutation, calendar); + return mergeEventStores(eventStore, relevant); + } + function excludeEventsBySourceId(eventStore, sourceId) { + return filterEventStoreDefs(eventStore, function (eventDef) { + return eventDef.sourceId !== sourceId; + }); + } + // QUESTION: why not just return instances? do a general object-property-exclusion util + function excludeInstances(eventStore, removals) { + return { + defs: eventStore.defs, + instances: filterHash(eventStore.instances, function (instance) { + return !removals[instance.instanceId]; + }) + }; + } + + // high-level segmenting-aware tester functions + // ------------------------------------------------------------------------------------------------------------------------ + function isInteractionValid(interaction, calendar) { + return isNewPropsValid({ eventDrag: interaction }, calendar); // HACK: the eventDrag props is used for ALL interactions + } + function isDateSelectionValid(dateSelection, calendar) { + return isNewPropsValid({ dateSelection: dateSelection }, calendar); + } + function isNewPropsValid(newProps, calendar) { + var view = calendar.view; + var props = __assign({ businessHours: view ? view.props.businessHours : createEmptyEventStore(), dateSelection: '', eventStore: calendar.state.eventStore, eventUiBases: calendar.eventUiBases, eventSelection: '', eventDrag: null, eventResize: null }, newProps); + return (calendar.pluginSystem.hooks.isPropsValid || isPropsValid)(props, calendar); + } + function isPropsValid(state, calendar, dateSpanMeta, filterConfig) { + if (dateSpanMeta === void 0) { dateSpanMeta = {}; } + if (state.eventDrag && !isInteractionPropsValid(state, calendar, dateSpanMeta, filterConfig)) { + return false; + } + if (state.dateSelection && !isDateSelectionPropsValid(state, calendar, dateSpanMeta, filterConfig)) { + return false; + } + return true; + } + // Moving Event Validation + // ------------------------------------------------------------------------------------------------------------------------ + function isInteractionPropsValid(state, calendar, dateSpanMeta, filterConfig) { + var interaction = state.eventDrag; // HACK: the eventDrag props is used for ALL interactions + var subjectEventStore = interaction.mutatedEvents; + var subjectDefs = subjectEventStore.defs; + var subjectInstances = subjectEventStore.instances; + var subjectConfigs = compileEventUis(subjectDefs, interaction.isEvent ? + state.eventUiBases : + { '': calendar.selectionConfig } // if not a real event, validate as a selection + ); + if (filterConfig) { + subjectConfigs = mapHash(subjectConfigs, filterConfig); + } + var otherEventStore = excludeInstances(state.eventStore, interaction.affectedEvents.instances); // exclude the subject events. TODO: exclude defs too? + var otherDefs = otherEventStore.defs; + var otherInstances = otherEventStore.instances; + var otherConfigs = compileEventUis(otherDefs, state.eventUiBases); + for (var subjectInstanceId in subjectInstances) { + var subjectInstance = subjectInstances[subjectInstanceId]; + var subjectRange = subjectInstance.range; + var subjectConfig = subjectConfigs[subjectInstance.defId]; + var subjectDef = subjectDefs[subjectInstance.defId]; + // constraint + if (!allConstraintsPass(subjectConfig.constraints, subjectRange, otherEventStore, state.businessHours, calendar)) { + return false; + } + // overlap + var overlapFunc = calendar.opt('eventOverlap'); + if (typeof overlapFunc !== 'function') { + overlapFunc = null; + } + for (var otherInstanceId in otherInstances) { + var otherInstance = otherInstances[otherInstanceId]; + // intersect! evaluate + if (rangesIntersect(subjectRange, otherInstance.range)) { + var otherOverlap = otherConfigs[otherInstance.defId].overlap; + // consider the other event's overlap. only do this if the subject event is a "real" event + if (otherOverlap === false && interaction.isEvent) { + return false; + } + if (subjectConfig.overlap === false) { + return false; + } + if (overlapFunc && !overlapFunc(new EventApi(calendar, otherDefs[otherInstance.defId], otherInstance), // still event + new EventApi(calendar, subjectDef, subjectInstance) // moving event + )) { + return false; + } + } + } + // allow (a function) + var calendarEventStore = calendar.state.eventStore; // need global-to-calendar, not local to component (splittable)state + for (var _i = 0, _a = subjectConfig.allows; _i < _a.length; _i++) { + var subjectAllow = _a[_i]; + var subjectDateSpan = __assign({}, dateSpanMeta, { range: subjectInstance.range, allDay: subjectDef.allDay }); + var origDef = calendarEventStore.defs[subjectDef.defId]; + var origInstance = calendarEventStore.instances[subjectInstanceId]; + var eventApi = void 0; + if (origDef) { // was previously in the calendar + eventApi = new EventApi(calendar, origDef, origInstance); + } + else { // was an external event + eventApi = new EventApi(calendar, subjectDef); // no instance, because had no dates + } + if (!subjectAllow(calendar.buildDateSpanApi(subjectDateSpan), eventApi)) { + return false; + } + } + } + return true; + } + // Date Selection Validation + // ------------------------------------------------------------------------------------------------------------------------ + function isDateSelectionPropsValid(state, calendar, dateSpanMeta, filterConfig) { + var relevantEventStore = state.eventStore; + var relevantDefs = relevantEventStore.defs; + var relevantInstances = relevantEventStore.instances; + var selection = state.dateSelection; + var selectionRange = selection.range; + var selectionConfig = calendar.selectionConfig; + if (filterConfig) { + selectionConfig = filterConfig(selectionConfig); + } + // constraint + if (!allConstraintsPass(selectionConfig.constraints, selectionRange, relevantEventStore, state.businessHours, calendar)) { + return false; + } + // overlap + var overlapFunc = calendar.opt('selectOverlap'); + if (typeof overlapFunc !== 'function') { + overlapFunc = null; + } + for (var relevantInstanceId in relevantInstances) { + var relevantInstance = relevantInstances[relevantInstanceId]; + // intersect! evaluate + if (rangesIntersect(selectionRange, relevantInstance.range)) { + if (selectionConfig.overlap === false) { + return false; + } + if (overlapFunc && !overlapFunc(new EventApi(calendar, relevantDefs[relevantInstance.defId], relevantInstance))) { + return false; + } + } + } + // allow (a function) + for (var _i = 0, _a = selectionConfig.allows; _i < _a.length; _i++) { + var selectionAllow = _a[_i]; + var fullDateSpan = __assign({}, dateSpanMeta, selection); + if (!selectionAllow(calendar.buildDateSpanApi(fullDateSpan), null)) { + return false; + } + } + return true; + } + // Constraint Utils + // ------------------------------------------------------------------------------------------------------------------------ + function allConstraintsPass(constraints, subjectRange, otherEventStore, businessHoursUnexpanded, calendar) { + for (var _i = 0, constraints_1 = constraints; _i < constraints_1.length; _i++) { + var constraint = constraints_1[_i]; + if (!anyRangesContainRange(constraintToRanges(constraint, subjectRange, otherEventStore, businessHoursUnexpanded, calendar), subjectRange)) { + return false; + } + } + return true; + } + function constraintToRanges(constraint, subjectRange, // for expanding a recurring constraint, or expanding business hours + otherEventStore, // for if constraint is an even group ID + businessHoursUnexpanded, // for if constraint is 'businessHours' + calendar // for expanding businesshours + ) { + if (constraint === 'businessHours') { + return eventStoreToRanges(expandRecurring(businessHoursUnexpanded, subjectRange, calendar)); + } + else if (typeof constraint === 'string') { // an group ID + return eventStoreToRanges(filterEventStoreDefs(otherEventStore, function (eventDef) { + return eventDef.groupId === constraint; + })); + } + else if (typeof constraint === 'object' && constraint) { // non-null object + return eventStoreToRanges(expandRecurring(constraint, subjectRange, calendar)); + } + return []; // if it's false + } + // TODO: move to event-store file? + function eventStoreToRanges(eventStore) { + var instances = eventStore.instances; + var ranges = []; + for (var instanceId in instances) { + ranges.push(instances[instanceId].range); + } + return ranges; + } + // TODO: move to geom file? + function anyRangesContainRange(outerRanges, innerRange) { + for (var _i = 0, outerRanges_1 = outerRanges; _i < outerRanges_1.length; _i++) { + var outerRange = outerRanges_1[_i]; + if (rangeContainsRange(outerRange, innerRange)) { + return true; + } + } + return false; + } + // Parsing + // ------------------------------------------------------------------------------------------------------------------------ + function normalizeConstraint(input, calendar) { + if (Array.isArray(input)) { + return parseEvents(input, '', calendar, true); // allowOpenRange=true + } + else if (typeof input === 'object' && input) { // non-null object + return parseEvents([input], '', calendar, true); // allowOpenRange=true + } + else if (input != null) { + return String(input); + } + else { + return null; + } + } + + function htmlEscape(s) { + return (s + '').replace(/&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/'/g, ''') + .replace(/"/g, '"') + .replace(/\n/g, '<br />'); + } + // Given a hash of CSS properties, returns a string of CSS. + // Uses property names as-is (no camel-case conversion). Will not make statements for null/undefined values. + function cssToStr(cssProps) { + var statements = []; + for (var name_1 in cssProps) { + var val = cssProps[name_1]; + if (val != null && val !== '') { + statements.push(name_1 + ':' + val); + } + } + return statements.join(';'); + } + // Given an object hash of HTML attribute names to values, + // generates a string that can be injected between < > in HTML + function attrsToStr(attrs) { + var parts = []; + for (var name_2 in attrs) { + var val = attrs[name_2]; + if (val != null) { + parts.push(name_2 + '="' + htmlEscape(val) + '"'); + } + } + return parts.join(' '); + } + function parseClassName(raw) { + if (Array.isArray(raw)) { + return raw; + } + else if (typeof raw === 'string') { + return raw.split(/\s+/); + } + else { + return []; + } + } + + var UNSCOPED_EVENT_UI_PROPS = { + editable: Boolean, + startEditable: Boolean, + durationEditable: Boolean, + constraint: null, + overlap: null, + allow: null, + className: parseClassName, + classNames: parseClassName, + color: String, + backgroundColor: String, + borderColor: String, + textColor: String + }; + function processUnscopedUiProps(rawProps, calendar, leftovers) { + var props = refineProps(rawProps, UNSCOPED_EVENT_UI_PROPS, {}, leftovers); + var constraint = normalizeConstraint(props.constraint, calendar); + return { + startEditable: props.startEditable != null ? props.startEditable : props.editable, + durationEditable: props.durationEditable != null ? props.durationEditable : props.editable, + constraints: constraint != null ? [constraint] : [], + overlap: props.overlap, + allows: props.allow != null ? [props.allow] : [], + backgroundColor: props.backgroundColor || props.color, + borderColor: props.borderColor || props.color, + textColor: props.textColor, + classNames: props.classNames.concat(props.className) + }; + } + function processScopedUiProps(prefix, rawScoped, calendar, leftovers) { + var rawUnscoped = {}; + var wasFound = {}; + for (var key in UNSCOPED_EVENT_UI_PROPS) { + var scopedKey = prefix + capitaliseFirstLetter(key); + rawUnscoped[key] = rawScoped[scopedKey]; + wasFound[scopedKey] = true; + } + if (prefix === 'event') { + rawUnscoped.editable = rawScoped.editable; // special case. there is no 'eventEditable', just 'editable' + } + if (leftovers) { + for (var key in rawScoped) { + if (!wasFound[key]) { + leftovers[key] = rawScoped[key]; + } + } + } + return processUnscopedUiProps(rawUnscoped, calendar); + } + var EMPTY_EVENT_UI = { + startEditable: null, + durationEditable: null, + constraints: [], + overlap: null, + allows: [], + backgroundColor: '', + borderColor: '', + textColor: '', + classNames: [] + }; + // prevent against problems with <2 args! + function combineEventUis(uis) { + return uis.reduce(combineTwoEventUis, EMPTY_EVENT_UI); + } + function combineTwoEventUis(item0, item1) { + return { + startEditable: item1.startEditable != null ? item1.startEditable : item0.startEditable, + durationEditable: item1.durationEditable != null ? item1.durationEditable : item0.durationEditable, + constraints: item0.constraints.concat(item1.constraints), + overlap: typeof item1.overlap === 'boolean' ? item1.overlap : item0.overlap, + allows: item0.allows.concat(item1.allows), + backgroundColor: item1.backgroundColor || item0.backgroundColor, + borderColor: item1.borderColor || item0.borderColor, + textColor: item1.textColor || item0.textColor, + classNames: item0.classNames.concat(item1.classNames) + }; + } + + var NON_DATE_PROPS = { + id: String, + groupId: String, + title: String, + url: String, + rendering: String, + extendedProps: null + }; + var DATE_PROPS = { + start: null, + date: null, + end: null, + allDay: null + }; + var uid = 0; + function parseEvent(raw, sourceId, calendar, allowOpenRange) { + var allDayDefault = computeIsAllDayDefault(sourceId, calendar); + var leftovers0 = {}; + var recurringRes = parseRecurring(raw, // raw, but with single-event stuff stripped out + allDayDefault, calendar.dateEnv, calendar.pluginSystem.hooks.recurringTypes, leftovers0 // will populate with non-recurring props + ); + if (recurringRes) { + var def = parseEventDef(leftovers0, sourceId, recurringRes.allDay, Boolean(recurringRes.duration), calendar); + def.recurringDef = { + typeId: recurringRes.typeId, + typeData: recurringRes.typeData, + duration: recurringRes.duration + }; + return { def: def, instance: null }; + } + else { + var leftovers1 = {}; + var singleRes = parseSingle(raw, allDayDefault, calendar, leftovers1, allowOpenRange); + if (singleRes) { + var def = parseEventDef(leftovers1, sourceId, singleRes.allDay, singleRes.hasEnd, calendar); + var instance = createEventInstance(def.defId, singleRes.range, singleRes.forcedStartTzo, singleRes.forcedEndTzo); + return { def: def, instance: instance }; + } + } + return null; + } + /* + Will NOT populate extendedProps with the leftover properties. + Will NOT populate date-related props. + The EventNonDateInput has been normalized (id => publicId, etc). + */ + function parseEventDef(raw, sourceId, allDay, hasEnd, calendar) { + var leftovers = {}; + var def = pluckNonDateProps(raw, calendar, leftovers); + def.defId = String(uid++); + def.sourceId = sourceId; + def.allDay = allDay; + def.hasEnd = hasEnd; + for (var _i = 0, _a = calendar.pluginSystem.hooks.eventDefParsers; _i < _a.length; _i++) { + var eventDefParser = _a[_i]; + var newLeftovers = {}; + eventDefParser(def, leftovers, newLeftovers); + leftovers = newLeftovers; + } + def.extendedProps = __assign(leftovers, def.extendedProps || {}); + // help out EventApi from having user modify props + Object.freeze(def.ui.classNames); + Object.freeze(def.extendedProps); + return def; + } + function createEventInstance(defId, range, forcedStartTzo, forcedEndTzo) { + return { + instanceId: String(uid++), + defId: defId, + range: range, + forcedStartTzo: forcedStartTzo == null ? null : forcedStartTzo, + forcedEndTzo: forcedEndTzo == null ? null : forcedEndTzo + }; + } + function parseSingle(raw, allDayDefault, calendar, leftovers, allowOpenRange) { + var props = pluckDateProps(raw, leftovers); + var allDay = props.allDay; + var startMeta; + var startMarker = null; + var hasEnd = false; + var endMeta; + var endMarker = null; + startMeta = calendar.dateEnv.createMarkerMeta(props.start); + if (startMeta) { + startMarker = startMeta.marker; + } + else if (!allowOpenRange) { + return null; + } + if (props.end != null) { + endMeta = calendar.dateEnv.createMarkerMeta(props.end); + } + if (allDay == null) { + if (allDayDefault != null) { + allDay = allDayDefault; + } + else { + // fall back to the date props LAST + allDay = (!startMeta || startMeta.isTimeUnspecified) && + (!endMeta || endMeta.isTimeUnspecified); + } + } + if (allDay && startMarker) { + startMarker = startOfDay(startMarker); + } + if (endMeta) { + endMarker = endMeta.marker; + if (allDay) { + endMarker = startOfDay(endMarker); + } + if (startMarker && endMarker <= startMarker) { + endMarker = null; + } + } + if (endMarker) { + hasEnd = true; + } + else if (!allowOpenRange) { + hasEnd = calendar.opt('forceEventDuration') || false; + endMarker = calendar.dateEnv.add(startMarker, allDay ? + calendar.defaultAllDayEventDuration : + calendar.defaultTimedEventDuration); + } + return { + allDay: allDay, + hasEnd: hasEnd, + range: { start: startMarker, end: endMarker }, + forcedStartTzo: startMeta ? startMeta.forcedTzo : null, + forcedEndTzo: endMeta ? endMeta.forcedTzo : null + }; + } + function pluckDateProps(raw, leftovers) { + var props = refineProps(raw, DATE_PROPS, {}, leftovers); + props.start = (props.start !== null) ? props.start : props.date; + delete props.date; + return props; + } + function pluckNonDateProps(raw, calendar, leftovers) { + var preLeftovers = {}; + var props = refineProps(raw, NON_DATE_PROPS, {}, preLeftovers); + var ui = processUnscopedUiProps(preLeftovers, calendar, leftovers); + props.publicId = props.id; + delete props.id; + props.ui = ui; + return props; + } + function computeIsAllDayDefault(sourceId, calendar) { + var res = null; + if (sourceId) { + var source = calendar.state.eventSources[sourceId]; + res = source.allDayDefault; + } + if (res == null) { + res = calendar.opt('allDayDefault'); + } + return res; + } + + var DEF_DEFAULTS = { + startTime: '09:00', + endTime: '17:00', + daysOfWeek: [1, 2, 3, 4, 5], + rendering: 'inverse-background', + classNames: 'fc-nonbusiness', + groupId: '_businessHours' // so multiple defs get grouped + }; + /* + TODO: pass around as EventDefHash!!! + */ + function parseBusinessHours(input, calendar) { + return parseEvents(refineInputs(input), '', calendar); + } + function refineInputs(input) { + var rawDefs; + if (input === true) { + rawDefs = [{}]; // will get DEF_DEFAULTS verbatim + } + else if (Array.isArray(input)) { + // if specifying an array, every sub-definition NEEDS a day-of-week + rawDefs = input.filter(function (rawDef) { + return rawDef.daysOfWeek; + }); + } + else if (typeof input === 'object' && input) { // non-null object + rawDefs = [input]; + } + else { // is probably false + rawDefs = []; + } + rawDefs = rawDefs.map(function (rawDef) { + return __assign({}, DEF_DEFAULTS, rawDef); + }); + return rawDefs; + } + + function memoizeRendering(renderFunc, unrenderFunc, dependencies) { + if (dependencies === void 0) { dependencies = []; } + var dependents = []; + var thisContext; + var prevArgs; + function unrender() { + if (prevArgs) { + for (var _i = 0, dependents_1 = dependents; _i < dependents_1.length; _i++) { + var dependent = dependents_1[_i]; + dependent.unrender(); + } + if (unrenderFunc) { + unrenderFunc.apply(thisContext, prevArgs); + } + prevArgs = null; + } + } + function res() { + if (!prevArgs || !isArraysEqual(prevArgs, arguments)) { + unrender(); + thisContext = this; + prevArgs = arguments; + renderFunc.apply(this, arguments); + } + } + res.dependents = dependents; + res.unrender = unrender; + for (var _i = 0, dependencies_1 = dependencies; _i < dependencies_1.length; _i++) { + var dependency = dependencies_1[_i]; + dependency.dependents.push(res); + } + return res; + } + + var EMPTY_EVENT_STORE = createEmptyEventStore(); // for purecomponents. TODO: keep elsewhere + var Splitter = /** @class */ (function () { + function Splitter() { + this.getKeysForEventDefs = memoize(this._getKeysForEventDefs); + this.splitDateSelection = memoize(this._splitDateSpan); + this.splitEventStore = memoize(this._splitEventStore); + this.splitIndividualUi = memoize(this._splitIndividualUi); + this.splitEventDrag = memoize(this._splitInteraction); + this.splitEventResize = memoize(this._splitInteraction); + this.eventUiBuilders = {}; // TODO: typescript protection + } + Splitter.prototype.splitProps = function (props) { + var _this = this; + var keyInfos = this.getKeyInfo(props); + var defKeys = this.getKeysForEventDefs(props.eventStore); + var dateSelections = this.splitDateSelection(props.dateSelection); + var individualUi = this.splitIndividualUi(props.eventUiBases, defKeys); // the individual *bases* + var eventStores = this.splitEventStore(props.eventStore, defKeys); + var eventDrags = this.splitEventDrag(props.eventDrag); + var eventResizes = this.splitEventResize(props.eventResize); + var splitProps = {}; + this.eventUiBuilders = mapHash(keyInfos, function (info, key) { + return _this.eventUiBuilders[key] || memoize(buildEventUiForKey); + }); + for (var key in keyInfos) { + var keyInfo = keyInfos[key]; + var eventStore = eventStores[key] || EMPTY_EVENT_STORE; + var buildEventUi = this.eventUiBuilders[key]; + splitProps[key] = { + businessHours: keyInfo.businessHours || props.businessHours, + dateSelection: dateSelections[key] || null, + eventStore: eventStore, + eventUiBases: buildEventUi(props.eventUiBases[''], keyInfo.ui, individualUi[key]), + eventSelection: eventStore.instances[props.eventSelection] ? props.eventSelection : '', + eventDrag: eventDrags[key] || null, + eventResize: eventResizes[key] || null + }; + } + return splitProps; + }; + Splitter.prototype._splitDateSpan = function (dateSpan) { + var dateSpans = {}; + if (dateSpan) { + var keys = this.getKeysForDateSpan(dateSpan); + for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { + var key = keys_1[_i]; + dateSpans[key] = dateSpan; + } + } + return dateSpans; + }; + Splitter.prototype._getKeysForEventDefs = function (eventStore) { + var _this = this; + return mapHash(eventStore.defs, function (eventDef) { + return _this.getKeysForEventDef(eventDef); + }); + }; + Splitter.prototype._splitEventStore = function (eventStore, defKeys) { + var defs = eventStore.defs, instances = eventStore.instances; + var splitStores = {}; + for (var defId in defs) { + for (var _i = 0, _a = defKeys[defId]; _i < _a.length; _i++) { + var key = _a[_i]; + if (!splitStores[key]) { + splitStores[key] = createEmptyEventStore(); + } + splitStores[key].defs[defId] = defs[defId]; + } + } + for (var instanceId in instances) { + var instance = instances[instanceId]; + for (var _b = 0, _c = defKeys[instance.defId]; _b < _c.length; _b++) { + var key = _c[_b]; + if (splitStores[key]) { // must have already been created + splitStores[key].instances[instanceId] = instance; + } + } + } + return splitStores; + }; + Splitter.prototype._splitIndividualUi = function (eventUiBases, defKeys) { + var splitHashes = {}; + for (var defId in eventUiBases) { + if (defId) { // not the '' key + for (var _i = 0, _a = defKeys[defId]; _i < _a.length; _i++) { + var key = _a[_i]; + if (!splitHashes[key]) { + splitHashes[key] = {}; + } + splitHashes[key][defId] = eventUiBases[defId]; + } + } + } + return splitHashes; + }; + Splitter.prototype._splitInteraction = function (interaction) { + var splitStates = {}; + if (interaction) { + var affectedStores_1 = this._splitEventStore(interaction.affectedEvents, this._getKeysForEventDefs(interaction.affectedEvents) // can't use cached. might be events from other calendar + ); + // can't rely on defKeys because event data is mutated + var mutatedKeysByDefId = this._getKeysForEventDefs(interaction.mutatedEvents); + var mutatedStores_1 = this._splitEventStore(interaction.mutatedEvents, mutatedKeysByDefId); + var populate = function (key) { + if (!splitStates[key]) { + splitStates[key] = { + affectedEvents: affectedStores_1[key] || EMPTY_EVENT_STORE, + mutatedEvents: mutatedStores_1[key] || EMPTY_EVENT_STORE, + isEvent: interaction.isEvent, + origSeg: interaction.origSeg + }; + } + }; + for (var key in affectedStores_1) { + populate(key); + } + for (var key in mutatedStores_1) { + populate(key); + } + } + return splitStates; + }; + return Splitter; + }()); + function buildEventUiForKey(allUi, eventUiForKey, individualUi) { + var baseParts = []; + if (allUi) { + baseParts.push(allUi); + } + if (eventUiForKey) { + baseParts.push(eventUiForKey); + } + var stuff = { + '': combineEventUis(baseParts) + }; + if (individualUi) { + __assign(stuff, individualUi); + } + return stuff; + } + + // Generates HTML for an anchor to another view into the calendar. + // Will either generate an <a> tag or a non-clickable <span> tag, depending on enabled settings. + // `gotoOptions` can either be a DateMarker, or an object with the form: + // { date, type, forceOff } + // `type` is a view-type like "day" or "week". default value is "day". + // `attrs` and `innerHtml` are use to generate the rest of the HTML tag. + function buildGotoAnchorHtml(component, gotoOptions, attrs, innerHtml) { + var dateEnv = component.dateEnv; + var date; + var type; + var forceOff; + var finalOptions; + if (gotoOptions instanceof Date) { + date = gotoOptions; // a single date-like input + } + else { + date = gotoOptions.date; + type = gotoOptions.type; + forceOff = gotoOptions.forceOff; + } + finalOptions = { + date: dateEnv.formatIso(date, { omitTime: true }), + type: type || 'day' + }; + if (typeof attrs === 'string') { + innerHtml = attrs; + attrs = null; + } + attrs = attrs ? ' ' + attrsToStr(attrs) : ''; // will have a leading space + innerHtml = innerHtml || ''; + if (!forceOff && component.opt('navLinks')) { + return '<a' + attrs + + ' data-goto="' + htmlEscape(JSON.stringify(finalOptions)) + '">' + + innerHtml + + '</a>'; + } + else { + return '<span' + attrs + '>' + + innerHtml + + '</span>'; + } + } + function getAllDayHtml(component) { + return component.opt('allDayHtml') || htmlEscape(component.opt('allDayText')); + } + // Computes HTML classNames for a single-day element + function getDayClasses(date, dateProfile, context, noThemeHighlight) { + var calendar = context.calendar, view = context.view, theme = context.theme, dateEnv = context.dateEnv; + var classes = []; + var todayStart; + var todayEnd; + if (!rangeContainsMarker(dateProfile.activeRange, date)) { + classes.push('fc-disabled-day'); + } + else { + classes.push('fc-' + DAY_IDS[date.getUTCDay()]); + if (view.opt('monthMode') && + dateEnv.getMonth(date) !== dateEnv.getMonth(dateProfile.currentRange.start)) { + classes.push('fc-other-month'); + } + todayStart = startOfDay(calendar.getNow()); + todayEnd = addDays(todayStart, 1); + if (date < todayStart) { + classes.push('fc-past'); + } + else if (date >= todayEnd) { + classes.push('fc-future'); + } + else { + classes.push('fc-today'); + if (noThemeHighlight !== true) { + classes.push(theme.getClass('today')); + } + } + } + return classes; + } + + // given a function that resolves a result asynchronously. + // the function can either call passed-in success and failure callbacks, + // or it can return a promise. + // if you need to pass additional params to func, bind them first. + function unpromisify(func, success, failure) { + // guard against success/failure callbacks being called more than once + // and guard against a promise AND callback being used together. + var isResolved = false; + var wrappedSuccess = function () { + if (!isResolved) { + isResolved = true; + success.apply(this, arguments); + } + }; + var wrappedFailure = function () { + if (!isResolved) { + isResolved = true; + if (failure) { + failure.apply(this, arguments); + } + } + }; + var res = func(wrappedSuccess, wrappedFailure); + if (res && typeof res.then === 'function') { + res.then(wrappedSuccess, wrappedFailure); + } + } + + var Mixin = /** @class */ (function () { + function Mixin() { + } + // mix into a CLASS + Mixin.mixInto = function (destClass) { + this.mixIntoObj(destClass.prototype); + }; + // mix into ANY object + Mixin.mixIntoObj = function (destObj) { + var _this = this; + Object.getOwnPropertyNames(this.prototype).forEach(function (name) { + if (!destObj[name]) { // if destination doesn't already define it + destObj[name] = _this.prototype[name]; + } + }); + }; + /* + will override existing methods + TODO: remove! not used anymore + */ + Mixin.mixOver = function (destClass) { + var _this = this; + Object.getOwnPropertyNames(this.prototype).forEach(function (name) { + destClass.prototype[name] = _this.prototype[name]; + }); + }; + return Mixin; + }()); + + /* + USAGE: + import { default as EmitterMixin, EmitterInterface } from './EmitterMixin' + in class: + on: EmitterInterface['on'] + one: EmitterInterface['one'] + off: EmitterInterface['off'] + trigger: EmitterInterface['trigger'] + triggerWith: EmitterInterface['triggerWith'] + hasHandlers: EmitterInterface['hasHandlers'] + after class: + EmitterMixin.mixInto(TheClass) + */ + var EmitterMixin = /** @class */ (function (_super) { + __extends(EmitterMixin, _super); + function EmitterMixin() { + return _super !== null && _super.apply(this, arguments) || this; + } + EmitterMixin.prototype.on = function (type, handler) { + addToHash(this._handlers || (this._handlers = {}), type, handler); + return this; // for chaining + }; + // todo: add comments + EmitterMixin.prototype.one = function (type, handler) { + addToHash(this._oneHandlers || (this._oneHandlers = {}), type, handler); + return this; // for chaining + }; + EmitterMixin.prototype.off = function (type, handler) { + if (this._handlers) { + removeFromHash(this._handlers, type, handler); + } + if (this._oneHandlers) { + removeFromHash(this._oneHandlers, type, handler); + } + return this; // for chaining + }; + EmitterMixin.prototype.trigger = function (type) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + this.triggerWith(type, this, args); + return this; // for chaining + }; + EmitterMixin.prototype.triggerWith = function (type, context, args) { + if (this._handlers) { + applyAll(this._handlers[type], context, args); + } + if (this._oneHandlers) { + applyAll(this._oneHandlers[type], context, args); + delete this._oneHandlers[type]; // will never fire again + } + return this; // for chaining + }; + EmitterMixin.prototype.hasHandlers = function (type) { + return (this._handlers && this._handlers[type] && this._handlers[type].length) || + (this._oneHandlers && this._oneHandlers[type] && this._oneHandlers[type].length); + }; + return EmitterMixin; + }(Mixin)); + function addToHash(hash, type, handler) { + (hash[type] || (hash[type] = [])) + .push(handler); + } + function removeFromHash(hash, type, handler) { + if (handler) { + if (hash[type]) { + hash[type] = hash[type].filter(function (func) { + return func !== handler; + }); + } + } + else { + delete hash[type]; // remove all handler funcs for this type + } + } + + /* + Records offset information for a set of elements, relative to an origin element. + Can record the left/right OR the top/bottom OR both. + Provides methods for querying the cache by position. + */ + var PositionCache = /** @class */ (function () { + function PositionCache(originEl, els, isHorizontal, isVertical) { + this.originEl = originEl; + this.els = els; + this.isHorizontal = isHorizontal; + this.isVertical = isVertical; + } + // Queries the els for coordinates and stores them. + // Call this method before using and of the get* methods below. + PositionCache.prototype.build = function () { + var originEl = this.originEl; + var originClientRect = this.originClientRect = + originEl.getBoundingClientRect(); // relative to viewport top-left + if (this.isHorizontal) { + this.buildElHorizontals(originClientRect.left); + } + if (this.isVertical) { + this.buildElVerticals(originClientRect.top); + } + }; + // Populates the left/right internal coordinate arrays + PositionCache.prototype.buildElHorizontals = function (originClientLeft) { + var lefts = []; + var rights = []; + for (var _i = 0, _a = this.els; _i < _a.length; _i++) { + var el = _a[_i]; + var rect = el.getBoundingClientRect(); + lefts.push(rect.left - originClientLeft); + rights.push(rect.right - originClientLeft); + } + this.lefts = lefts; + this.rights = rights; + }; + // Populates the top/bottom internal coordinate arrays + PositionCache.prototype.buildElVerticals = function (originClientTop) { + var tops = []; + var bottoms = []; + for (var _i = 0, _a = this.els; _i < _a.length; _i++) { + var el = _a[_i]; + var rect = el.getBoundingClientRect(); + tops.push(rect.top - originClientTop); + bottoms.push(rect.bottom - originClientTop); + } + this.tops = tops; + this.bottoms = bottoms; + }; + // Given a left offset (from document left), returns the index of the el that it horizontally intersects. + // If no intersection is made, returns undefined. + PositionCache.prototype.leftToIndex = function (leftPosition) { + var lefts = this.lefts; + var rights = this.rights; + var len = lefts.length; + var i; + for (i = 0; i < len; i++) { + if (leftPosition >= lefts[i] && leftPosition < rights[i]) { + return i; + } + } + }; + // Given a top offset (from document top), returns the index of the el that it vertically intersects. + // If no intersection is made, returns undefined. + PositionCache.prototype.topToIndex = function (topPosition) { + var tops = this.tops; + var bottoms = this.bottoms; + var len = tops.length; + var i; + for (i = 0; i < len; i++) { + if (topPosition >= tops[i] && topPosition < bottoms[i]) { + return i; + } + } + }; + // Gets the width of the element at the given index + PositionCache.prototype.getWidth = function (leftIndex) { + return this.rights[leftIndex] - this.lefts[leftIndex]; + }; + // Gets the height of the element at the given index + PositionCache.prototype.getHeight = function (topIndex) { + return this.bottoms[topIndex] - this.tops[topIndex]; + }; + return PositionCache; + }()); + + /* + An object for getting/setting scroll-related information for an element. + Internally, this is done very differently for window versus DOM element, + so this object serves as a common interface. + */ + var ScrollController = /** @class */ (function () { + function ScrollController() { + } + ScrollController.prototype.getMaxScrollTop = function () { + return this.getScrollHeight() - this.getClientHeight(); + }; + ScrollController.prototype.getMaxScrollLeft = function () { + return this.getScrollWidth() - this.getClientWidth(); + }; + ScrollController.prototype.canScrollVertically = function () { + return this.getMaxScrollTop() > 0; + }; + ScrollController.prototype.canScrollHorizontally = function () { + return this.getMaxScrollLeft() > 0; + }; + ScrollController.prototype.canScrollUp = function () { + return this.getScrollTop() > 0; + }; + ScrollController.prototype.canScrollDown = function () { + return this.getScrollTop() < this.getMaxScrollTop(); + }; + ScrollController.prototype.canScrollLeft = function () { + return this.getScrollLeft() > 0; + }; + ScrollController.prototype.canScrollRight = function () { + return this.getScrollLeft() < this.getMaxScrollLeft(); + }; + return ScrollController; + }()); + var ElementScrollController = /** @class */ (function (_super) { + __extends(ElementScrollController, _super); + function ElementScrollController(el) { + var _this = _super.call(this) || this; + _this.el = el; + return _this; + } + ElementScrollController.prototype.getScrollTop = function () { + return this.el.scrollTop; + }; + ElementScrollController.prototype.getScrollLeft = function () { + return this.el.scrollLeft; + }; + ElementScrollController.prototype.setScrollTop = function (top) { + this.el.scrollTop = top; + }; + ElementScrollController.prototype.setScrollLeft = function (left) { + this.el.scrollLeft = left; + }; + ElementScrollController.prototype.getScrollWidth = function () { + return this.el.scrollWidth; + }; + ElementScrollController.prototype.getScrollHeight = function () { + return this.el.scrollHeight; + }; + ElementScrollController.prototype.getClientHeight = function () { + return this.el.clientHeight; + }; + ElementScrollController.prototype.getClientWidth = function () { + return this.el.clientWidth; + }; + return ElementScrollController; + }(ScrollController)); + var WindowScrollController = /** @class */ (function (_super) { + __extends(WindowScrollController, _super); + function WindowScrollController() { + return _super !== null && _super.apply(this, arguments) || this; + } + WindowScrollController.prototype.getScrollTop = function () { + return window.pageYOffset; + }; + WindowScrollController.prototype.getScrollLeft = function () { + return window.pageXOffset; + }; + WindowScrollController.prototype.setScrollTop = function (n) { + window.scroll(window.pageXOffset, n); + }; + WindowScrollController.prototype.setScrollLeft = function (n) { + window.scroll(n, window.pageYOffset); + }; + WindowScrollController.prototype.getScrollWidth = function () { + return document.documentElement.scrollWidth; + }; + WindowScrollController.prototype.getScrollHeight = function () { + return document.documentElement.scrollHeight; + }; + WindowScrollController.prototype.getClientHeight = function () { + return document.documentElement.clientHeight; + }; + WindowScrollController.prototype.getClientWidth = function () { + return document.documentElement.clientWidth; + }; + return WindowScrollController; + }(ScrollController)); + + /* + Embodies a div that has potential scrollbars + */ + var ScrollComponent = /** @class */ (function (_super) { + __extends(ScrollComponent, _super); + function ScrollComponent(overflowX, overflowY) { + var _this = _super.call(this, createElement('div', { + className: 'fc-scroller' + })) || this; + _this.overflowX = overflowX; + _this.overflowY = overflowY; + _this.applyOverflow(); + return _this; + } + // sets to natural height, unlocks overflow + ScrollComponent.prototype.clear = function () { + this.setHeight('auto'); + this.applyOverflow(); + }; + ScrollComponent.prototype.destroy = function () { + removeElement(this.el); + }; + // Overflow + // ----------------------------------------------------------------------------------------------------------------- + ScrollComponent.prototype.applyOverflow = function () { + applyStyle(this.el, { + overflowX: this.overflowX, + overflowY: this.overflowY + }); + }; + // Causes any 'auto' overflow values to resolves to 'scroll' or 'hidden'. + // Useful for preserving scrollbar widths regardless of future resizes. + // Can pass in scrollbarWidths for optimization. + ScrollComponent.prototype.lockOverflow = function (scrollbarWidths) { + var overflowX = this.overflowX; + var overflowY = this.overflowY; + scrollbarWidths = scrollbarWidths || this.getScrollbarWidths(); + if (overflowX === 'auto') { + overflowX = (scrollbarWidths.bottom || // horizontal scrollbars? + this.canScrollHorizontally() // OR scrolling pane with massless scrollbars? + ) ? 'scroll' : 'hidden'; + } + if (overflowY === 'auto') { + overflowY = (scrollbarWidths.left || scrollbarWidths.right || // horizontal scrollbars? + this.canScrollVertically() // OR scrolling pane with massless scrollbars? + ) ? 'scroll' : 'hidden'; + } + applyStyle(this.el, { overflowX: overflowX, overflowY: overflowY }); + }; + ScrollComponent.prototype.setHeight = function (height) { + applyStyleProp(this.el, 'height', height); + }; + ScrollComponent.prototype.getScrollbarWidths = function () { + var edges = computeEdges(this.el); + return { + left: edges.scrollbarLeft, + right: edges.scrollbarRight, + bottom: edges.scrollbarBottom + }; + }; + return ScrollComponent; + }(ElementScrollController)); + + var Theme = /** @class */ (function () { + function Theme(calendarOptions) { + this.calendarOptions = calendarOptions; + this.processIconOverride(); + } + Theme.prototype.processIconOverride = function () { + if (this.iconOverrideOption) { + this.setIconOverride(this.calendarOptions[this.iconOverrideOption]); + } + }; + Theme.prototype.setIconOverride = function (iconOverrideHash) { + var iconClassesCopy; + var buttonName; + if (typeof iconOverrideHash === 'object' && iconOverrideHash) { // non-null object + iconClassesCopy = __assign({}, this.iconClasses); + for (buttonName in iconOverrideHash) { + iconClassesCopy[buttonName] = this.applyIconOverridePrefix(iconOverrideHash[buttonName]); + } + this.iconClasses = iconClassesCopy; + } + else if (iconOverrideHash === false) { + this.iconClasses = {}; + } + }; + Theme.prototype.applyIconOverridePrefix = function (className) { + var prefix = this.iconOverridePrefix; + if (prefix && className.indexOf(prefix) !== 0) { // if not already present + className = prefix + className; + } + return className; + }; + Theme.prototype.getClass = function (key) { + return this.classes[key] || ''; + }; + Theme.prototype.getIconClass = function (buttonName) { + var className = this.iconClasses[buttonName]; + if (className) { + return this.baseIconClass + ' ' + className; + } + return ''; + }; + Theme.prototype.getCustomButtonIconClass = function (customButtonProps) { + var className; + if (this.iconOverrideCustomButtonOption) { + className = customButtonProps[this.iconOverrideCustomButtonOption]; + if (className) { + return this.baseIconClass + ' ' + this.applyIconOverridePrefix(className); + } + } + return ''; + }; + return Theme; + }()); + Theme.prototype.classes = {}; + Theme.prototype.iconClasses = {}; + Theme.prototype.baseIconClass = ''; + Theme.prototype.iconOverridePrefix = ''; + + var guid = 0; + var Component = /** @class */ (function () { + function Component(context, isView) { + // HACK to populate view at top of component instantiation call chain + if (isView) { + context.view = this; + } + this.uid = String(guid++); + this.context = context; + this.dateEnv = context.dateEnv; + this.theme = context.theme; + this.view = context.view; + this.calendar = context.calendar; + this.isRtl = this.opt('dir') === 'rtl'; + } + Component.addEqualityFuncs = function (newFuncs) { + this.prototype.equalityFuncs = __assign({}, this.prototype.equalityFuncs, newFuncs); + }; + Component.prototype.opt = function (name) { + return this.context.options[name]; + }; + Component.prototype.receiveProps = function (props) { + var _a = recycleProps(this.props || {}, props, this.equalityFuncs), anyChanges = _a.anyChanges, comboProps = _a.comboProps; + this.props = comboProps; + if (anyChanges) { + this.render(comboProps); + } + }; + Component.prototype.render = function (props) { + }; + // after destroy is called, this component won't ever be used again + Component.prototype.destroy = function () { + }; + return Component; + }()); + Component.prototype.equalityFuncs = {}; + /* + Reuses old values when equal. If anything is unequal, returns newProps as-is. + Great for PureComponent, but won't be feasible with React, so just eliminate and use React's DOM diffing. + */ + function recycleProps(oldProps, newProps, equalityFuncs) { + var comboProps = {}; // some old, some new + var anyChanges = false; + for (var key in newProps) { + if (key in oldProps && (oldProps[key] === newProps[key] || + (equalityFuncs[key] && equalityFuncs[key](oldProps[key], newProps[key])))) { + // equal to old? use old prop + comboProps[key] = oldProps[key]; + } + else { + comboProps[key] = newProps[key]; + anyChanges = true; + } + } + for (var key in oldProps) { + if (!(key in newProps)) { + anyChanges = true; + break; + } + } + return { anyChanges: anyChanges, comboProps: comboProps }; + } + + /* + PURPOSES: + - hook up to fg, fill, and mirror renderers + - interface for dragging and hits + */ + var DateComponent = /** @class */ (function (_super) { + __extends(DateComponent, _super); + function DateComponent(context, el, isView) { + var _this = _super.call(this, context, isView) || this; + _this.el = el; + return _this; + } + DateComponent.prototype.destroy = function () { + _super.prototype.destroy.call(this); + removeElement(this.el); + }; + // TODO: WHAT ABOUT (sourceSeg && sourceSeg.component.doesDragMirror) + // + // Event Drag-n-Drop Rendering (for both events and external elements) + // --------------------------------------------------------------------------------------------------------------- + /* + renderEventDragSegs(state: EventSegUiInteractionState) { + if (state) { + let { isEvent, segs, sourceSeg } = state + + if (this.eventRenderer) { + this.eventRenderer.hideByHash(state.affectedInstances) + } + + // if the user is dragging something that is considered an event with real event data, + // and this component likes to do drag mirrors OR the component where the seg came from + // likes to do drag mirrors, then render a drag mirror. + if (isEvent && (this.doesDragMirror || sourceSeg && sourceSeg.component.doesDragMirror)) { + if (this.mirrorRenderer) { + this.mirrorRenderer.renderSegs(segs, { isDragging: true, sourceSeg }) + } + } + + // if it would be impossible to render a drag mirror OR this component likes to render + // highlights, then render a highlight. + if (!isEvent || this.doesDragHighlight) { + if (this.fillRenderer) { + this.fillRenderer.renderSegs('highlight', segs) + } + } + } + } + */ + // Hit System + // ----------------------------------------------------------------------------------------------------------------- + DateComponent.prototype.buildPositionCaches = function () { + }; + DateComponent.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) { + return null; // this should be abstract + }; + // Validation + // ----------------------------------------------------------------------------------------------------------------- + DateComponent.prototype.isInteractionValid = function (interaction) { + var calendar = this.calendar; + var dateProfile = this.props.dateProfile; // HACK + var instances = interaction.mutatedEvents.instances; + if (dateProfile) { // HACK for DayTile + for (var instanceId in instances) { + if (!rangeContainsRange(dateProfile.validRange, instances[instanceId].range)) { + return false; + } + } + } + return isInteractionValid(interaction, calendar); + }; + DateComponent.prototype.isDateSelectionValid = function (selection) { + var dateProfile = this.props.dateProfile; // HACK + if (dateProfile && // HACK for DayTile + !rangeContainsRange(dateProfile.validRange, selection.range)) { + return false; + } + return isDateSelectionValid(selection, this.calendar); + }; + // Triggering + // ----------------------------------------------------------------------------------------------------------------- + // TODO: move to Calendar + DateComponent.prototype.publiclyTrigger = function (name, args) { + var calendar = this.calendar; + return calendar.publiclyTrigger(name, args); + }; + DateComponent.prototype.publiclyTriggerAfterSizing = function (name, args) { + var calendar = this.calendar; + return calendar.publiclyTriggerAfterSizing(name, args); + }; + DateComponent.prototype.hasPublicHandlers = function (name) { + var calendar = this.calendar; + return calendar.hasPublicHandlers(name); + }; + DateComponent.prototype.triggerRenderedSegs = function (segs, isMirrors) { + var calendar = this.calendar; + if (this.hasPublicHandlers('eventPositioned')) { + for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { + var seg = segs_1[_i]; + this.publiclyTriggerAfterSizing('eventPositioned', [ + { + event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance), + isMirror: isMirrors, + isStart: seg.isStart, + isEnd: seg.isEnd, + el: seg.el, + view: this // safe to cast because this method is only called on context.view + } + ]); + } + } + if (!calendar.state.loadingLevel) { // avoid initial empty state while pending + calendar.afterSizingTriggers._eventsPositioned = [null]; // fire once + } + }; + DateComponent.prototype.triggerWillRemoveSegs = function (segs, isMirrors) { + var calendar = this.calendar; + for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { + var seg = segs_2[_i]; + calendar.trigger('eventElRemove', seg.el); + } + if (this.hasPublicHandlers('eventDestroy')) { + for (var _a = 0, segs_3 = segs; _a < segs_3.length; _a++) { + var seg = segs_3[_a]; + this.publiclyTrigger('eventDestroy', [ + { + event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance), + isMirror: isMirrors, + el: seg.el, + view: this // safe to cast because this method is only called on context.view + } + ]); + } + } + }; + // Pointer Interaction Utils + // ----------------------------------------------------------------------------------------------------------------- + DateComponent.prototype.isValidSegDownEl = function (el) { + return !this.props.eventDrag && // HACK + !this.props.eventResize && // HACK + !elementClosest(el, '.fc-mirror') && + (this.isPopover() || !this.isInPopover(el)); + // ^above line ensures we don't detect a seg interaction within a nested component. + // it's a HACK because it only supports a popover as the nested component. + }; + DateComponent.prototype.isValidDateDownEl = function (el) { + var segEl = elementClosest(el, this.fgSegSelector); + return (!segEl || segEl.classList.contains('fc-mirror')) && + !elementClosest(el, '.fc-more') && // a "more.." link + !elementClosest(el, 'a[data-goto]') && // a clickable nav link + !this.isInPopover(el); + }; + DateComponent.prototype.isPopover = function () { + return this.el.classList.contains('fc-popover'); + }; + DateComponent.prototype.isInPopover = function (el) { + return Boolean(elementClosest(el, '.fc-popover')); + }; + return DateComponent; + }(Component)); + DateComponent.prototype.fgSegSelector = '.fc-event-container > *'; + DateComponent.prototype.bgSegSelector = '.fc-bgevent:not(.fc-nonbusiness)'; + + var uid$1 = 0; + function createPlugin(input) { + return { + id: String(uid$1++), + deps: input.deps || [], + reducers: input.reducers || [], + eventDefParsers: input.eventDefParsers || [], + isDraggableTransformers: input.isDraggableTransformers || [], + eventDragMutationMassagers: input.eventDragMutationMassagers || [], + eventDefMutationAppliers: input.eventDefMutationAppliers || [], + dateSelectionTransformers: input.dateSelectionTransformers || [], + datePointTransforms: input.datePointTransforms || [], + dateSpanTransforms: input.dateSpanTransforms || [], + views: input.views || {}, + viewPropsTransformers: input.viewPropsTransformers || [], + isPropsValid: input.isPropsValid || null, + externalDefTransforms: input.externalDefTransforms || [], + eventResizeJoinTransforms: input.eventResizeJoinTransforms || [], + viewContainerModifiers: input.viewContainerModifiers || [], + eventDropTransformers: input.eventDropTransformers || [], + componentInteractions: input.componentInteractions || [], + calendarInteractions: input.calendarInteractions || [], + themeClasses: input.themeClasses || {}, + eventSourceDefs: input.eventSourceDefs || [], + cmdFormatter: input.cmdFormatter, + recurringTypes: input.recurringTypes || [], + namedTimeZonedImpl: input.namedTimeZonedImpl, + defaultView: input.defaultView || '', + elementDraggingImpl: input.elementDraggingImpl, + optionChangeHandlers: input.optionChangeHandlers || {} + }; + } + var PluginSystem = /** @class */ (function () { + function PluginSystem() { + this.hooks = { + reducers: [], + eventDefParsers: [], + isDraggableTransformers: [], + eventDragMutationMassagers: [], + eventDefMutationAppliers: [], + dateSelectionTransformers: [], + datePointTransforms: [], + dateSpanTransforms: [], + views: {}, + viewPropsTransformers: [], + isPropsValid: null, + externalDefTransforms: [], + eventResizeJoinTransforms: [], + viewContainerModifiers: [], + eventDropTransformers: [], + componentInteractions: [], + calendarInteractions: [], + themeClasses: {}, + eventSourceDefs: [], + cmdFormatter: null, + recurringTypes: [], + namedTimeZonedImpl: null, + defaultView: '', + elementDraggingImpl: null, + optionChangeHandlers: {} + }; + this.addedHash = {}; + } + PluginSystem.prototype.add = function (plugin) { + if (!this.addedHash[plugin.id]) { + this.addedHash[plugin.id] = true; + for (var _i = 0, _a = plugin.deps; _i < _a.length; _i++) { + var dep = _a[_i]; + this.add(dep); + } + this.hooks = combineHooks(this.hooks, plugin); + } + }; + return PluginSystem; + }()); + function combineHooks(hooks0, hooks1) { + return { + reducers: hooks0.reducers.concat(hooks1.reducers), + eventDefParsers: hooks0.eventDefParsers.concat(hooks1.eventDefParsers), + isDraggableTransformers: hooks0.isDraggableTransformers.concat(hooks1.isDraggableTransformers), + eventDragMutationMassagers: hooks0.eventDragMutationMassagers.concat(hooks1.eventDragMutationMassagers), + eventDefMutationAppliers: hooks0.eventDefMutationAppliers.concat(hooks1.eventDefMutationAppliers), + dateSelectionTransformers: hooks0.dateSelectionTransformers.concat(hooks1.dateSelectionTransformers), + datePointTransforms: hooks0.datePointTransforms.concat(hooks1.datePointTransforms), + dateSpanTransforms: hooks0.dateSpanTransforms.concat(hooks1.dateSpanTransforms), + views: __assign({}, hooks0.views, hooks1.views), + viewPropsTransformers: hooks0.viewPropsTransformers.concat(hooks1.viewPropsTransformers), + isPropsValid: hooks1.isPropsValid || hooks0.isPropsValid, + externalDefTransforms: hooks0.externalDefTransforms.concat(hooks1.externalDefTransforms), + eventResizeJoinTransforms: hooks0.eventResizeJoinTransforms.concat(hooks1.eventResizeJoinTransforms), + viewContainerModifiers: hooks0.viewContainerModifiers.concat(hooks1.viewContainerModifiers), + eventDropTransformers: hooks0.eventDropTransformers.concat(hooks1.eventDropTransformers), + calendarInteractions: hooks0.calendarInteractions.concat(hooks1.calendarInteractions), + componentInteractions: hooks0.componentInteractions.concat(hooks1.componentInteractions), + themeClasses: __assign({}, hooks0.themeClasses, hooks1.themeClasses), + eventSourceDefs: hooks0.eventSourceDefs.concat(hooks1.eventSourceDefs), + cmdFormatter: hooks1.cmdFormatter || hooks0.cmdFormatter, + recurringTypes: hooks0.recurringTypes.concat(hooks1.recurringTypes), + namedTimeZonedImpl: hooks1.namedTimeZonedImpl || hooks0.namedTimeZonedImpl, + defaultView: hooks0.defaultView || hooks1.defaultView, + elementDraggingImpl: hooks0.elementDraggingImpl || hooks1.elementDraggingImpl, + optionChangeHandlers: __assign({}, hooks0.optionChangeHandlers, hooks1.optionChangeHandlers) + }; + } + + var eventSourceDef = { + ignoreRange: true, + parseMeta: function (raw) { + if (Array.isArray(raw)) { // short form + return raw; + } + else if (Array.isArray(raw.events)) { + return raw.events; + } + return null; + }, + fetch: function (arg, success) { + success({ + rawEvents: arg.eventSource.meta + }); + } + }; + var ArrayEventSourcePlugin = createPlugin({ + eventSourceDefs: [eventSourceDef] + }); + + var eventSourceDef$1 = { + parseMeta: function (raw) { + if (typeof raw === 'function') { // short form + return raw; + } + else if (typeof raw.events === 'function') { + return raw.events; + } + return null; + }, + fetch: function (arg, success, failure) { + var dateEnv = arg.calendar.dateEnv; + var func = arg.eventSource.meta; + unpromisify(func.bind(null, { + start: dateEnv.toDate(arg.range.start), + end: dateEnv.toDate(arg.range.end), + startStr: dateEnv.formatIso(arg.range.start), + endStr: dateEnv.formatIso(arg.range.end), + timeZone: dateEnv.timeZone + }), function (rawEvents) { + success({ rawEvents: rawEvents }); // needs an object response + }, failure // send errorObj directly to failure callback + ); + } + }; + var FuncEventSourcePlugin = createPlugin({ + eventSourceDefs: [eventSourceDef$1] + }); + + function requestJson(method, url, params, successCallback, failureCallback) { + method = method.toUpperCase(); + var body = null; + if (method === 'GET') { + url = injectQueryStringParams(url, params); + } + else { + body = encodeParams(params); + } + var xhr = new XMLHttpRequest(); + xhr.open(method, url, true); + if (method !== 'GET') { + xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + } + xhr.onload = function () { + if (xhr.status >= 200 && xhr.status < 400) { + try { + var res = JSON.parse(xhr.responseText); + successCallback(res, xhr); + } + catch (err) { + failureCallback('Failure parsing JSON', xhr); + } + } + else { + failureCallback('Request failed', xhr); + } + }; + xhr.onerror = function () { + failureCallback('Request failed', xhr); + }; + xhr.send(body); + } + function injectQueryStringParams(url, params) { + return url + + (url.indexOf('?') === -1 ? '?' : '&') + + encodeParams(params); + } + function encodeParams(params) { + var parts = []; + for (var key in params) { + parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(params[key])); + } + return parts.join('&'); + } + + var eventSourceDef$2 = { + parseMeta: function (raw) { + if (typeof raw === 'string') { // short form + raw = { url: raw }; + } + else if (!raw || typeof raw !== 'object' || !raw.url) { + return null; + } + return { + url: raw.url, + method: (raw.method || 'GET').toUpperCase(), + extraParams: raw.extraParams, + startParam: raw.startParam, + endParam: raw.endParam, + timeZoneParam: raw.timeZoneParam + }; + }, + fetch: function (arg, success, failure) { + var meta = arg.eventSource.meta; + var requestParams = buildRequestParams(meta, arg.range, arg.calendar); + requestJson(meta.method, meta.url, requestParams, function (rawEvents, xhr) { + success({ rawEvents: rawEvents, xhr: xhr }); + }, function (errorMessage, xhr) { + failure({ message: errorMessage, xhr: xhr }); + }); + } + }; + var JsonFeedEventSourcePlugin = createPlugin({ + eventSourceDefs: [eventSourceDef$2] + }); + function buildRequestParams(meta, range, calendar) { + var dateEnv = calendar.dateEnv; + var startParam; + var endParam; + var timeZoneParam; + var customRequestParams; + var params = {}; + startParam = meta.startParam; + if (startParam == null) { + startParam = calendar.opt('startParam'); + } + endParam = meta.endParam; + if (endParam == null) { + endParam = calendar.opt('endParam'); + } + timeZoneParam = meta.timeZoneParam; + if (timeZoneParam == null) { + timeZoneParam = calendar.opt('timeZoneParam'); + } + // retrieve any outbound GET/POST data from the options + if (typeof meta.extraParams === 'function') { + // supplied as a function that returns a key/value object + customRequestParams = meta.extraParams(); + } + else { + // probably supplied as a straight key/value object + customRequestParams = meta.extraParams || {}; + } + __assign(params, customRequestParams); + params[startParam] = dateEnv.formatIso(range.start); + params[endParam] = dateEnv.formatIso(range.end); + if (dateEnv.timeZone !== 'local') { + params[timeZoneParam] = dateEnv.timeZone; + } + return params; + } + + var recurring = { + parse: function (rawEvent, leftoverProps, dateEnv) { + var createMarker = dateEnv.createMarker.bind(dateEnv); + var processors = { + daysOfWeek: null, + startTime: createDuration, + endTime: createDuration, + startRecur: createMarker, + endRecur: createMarker + }; + var props = refineProps(rawEvent, processors, {}, leftoverProps); + var anyValid = false; + for (var propName in props) { + if (props[propName] != null) { + anyValid = true; + break; + } + } + if (anyValid) { + var duration = null; + if ('duration' in leftoverProps) { + duration = createDuration(leftoverProps.duration); + delete leftoverProps.duration; + } + if (!duration && props.startTime && props.endTime) { + duration = subtractDurations(props.endTime, props.startTime); + } + return { + allDayGuess: Boolean(!props.startTime && !props.endTime), + duration: duration, + typeData: props // doesn't need endTime anymore but oh well + }; + } + return null; + }, + expand: function (typeData, framingRange, dateEnv) { + var clippedFramingRange = intersectRanges(framingRange, { start: typeData.startRecur, end: typeData.endRecur }); + if (clippedFramingRange) { + return expandRanges(typeData.daysOfWeek, typeData.startTime, clippedFramingRange, dateEnv); + } + else { + return []; + } + } + }; + var SimpleRecurrencePlugin = createPlugin({ + recurringTypes: [recurring] + }); + function expandRanges(daysOfWeek, startTime, framingRange, dateEnv) { + var dowHash = daysOfWeek ? arrayToHash(daysOfWeek) : null; + var dayMarker = startOfDay(framingRange.start); + var endMarker = framingRange.end; + var instanceStarts = []; + while (dayMarker < endMarker) { + var instanceStart + // if everyday, or this particular day-of-week + = void 0; + // if everyday, or this particular day-of-week + if (!dowHash || dowHash[dayMarker.getUTCDay()]) { + if (startTime) { + instanceStart = dateEnv.add(dayMarker, startTime); + } + else { + instanceStart = dayMarker; + } + instanceStarts.push(instanceStart); + } + dayMarker = addDays(dayMarker, 1); + } + return instanceStarts; + } + + var DefaultOptionChangeHandlers = createPlugin({ + optionChangeHandlers: { + events: function (events, calendar, deepEqual) { + handleEventSources([events], calendar, deepEqual); + }, + eventSources: handleEventSources, + plugins: handlePlugins + } + }); + function handleEventSources(inputs, calendar, deepEqual) { + var unfoundSources = hashValuesToArray(calendar.state.eventSources); + var newInputs = []; + for (var _i = 0, inputs_1 = inputs; _i < inputs_1.length; _i++) { + var input = inputs_1[_i]; + var inputFound = false; + for (var i = 0; i < unfoundSources.length; i++) { + if (deepEqual(unfoundSources[i]._raw, input)) { + unfoundSources.splice(i, 1); // delete + inputFound = true; + break; + } + } + if (!inputFound) { + newInputs.push(input); + } + } + for (var _a = 0, unfoundSources_1 = unfoundSources; _a < unfoundSources_1.length; _a++) { + var unfoundSource = unfoundSources_1[_a]; + calendar.dispatch({ + type: 'REMOVE_EVENT_SOURCE', + sourceId: unfoundSource.sourceId + }); + } + for (var _b = 0, newInputs_1 = newInputs; _b < newInputs_1.length; _b++) { + var newInput = newInputs_1[_b]; + calendar.addEventSource(newInput); + } + } + // shortcoming: won't remove plugins + function handlePlugins(inputs, calendar) { + calendar.addPluginInputs(inputs); // will gracefully handle duplicates + } + + var config = {}; // TODO: make these options + var globalDefaults = { + defaultRangeSeparator: ' - ', + titleRangeSeparator: ' \u2013 ', + defaultTimedEventDuration: '01:00:00', + defaultAllDayEventDuration: { day: 1 }, + forceEventDuration: false, + nextDayThreshold: '00:00:00', + // display + columnHeader: true, + defaultView: '', + aspectRatio: 1.35, + header: { + left: 'title', + center: '', + right: 'today prev,next' + }, + weekends: true, + weekNumbers: false, + weekNumberCalculation: 'local', + editable: false, + // nowIndicator: false, + scrollTime: '06:00:00', + minTime: '00:00:00', + maxTime: '24:00:00', + showNonCurrentDates: true, + // event ajax + lazyFetching: true, + startParam: 'start', + endParam: 'end', + timeZoneParam: 'timeZone', + timeZone: 'local', + // allDayDefault: undefined, + // locale + locales: [], + locale: '', + // dir: will get this from the default locale + // buttonIcons: null, + // allows setting a min-height to the event segment to prevent short events overlapping each other + timeGridEventMinHeight: 0, + themeSystem: 'standard', + // eventResizableFromStart: false, + dragRevertDuration: 500, + dragScroll: true, + allDayMaintainDuration: false, + // selectable: false, + unselectAuto: true, + // selectMinDistance: 0, + dropAccept: '*', + eventOrder: 'start,-duration,allDay,title', + // ^ if start tie, longer events go before shorter. final tie-breaker is title text + // rerenderDelay: null, + eventLimit: false, + eventLimitClick: 'popover', + dayPopoverFormat: { month: 'long', day: 'numeric', year: 'numeric' }, + handleWindowResize: true, + windowResizeDelay: 100, + longPressDelay: 1000, + eventDragMinDistance: 5 // only applies to mouse + }; + var rtlDefaults = { + header: { + left: 'next,prev today', + center: '', + right: 'title' + }, + buttonIcons: { + // TODO: make RTL support the responibility of the theme + prev: 'fc-icon-chevron-right', + next: 'fc-icon-chevron-left', + prevYear: 'fc-icon-chevrons-right', + nextYear: 'fc-icon-chevrons-left' + } + }; + var complexOptions = [ + 'header', + 'footer', + 'buttonText', + 'buttonIcons' + ]; + // Merges an array of option objects into a single object + function mergeOptions(optionObjs) { + return mergeProps(optionObjs, complexOptions); + } + // TODO: move this stuff to a "plugin"-related file... + var INTERNAL_PLUGINS = [ + ArrayEventSourcePlugin, + FuncEventSourcePlugin, + JsonFeedEventSourcePlugin, + SimpleRecurrencePlugin, + DefaultOptionChangeHandlers + ]; + function refinePluginDefs(pluginInputs) { + var plugins = []; + for (var _i = 0, pluginInputs_1 = pluginInputs; _i < pluginInputs_1.length; _i++) { + var pluginInput = pluginInputs_1[_i]; + if (typeof pluginInput === 'string') { + var globalName = 'FullCalendar' + capitaliseFirstLetter(pluginInput); + if (!window[globalName]) { + console.warn('Plugin file not loaded for ' + pluginInput); + } + else { + plugins.push(window[globalName].default); // is an ES6 module + } + } + else { + plugins.push(pluginInput); + } + } + return INTERNAL_PLUGINS.concat(plugins); + } + + var RAW_EN_LOCALE = { + code: 'en', + week: { + dow: 0, + doy: 4 // 4 days need to be within the year to be considered the first week + }, + dir: 'ltr', + buttonText: { + prev: 'prev', + next: 'next', + prevYear: 'prev year', + nextYear: 'next year', + year: 'year', + today: 'today', + month: 'month', + week: 'week', + day: 'day', + list: 'list' + }, + weekLabel: 'W', + allDayText: 'all-day', + eventLimitText: 'more', + noEventsMessage: 'No events to display' + }; + function parseRawLocales(explicitRawLocales) { + var defaultCode = explicitRawLocales.length > 0 ? explicitRawLocales[0].code : 'en'; + var globalArray = window['FullCalendarLocalesAll'] || []; // from locales-all.js + var globalObject = window['FullCalendarLocales'] || {}; // from locales/*.js. keys are meaningless + var allRawLocales = globalArray.concat(// globalArray is low prio + hashValuesToArray(globalObject), // medium prio + explicitRawLocales // highest prio + ); + var rawLocaleMap = { + en: RAW_EN_LOCALE // necessary? + }; + for (var _i = 0, allRawLocales_1 = allRawLocales; _i < allRawLocales_1.length; _i++) { + var rawLocale = allRawLocales_1[_i]; + rawLocaleMap[rawLocale.code] = rawLocale; + } + return { + map: rawLocaleMap, + defaultCode: defaultCode + }; + } + function buildLocale(inputSingular, available) { + if (typeof inputSingular === 'object' && !Array.isArray(inputSingular)) { + return parseLocale(inputSingular.code, [inputSingular.code], inputSingular); + } + else { + return queryLocale(inputSingular, available); + } + } + function queryLocale(codeArg, available) { + var codes = [].concat(codeArg || []); // will convert to array + var raw = queryRawLocale(codes, available) || RAW_EN_LOCALE; + return parseLocale(codeArg, codes, raw); + } + function queryRawLocale(codes, available) { + for (var i = 0; i < codes.length; i++) { + var parts = codes[i].toLocaleLowerCase().split('-'); + for (var j = parts.length; j > 0; j--) { + var simpleId = parts.slice(0, j).join('-'); + if (available[simpleId]) { + return available[simpleId]; + } + } + } + return null; + } + function parseLocale(codeArg, codes, raw) { + var merged = mergeProps([RAW_EN_LOCALE, raw], ['buttonText']); + delete merged.code; // don't want this part of the options + var week = merged.week; + delete merged.week; + return { + codeArg: codeArg, + codes: codes, + week: week, + simpleNumberFormat: new Intl.NumberFormat(codeArg), + options: merged + }; + } + + var OptionsManager = /** @class */ (function () { + function OptionsManager(overrides) { + this.overrides = __assign({}, overrides); // make a copy + this.dynamicOverrides = {}; + this.compute(); + } + OptionsManager.prototype.mutate = function (updates, removals, isDynamic) { + var overrideHash = isDynamic ? this.dynamicOverrides : this.overrides; + __assign(overrideHash, updates); + for (var _i = 0, removals_1 = removals; _i < removals_1.length; _i++) { + var propName = removals_1[_i]; + delete overrideHash[propName]; + } + this.compute(); + }; + // Computes the flattened options hash for the calendar and assigns to `this.options`. + // Assumes this.overrides and this.dynamicOverrides have already been initialized. + OptionsManager.prototype.compute = function () { + // TODO: not a very efficient system + var locales = firstDefined(// explicit locale option given? + this.dynamicOverrides.locales, this.overrides.locales, globalDefaults.locales); + var locale = firstDefined(// explicit locales option given? + this.dynamicOverrides.locale, this.overrides.locale, globalDefaults.locale); + var available = parseRawLocales(locales); + var localeDefaults = buildLocale(locale || available.defaultCode, available.map).options; + var dir = firstDefined(// based on options computed so far, is direction RTL? + this.dynamicOverrides.dir, this.overrides.dir, localeDefaults.dir); + var dirDefaults = dir === 'rtl' ? rtlDefaults : {}; + this.dirDefaults = dirDefaults; + this.localeDefaults = localeDefaults; + this.computed = mergeOptions([ + globalDefaults, + dirDefaults, + localeDefaults, + this.overrides, + this.dynamicOverrides + ]); + }; + return OptionsManager; + }()); + + var calendarSystemClassMap = {}; + function registerCalendarSystem(name, theClass) { + calendarSystemClassMap[name] = theClass; + } + function createCalendarSystem(name) { + return new calendarSystemClassMap[name](); + } + var GregorianCalendarSystem = /** @class */ (function () { + function GregorianCalendarSystem() { + } + GregorianCalendarSystem.prototype.getMarkerYear = function (d) { + return d.getUTCFullYear(); + }; + GregorianCalendarSystem.prototype.getMarkerMonth = function (d) { + return d.getUTCMonth(); + }; + GregorianCalendarSystem.prototype.getMarkerDay = function (d) { + return d.getUTCDate(); + }; + GregorianCalendarSystem.prototype.arrayToMarker = function (arr) { + return arrayToUtcDate(arr); + }; + GregorianCalendarSystem.prototype.markerToArray = function (marker) { + return dateToUtcArray(marker); + }; + return GregorianCalendarSystem; + }()); + registerCalendarSystem('gregory', GregorianCalendarSystem); + + var ISO_RE = /^\s*(\d{4})(-(\d{2})(-(\d{2})([T ](\d{2}):(\d{2})(:(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/; + function parse(str) { + var m = ISO_RE.exec(str); + if (m) { + var marker = new Date(Date.UTC(Number(m[1]), m[3] ? Number(m[3]) - 1 : 0, Number(m[5] || 1), Number(m[7] || 0), Number(m[8] || 0), Number(m[10] || 0), m[12] ? Number('0.' + m[12]) * 1000 : 0)); + if (isValidDate(marker)) { + var timeZoneOffset = null; + if (m[13]) { + timeZoneOffset = (m[15] === '-' ? -1 : 1) * (Number(m[16] || 0) * 60 + + Number(m[18] || 0)); + } + return { + marker: marker, + isTimeUnspecified: !m[6], + timeZoneOffset: timeZoneOffset + }; + } + } + return null; + } + + var DateEnv = /** @class */ (function () { + function DateEnv(settings) { + var timeZone = this.timeZone = settings.timeZone; + var isNamedTimeZone = timeZone !== 'local' && timeZone !== 'UTC'; + if (settings.namedTimeZoneImpl && isNamedTimeZone) { + this.namedTimeZoneImpl = new settings.namedTimeZoneImpl(timeZone); + } + this.canComputeOffset = Boolean(!isNamedTimeZone || this.namedTimeZoneImpl); + this.calendarSystem = createCalendarSystem(settings.calendarSystem); + this.locale = settings.locale; + this.weekDow = settings.locale.week.dow; + this.weekDoy = settings.locale.week.doy; + if (settings.weekNumberCalculation === 'ISO') { + this.weekDow = 1; + this.weekDoy = 4; + } + if (typeof settings.firstDay === 'number') { + this.weekDow = settings.firstDay; + } + if (typeof settings.weekNumberCalculation === 'function') { + this.weekNumberFunc = settings.weekNumberCalculation; + } + this.weekLabel = settings.weekLabel != null ? settings.weekLabel : settings.locale.options.weekLabel; + this.cmdFormatter = settings.cmdFormatter; + } + // Creating / Parsing + DateEnv.prototype.createMarker = function (input) { + var meta = this.createMarkerMeta(input); + if (meta === null) { + return null; + } + return meta.marker; + }; + DateEnv.prototype.createNowMarker = function () { + if (this.canComputeOffset) { + return this.timestampToMarker(new Date().valueOf()); + } + else { + // if we can't compute the current date val for a timezone, + // better to give the current local date vals than UTC + return arrayToUtcDate(dateToLocalArray(new Date())); + } + }; + DateEnv.prototype.createMarkerMeta = function (input) { + if (typeof input === 'string') { + return this.parse(input); + } + var marker = null; + if (typeof input === 'number') { + marker = this.timestampToMarker(input); + } + else if (input instanceof Date) { + input = input.valueOf(); + if (!isNaN(input)) { + marker = this.timestampToMarker(input); + } + } + else if (Array.isArray(input)) { + marker = arrayToUtcDate(input); + } + if (marker === null || !isValidDate(marker)) { + return null; + } + return { marker: marker, isTimeUnspecified: false, forcedTzo: null }; + }; + DateEnv.prototype.parse = function (s) { + var parts = parse(s); + if (parts === null) { + return null; + } + var marker = parts.marker; + var forcedTzo = null; + if (parts.timeZoneOffset !== null) { + if (this.canComputeOffset) { + marker = this.timestampToMarker(marker.valueOf() - parts.timeZoneOffset * 60 * 1000); + } + else { + forcedTzo = parts.timeZoneOffset; + } + } + return { marker: marker, isTimeUnspecified: parts.isTimeUnspecified, forcedTzo: forcedTzo }; + }; + // Accessors + DateEnv.prototype.getYear = function (marker) { + return this.calendarSystem.getMarkerYear(marker); + }; + DateEnv.prototype.getMonth = function (marker) { + return this.calendarSystem.getMarkerMonth(marker); + }; + // Adding / Subtracting + DateEnv.prototype.add = function (marker, dur) { + var a = this.calendarSystem.markerToArray(marker); + a[0] += dur.years; + a[1] += dur.months; + a[2] += dur.days; + a[6] += dur.milliseconds; + return this.calendarSystem.arrayToMarker(a); + }; + DateEnv.prototype.subtract = function (marker, dur) { + var a = this.calendarSystem.markerToArray(marker); + a[0] -= dur.years; + a[1] -= dur.months; + a[2] -= dur.days; + a[6] -= dur.milliseconds; + return this.calendarSystem.arrayToMarker(a); + }; + DateEnv.prototype.addYears = function (marker, n) { + var a = this.calendarSystem.markerToArray(marker); + a[0] += n; + return this.calendarSystem.arrayToMarker(a); + }; + DateEnv.prototype.addMonths = function (marker, n) { + var a = this.calendarSystem.markerToArray(marker); + a[1] += n; + return this.calendarSystem.arrayToMarker(a); + }; + // Diffing Whole Units + DateEnv.prototype.diffWholeYears = function (m0, m1) { + var calendarSystem = this.calendarSystem; + if (timeAsMs(m0) === timeAsMs(m1) && + calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1) && + calendarSystem.getMarkerMonth(m0) === calendarSystem.getMarkerMonth(m1)) { + return calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0); + } + return null; + }; + DateEnv.prototype.diffWholeMonths = function (m0, m1) { + var calendarSystem = this.calendarSystem; + if (timeAsMs(m0) === timeAsMs(m1) && + calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1)) { + return (calendarSystem.getMarkerMonth(m1) - calendarSystem.getMarkerMonth(m0)) + + (calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0)) * 12; + } + return null; + }; + // Range / Duration + DateEnv.prototype.greatestWholeUnit = function (m0, m1) { + var n = this.diffWholeYears(m0, m1); + if (n !== null) { + return { unit: 'year', value: n }; + } + n = this.diffWholeMonths(m0, m1); + if (n !== null) { + return { unit: 'month', value: n }; + } + n = diffWholeWeeks(m0, m1); + if (n !== null) { + return { unit: 'week', value: n }; + } + n = diffWholeDays(m0, m1); + if (n !== null) { + return { unit: 'day', value: n }; + } + n = diffHours(m0, m1); + if (isInt(n)) { + return { unit: 'hour', value: n }; + } + n = diffMinutes(m0, m1); + if (isInt(n)) { + return { unit: 'minute', value: n }; + } + n = diffSeconds(m0, m1); + if (isInt(n)) { + return { unit: 'second', value: n }; + } + return { unit: 'millisecond', value: m1.valueOf() - m0.valueOf() }; + }; + DateEnv.prototype.countDurationsBetween = function (m0, m1, d) { + // TODO: can use greatestWholeUnit + var diff; + if (d.years) { + diff = this.diffWholeYears(m0, m1); + if (diff !== null) { + return diff / asRoughYears(d); + } + } + if (d.months) { + diff = this.diffWholeMonths(m0, m1); + if (diff !== null) { + return diff / asRoughMonths(d); + } + } + if (d.days) { + diff = diffWholeDays(m0, m1); + if (diff !== null) { + return diff / asRoughDays(d); + } + } + return (m1.valueOf() - m0.valueOf()) / asRoughMs(d); + }; + // Start-Of + DateEnv.prototype.startOf = function (m, unit) { + if (unit === 'year') { + return this.startOfYear(m); + } + else if (unit === 'month') { + return this.startOfMonth(m); + } + else if (unit === 'week') { + return this.startOfWeek(m); + } + else if (unit === 'day') { + return startOfDay(m); + } + else if (unit === 'hour') { + return startOfHour(m); + } + else if (unit === 'minute') { + return startOfMinute(m); + } + else if (unit === 'second') { + return startOfSecond(m); + } + }; + DateEnv.prototype.startOfYear = function (m) { + return this.calendarSystem.arrayToMarker([ + this.calendarSystem.getMarkerYear(m) + ]); + }; + DateEnv.prototype.startOfMonth = function (m) { + return this.calendarSystem.arrayToMarker([ + this.calendarSystem.getMarkerYear(m), + this.calendarSystem.getMarkerMonth(m) + ]); + }; + DateEnv.prototype.startOfWeek = function (m) { + return this.calendarSystem.arrayToMarker([ + this.calendarSystem.getMarkerYear(m), + this.calendarSystem.getMarkerMonth(m), + m.getUTCDate() - ((m.getUTCDay() - this.weekDow + 7) % 7) + ]); + }; + // Week Number + DateEnv.prototype.computeWeekNumber = function (marker) { + if (this.weekNumberFunc) { + return this.weekNumberFunc(this.toDate(marker)); + } + else { + return weekOfYear(marker, this.weekDow, this.weekDoy); + } + }; + // TODO: choke on timeZoneName: long + DateEnv.prototype.format = function (marker, formatter, dateOptions) { + if (dateOptions === void 0) { dateOptions = {}; } + return formatter.format({ + marker: marker, + timeZoneOffset: dateOptions.forcedTzo != null ? + dateOptions.forcedTzo : + this.offsetForMarker(marker) + }, this); + }; + DateEnv.prototype.formatRange = function (start, end, formatter, dateOptions) { + if (dateOptions === void 0) { dateOptions = {}; } + if (dateOptions.isEndExclusive) { + end = addMs(end, -1); + } + return formatter.formatRange({ + marker: start, + timeZoneOffset: dateOptions.forcedStartTzo != null ? + dateOptions.forcedStartTzo : + this.offsetForMarker(start) + }, { + marker: end, + timeZoneOffset: dateOptions.forcedEndTzo != null ? + dateOptions.forcedEndTzo : + this.offsetForMarker(end) + }, this); + }; + DateEnv.prototype.formatIso = function (marker, extraOptions) { + if (extraOptions === void 0) { extraOptions = {}; } + var timeZoneOffset = null; + if (!extraOptions.omitTimeZoneOffset) { + if (extraOptions.forcedTzo != null) { + timeZoneOffset = extraOptions.forcedTzo; + } + else { + timeZoneOffset = this.offsetForMarker(marker); + } + } + return buildIsoString(marker, timeZoneOffset, extraOptions.omitTime); + }; + // TimeZone + DateEnv.prototype.timestampToMarker = function (ms) { + if (this.timeZone === 'local') { + return arrayToUtcDate(dateToLocalArray(new Date(ms))); + } + else if (this.timeZone === 'UTC' || !this.namedTimeZoneImpl) { + return new Date(ms); + } + else { + return arrayToUtcDate(this.namedTimeZoneImpl.timestampToArray(ms)); + } + }; + DateEnv.prototype.offsetForMarker = function (m) { + if (this.timeZone === 'local') { + return -arrayToLocalDate(dateToUtcArray(m)).getTimezoneOffset(); // convert "inverse" offset to "normal" offset + } + else if (this.timeZone === 'UTC') { + return 0; + } + else if (this.namedTimeZoneImpl) { + return this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)); + } + return null; + }; + // Conversion + DateEnv.prototype.toDate = function (m, forcedTzo) { + if (this.timeZone === 'local') { + return arrayToLocalDate(dateToUtcArray(m)); + } + else if (this.timeZone === 'UTC') { + return new Date(m.valueOf()); // make sure it's a copy + } + else if (!this.namedTimeZoneImpl) { + return new Date(m.valueOf() - (forcedTzo || 0)); + } + else { + return new Date(m.valueOf() - + this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)) * 1000 * 60 // convert minutes -> ms + ); + } + }; + return DateEnv; + }()); + + var SIMPLE_SOURCE_PROPS = { + id: String, + allDayDefault: Boolean, + eventDataTransform: Function, + success: Function, + failure: Function + }; + var uid$2 = 0; + function doesSourceNeedRange(eventSource, calendar) { + var defs = calendar.pluginSystem.hooks.eventSourceDefs; + return !defs[eventSource.sourceDefId].ignoreRange; + } + function parseEventSource(raw, calendar) { + var defs = calendar.pluginSystem.hooks.eventSourceDefs; + for (var i = defs.length - 1; i >= 0; i--) { // later-added plugins take precedence + var def = defs[i]; + var meta = def.parseMeta(raw); + if (meta) { + var res = parseEventSourceProps(typeof raw === 'object' ? raw : {}, meta, i, calendar); + res._raw = raw; + return res; + } + } + return null; + } + function parseEventSourceProps(raw, meta, sourceDefId, calendar) { + var leftovers0 = {}; + var props = refineProps(raw, SIMPLE_SOURCE_PROPS, {}, leftovers0); + var leftovers1 = {}; + var ui = processUnscopedUiProps(leftovers0, calendar, leftovers1); + props.isFetching = false; + props.latestFetchId = ''; + props.fetchRange = null; + props.publicId = String(raw.id || ''); + props.sourceId = String(uid$2++); + props.sourceDefId = sourceDefId; + props.meta = meta; + props.ui = ui; + props.extendedProps = leftovers1; + return props; + } + + function reduceEventSources (eventSources, action, dateProfile, calendar) { + switch (action.type) { + case 'ADD_EVENT_SOURCES': // already parsed + return addSources(eventSources, action.sources, dateProfile ? dateProfile.activeRange : null, calendar); + case 'REMOVE_EVENT_SOURCE': + return removeSource(eventSources, action.sourceId); + case 'PREV': // TODO: how do we track all actions that affect dateProfile :( + case 'NEXT': + case 'SET_DATE': + case 'SET_VIEW_TYPE': + if (dateProfile) { + return fetchDirtySources(eventSources, dateProfile.activeRange, calendar); + } + else { + return eventSources; + } + case 'FETCH_EVENT_SOURCES': + case 'CHANGE_TIMEZONE': + return fetchSourcesByIds(eventSources, action.sourceIds ? + arrayToHash(action.sourceIds) : + excludeStaticSources(eventSources, calendar), dateProfile ? dateProfile.activeRange : null, calendar); + case 'RECEIVE_EVENTS': + case 'RECEIVE_EVENT_ERROR': + return receiveResponse(eventSources, action.sourceId, action.fetchId, action.fetchRange); + case 'REMOVE_ALL_EVENT_SOURCES': + return {}; + default: + return eventSources; + } + } + var uid$3 = 0; + function addSources(eventSourceHash, sources, fetchRange, calendar) { + var hash = {}; + for (var _i = 0, sources_1 = sources; _i < sources_1.length; _i++) { + var source = sources_1[_i]; + hash[source.sourceId] = source; + } + if (fetchRange) { + hash = fetchDirtySources(hash, fetchRange, calendar); + } + return __assign({}, eventSourceHash, hash); + } + function removeSource(eventSourceHash, sourceId) { + return filterHash(eventSourceHash, function (eventSource) { + return eventSource.sourceId !== sourceId; + }); + } + function fetchDirtySources(sourceHash, fetchRange, calendar) { + return fetchSourcesByIds(sourceHash, filterHash(sourceHash, function (eventSource) { + return isSourceDirty(eventSource, fetchRange, calendar); + }), fetchRange, calendar); + } + function isSourceDirty(eventSource, fetchRange, calendar) { + if (!doesSourceNeedRange(eventSource, calendar)) { + return !eventSource.latestFetchId; + } + else { + return !calendar.opt('lazyFetching') || + !eventSource.fetchRange || + fetchRange.start < eventSource.fetchRange.start || + fetchRange.end > eventSource.fetchRange.end; + } + } + function fetchSourcesByIds(prevSources, sourceIdHash, fetchRange, calendar) { + var nextSources = {}; + for (var sourceId in prevSources) { + var source = prevSources[sourceId]; + if (sourceIdHash[sourceId]) { + nextSources[sourceId] = fetchSource(source, fetchRange, calendar); + } + else { + nextSources[sourceId] = source; + } + } + return nextSources; + } + function fetchSource(eventSource, fetchRange, calendar) { + var sourceDef = calendar.pluginSystem.hooks.eventSourceDefs[eventSource.sourceDefId]; + var fetchId = String(uid$3++); + sourceDef.fetch({ + eventSource: eventSource, + calendar: calendar, + range: fetchRange + }, function (res) { + var rawEvents = res.rawEvents; + var calSuccess = calendar.opt('eventSourceSuccess'); + var calSuccessRes; + var sourceSuccessRes; + if (eventSource.success) { + sourceSuccessRes = eventSource.success(rawEvents, res.xhr); + } + if (calSuccess) { + calSuccessRes = calSuccess(rawEvents, res.xhr); + } + rawEvents = sourceSuccessRes || calSuccessRes || rawEvents; + calendar.dispatch({ + type: 'RECEIVE_EVENTS', + sourceId: eventSource.sourceId, + fetchId: fetchId, + fetchRange: fetchRange, + rawEvents: rawEvents + }); + }, function (error) { + var callFailure = calendar.opt('eventSourceFailure'); + console.warn(error.message, error); + if (eventSource.failure) { + eventSource.failure(error); + } + if (callFailure) { + callFailure(error); + } + calendar.dispatch({ + type: 'RECEIVE_EVENT_ERROR', + sourceId: eventSource.sourceId, + fetchId: fetchId, + fetchRange: fetchRange, + error: error + }); + }); + return __assign({}, eventSource, { isFetching: true, latestFetchId: fetchId }); + } + function receiveResponse(sourceHash, sourceId, fetchId, fetchRange) { + var _a; + var eventSource = sourceHash[sourceId]; + if (eventSource && // not already removed + fetchId === eventSource.latestFetchId) { + return __assign({}, sourceHash, (_a = {}, _a[sourceId] = __assign({}, eventSource, { isFetching: false, fetchRange: fetchRange }), _a)); + } + return sourceHash; + } + function excludeStaticSources(eventSources, calendar) { + return filterHash(eventSources, function (eventSource) { + return doesSourceNeedRange(eventSource, calendar); + }); + } + + var DateProfileGenerator = /** @class */ (function () { + function DateProfileGenerator(viewSpec, calendar) { + this.viewSpec = viewSpec; + this.options = viewSpec.options; + this.dateEnv = calendar.dateEnv; + this.calendar = calendar; + this.initHiddenDays(); + } + /* Date Range Computation + ------------------------------------------------------------------------------------------------------------------*/ + // Builds a structure with info about what the dates/ranges will be for the "prev" view. + DateProfileGenerator.prototype.buildPrev = function (currentDateProfile, currentDate) { + var dateEnv = this.dateEnv; + var prevDate = dateEnv.subtract(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month + currentDateProfile.dateIncrement); + return this.build(prevDate, -1); + }; + // Builds a structure with info about what the dates/ranges will be for the "next" view. + DateProfileGenerator.prototype.buildNext = function (currentDateProfile, currentDate) { + var dateEnv = this.dateEnv; + var nextDate = dateEnv.add(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month + currentDateProfile.dateIncrement); + return this.build(nextDate, 1); + }; + // Builds a structure holding dates/ranges for rendering around the given date. + // Optional direction param indicates whether the date is being incremented/decremented + // from its previous value. decremented = -1, incremented = 1 (default). + DateProfileGenerator.prototype.build = function (currentDate, direction, forceToValid) { + if (forceToValid === void 0) { forceToValid = false; } + var validRange; + var minTime = null; + var maxTime = null; + var currentInfo; + var isRangeAllDay; + var renderRange; + var activeRange; + var isValid; + validRange = this.buildValidRange(); + validRange = this.trimHiddenDays(validRange); + if (forceToValid) { + currentDate = constrainMarkerToRange(currentDate, validRange); + } + currentInfo = this.buildCurrentRangeInfo(currentDate, direction); + isRangeAllDay = /^(year|month|week|day)$/.test(currentInfo.unit); + renderRange = this.buildRenderRange(this.trimHiddenDays(currentInfo.range), currentInfo.unit, isRangeAllDay); + renderRange = this.trimHiddenDays(renderRange); + activeRange = renderRange; + if (!this.options.showNonCurrentDates) { + activeRange = intersectRanges(activeRange, currentInfo.range); + } + minTime = createDuration(this.options.minTime); + maxTime = createDuration(this.options.maxTime); + activeRange = this.adjustActiveRange(activeRange, minTime, maxTime); + activeRange = intersectRanges(activeRange, validRange); // might return null + // it's invalid if the originally requested date is not contained, + // or if the range is completely outside of the valid range. + isValid = rangesIntersect(currentInfo.range, validRange); + return { + // constraint for where prev/next operations can go and where events can be dragged/resized to. + // an object with optional start and end properties. + validRange: validRange, + // range the view is formally responsible for. + // for example, a month view might have 1st-31st, excluding padded dates + currentRange: currentInfo.range, + // name of largest unit being displayed, like "month" or "week" + currentRangeUnit: currentInfo.unit, + isRangeAllDay: isRangeAllDay, + // dates that display events and accept drag-n-drop + // will be `null` if no dates accept events + activeRange: activeRange, + // date range with a rendered skeleton + // includes not-active days that need some sort of DOM + renderRange: renderRange, + // Duration object that denotes the first visible time of any given day + minTime: minTime, + // Duration object that denotes the exclusive visible end time of any given day + maxTime: maxTime, + isValid: isValid, + // how far the current date will move for a prev/next operation + dateIncrement: this.buildDateIncrement(currentInfo.duration) + // pass a fallback (might be null) ^ + }; + }; + // Builds an object with optional start/end properties. + // Indicates the minimum/maximum dates to display. + // not responsible for trimming hidden days. + DateProfileGenerator.prototype.buildValidRange = function () { + return this.getRangeOption('validRange', this.calendar.getNow()) || + { start: null, end: null }; // completely open-ended + }; + // Builds a structure with info about the "current" range, the range that is + // highlighted as being the current month for example. + // See build() for a description of `direction`. + // Guaranteed to have `range` and `unit` properties. `duration` is optional. + DateProfileGenerator.prototype.buildCurrentRangeInfo = function (date, direction) { + var _a = this, viewSpec = _a.viewSpec, dateEnv = _a.dateEnv; + var duration = null; + var unit = null; + var range = null; + var dayCount; + if (viewSpec.duration) { + duration = viewSpec.duration; + unit = viewSpec.durationUnit; + range = this.buildRangeFromDuration(date, direction, duration, unit); + } + else if ((dayCount = this.options.dayCount)) { + unit = 'day'; + range = this.buildRangeFromDayCount(date, direction, dayCount); + } + else if ((range = this.buildCustomVisibleRange(date))) { + unit = dateEnv.greatestWholeUnit(range.start, range.end).unit; + } + else { + duration = this.getFallbackDuration(); + unit = greatestDurationDenominator(duration).unit; + range = this.buildRangeFromDuration(date, direction, duration, unit); + } + return { duration: duration, unit: unit, range: range }; + }; + DateProfileGenerator.prototype.getFallbackDuration = function () { + return createDuration({ day: 1 }); + }; + // Returns a new activeRange to have time values (un-ambiguate) + // minTime or maxTime causes the range to expand. + DateProfileGenerator.prototype.adjustActiveRange = function (range, minTime, maxTime) { + var dateEnv = this.dateEnv; + var start = range.start; + var end = range.end; + if (this.viewSpec.class.prototype.usesMinMaxTime) { + // expand active range if minTime is negative (why not when positive?) + if (asRoughDays(minTime) < 0) { + start = startOfDay(start); // necessary? + start = dateEnv.add(start, minTime); + } + // expand active range if maxTime is beyond one day (why not when positive?) + if (asRoughDays(maxTime) > 1) { + end = startOfDay(end); // necessary? + end = addDays(end, -1); + end = dateEnv.add(end, maxTime); + } + } + return { start: start, end: end }; + }; + // Builds the "current" range when it is specified as an explicit duration. + // `unit` is the already-computed greatestDurationDenominator unit of duration. + DateProfileGenerator.prototype.buildRangeFromDuration = function (date, direction, duration, unit) { + var dateEnv = this.dateEnv; + var alignment = this.options.dateAlignment; + var dateIncrementInput; + var dateIncrementDuration; + var start; + var end; + var res; + // compute what the alignment should be + if (!alignment) { + dateIncrementInput = this.options.dateIncrement; + if (dateIncrementInput) { + dateIncrementDuration = createDuration(dateIncrementInput); + // use the smaller of the two units + if (asRoughMs(dateIncrementDuration) < asRoughMs(duration)) { + alignment = greatestDurationDenominator(dateIncrementDuration, !getWeeksFromInput(dateIncrementInput)).unit; + } + else { + alignment = unit; + } + } + else { + alignment = unit; + } + } + // if the view displays a single day or smaller + if (asRoughDays(duration) <= 1) { + if (this.isHiddenDay(start)) { + start = this.skipHiddenDays(start, direction); + start = startOfDay(start); + } + } + function computeRes() { + start = dateEnv.startOf(date, alignment); + end = dateEnv.add(start, duration); + res = { start: start, end: end }; + } + computeRes(); + // if range is completely enveloped by hidden days, go past the hidden days + if (!this.trimHiddenDays(res)) { + date = this.skipHiddenDays(date, direction); + computeRes(); + } + return res; + }; + // Builds the "current" range when a dayCount is specified. + DateProfileGenerator.prototype.buildRangeFromDayCount = function (date, direction, dayCount) { + var dateEnv = this.dateEnv; + var customAlignment = this.options.dateAlignment; + var runningCount = 0; + var start = date; + var end; + if (customAlignment) { + start = dateEnv.startOf(start, customAlignment); + } + start = startOfDay(start); + start = this.skipHiddenDays(start, direction); + end = start; + do { + end = addDays(end, 1); + if (!this.isHiddenDay(end)) { + runningCount++; + } + } while (runningCount < dayCount); + return { start: start, end: end }; + }; + // Builds a normalized range object for the "visible" range, + // which is a way to define the currentRange and activeRange at the same time. + DateProfileGenerator.prototype.buildCustomVisibleRange = function (date) { + var dateEnv = this.dateEnv; + var visibleRange = this.getRangeOption('visibleRange', dateEnv.toDate(date)); + if (visibleRange && (visibleRange.start == null || visibleRange.end == null)) { + return null; + } + return visibleRange; + }; + // Computes the range that will represent the element/cells for *rendering*, + // but which may have voided days/times. + // not responsible for trimming hidden days. + DateProfileGenerator.prototype.buildRenderRange = function (currentRange, currentRangeUnit, isRangeAllDay) { + return currentRange; + }; + // Compute the duration value that should be added/substracted to the current date + // when a prev/next operation happens. + DateProfileGenerator.prototype.buildDateIncrement = function (fallback) { + var dateIncrementInput = this.options.dateIncrement; + var customAlignment; + if (dateIncrementInput) { + return createDuration(dateIncrementInput); + } + else if ((customAlignment = this.options.dateAlignment)) { + return createDuration(1, customAlignment); + } + else if (fallback) { + return fallback; + } + else { + return createDuration({ days: 1 }); + } + }; + // Arguments after name will be forwarded to a hypothetical function value + // WARNING: passed-in arguments will be given to generator functions as-is and can cause side-effects. + // Always clone your objects if you fear mutation. + DateProfileGenerator.prototype.getRangeOption = function (name) { + var otherArgs = []; + for (var _i = 1; _i < arguments.length; _i++) { + otherArgs[_i - 1] = arguments[_i]; + } + var val = this.options[name]; + if (typeof val === 'function') { + val = val.apply(null, otherArgs); + } + if (val) { + val = parseRange(val, this.dateEnv); + } + if (val) { + val = computeVisibleDayRange(val); + } + return val; + }; + /* Hidden Days + ------------------------------------------------------------------------------------------------------------------*/ + // Initializes internal variables related to calculating hidden days-of-week + DateProfileGenerator.prototype.initHiddenDays = function () { + var hiddenDays = this.options.hiddenDays || []; // array of day-of-week indices that are hidden + var isHiddenDayHash = []; // is the day-of-week hidden? (hash with day-of-week-index -> bool) + var dayCnt = 0; + var i; + if (this.options.weekends === false) { + hiddenDays.push(0, 6); // 0=sunday, 6=saturday + } + for (i = 0; i < 7; i++) { + if (!(isHiddenDayHash[i] = hiddenDays.indexOf(i) !== -1)) { + dayCnt++; + } + } + if (!dayCnt) { + throw new Error('invalid hiddenDays'); // all days were hidden? bad. + } + this.isHiddenDayHash = isHiddenDayHash; + }; + // Remove days from the beginning and end of the range that are computed as hidden. + // If the whole range is trimmed off, returns null + DateProfileGenerator.prototype.trimHiddenDays = function (range) { + var start = range.start; + var end = range.end; + if (start) { + start = this.skipHiddenDays(start); + } + if (end) { + end = this.skipHiddenDays(end, -1, true); + } + if (start == null || end == null || start < end) { + return { start: start, end: end }; + } + return null; + }; + // Is the current day hidden? + // `day` is a day-of-week index (0-6), or a Date (used for UTC) + DateProfileGenerator.prototype.isHiddenDay = function (day) { + if (day instanceof Date) { + day = day.getUTCDay(); + } + return this.isHiddenDayHash[day]; + }; + // Incrementing the current day until it is no longer a hidden day, returning a copy. + // DOES NOT CONSIDER validRange! + // If the initial value of `date` is not a hidden day, don't do anything. + // Pass `isExclusive` as `true` if you are dealing with an end date. + // `inc` defaults to `1` (increment one day forward each time) + DateProfileGenerator.prototype.skipHiddenDays = function (date, inc, isExclusive) { + if (inc === void 0) { inc = 1; } + if (isExclusive === void 0) { isExclusive = false; } + while (this.isHiddenDayHash[(date.getUTCDay() + (isExclusive ? inc : 0) + 7) % 7]) { + date = addDays(date, inc); + } + return date; + }; + return DateProfileGenerator; + }()); + // TODO: find a way to avoid comparing DateProfiles. it's tedious + function isDateProfilesEqual(p0, p1) { + return rangesEqual(p0.validRange, p1.validRange) && + rangesEqual(p0.activeRange, p1.activeRange) && + rangesEqual(p0.renderRange, p1.renderRange) && + durationsEqual(p0.minTime, p1.minTime) && + durationsEqual(p0.maxTime, p1.maxTime); + /* + TODO: compare more? + currentRange: DateRange + currentRangeUnit: string + isRangeAllDay: boolean + isValid: boolean + dateIncrement: Duration + */ + } + + function reduce (state, action, calendar) { + var viewType = reduceViewType(state.viewType, action); + var dateProfile = reduceDateProfile(state.dateProfile, action, state.currentDate, viewType, calendar); + var eventSources = reduceEventSources(state.eventSources, action, dateProfile, calendar); + var nextState = __assign({}, state, { viewType: viewType, + dateProfile: dateProfile, currentDate: reduceCurrentDate(state.currentDate, action, dateProfile), eventSources: eventSources, eventStore: reduceEventStore(state.eventStore, action, eventSources, dateProfile, calendar), dateSelection: reduceDateSelection(state.dateSelection, action, calendar), eventSelection: reduceSelectedEvent(state.eventSelection, action), eventDrag: reduceEventDrag(state.eventDrag, action, eventSources, calendar), eventResize: reduceEventResize(state.eventResize, action, eventSources, calendar), eventSourceLoadingLevel: computeLoadingLevel(eventSources), loadingLevel: computeLoadingLevel(eventSources) }); + for (var _i = 0, _a = calendar.pluginSystem.hooks.reducers; _i < _a.length; _i++) { + var reducerFunc = _a[_i]; + nextState = reducerFunc(nextState, action, calendar); + } + // console.log(action.type, nextState) + return nextState; + } + function reduceViewType(currentViewType, action) { + switch (action.type) { + case 'SET_VIEW_TYPE': + return action.viewType; + default: + return currentViewType; + } + } + function reduceDateProfile(currentDateProfile, action, currentDate, viewType, calendar) { + var newDateProfile; + switch (action.type) { + case 'PREV': + newDateProfile = calendar.dateProfileGenerators[viewType].buildPrev(currentDateProfile, currentDate); + break; + case 'NEXT': + newDateProfile = calendar.dateProfileGenerators[viewType].buildNext(currentDateProfile, currentDate); + break; + case 'SET_DATE': + if (!currentDateProfile.activeRange || + !rangeContainsMarker(currentDateProfile.currentRange, action.dateMarker)) { + newDateProfile = calendar.dateProfileGenerators[viewType].build(action.dateMarker, undefined, true // forceToValid + ); + } + break; + case 'SET_VIEW_TYPE': + var generator = calendar.dateProfileGenerators[viewType]; + if (!generator) { + throw new Error(viewType ? + 'The FullCalendar view "' + viewType + '" does not exist. Make sure your plugins are loaded correctly.' : + 'No available FullCalendar view plugins.'); + } + newDateProfile = generator.build(action.dateMarker || currentDate, undefined, true // forceToValid + ); + break; + } + if (newDateProfile && + newDateProfile.isValid && + !(currentDateProfile && isDateProfilesEqual(currentDateProfile, newDateProfile))) { + return newDateProfile; + } + else { + return currentDateProfile; + } + } + function reduceCurrentDate(currentDate, action, dateProfile) { + switch (action.type) { + case 'PREV': + case 'NEXT': + if (!rangeContainsMarker(dateProfile.currentRange, currentDate)) { + return dateProfile.currentRange.start; + } + else { + return currentDate; + } + case 'SET_DATE': + case 'SET_VIEW_TYPE': + var newDate = action.dateMarker || currentDate; + if (dateProfile.activeRange && !rangeContainsMarker(dateProfile.activeRange, newDate)) { + return dateProfile.currentRange.start; + } + else { + return newDate; + } + default: + return currentDate; + } + } + function reduceDateSelection(currentSelection, action, calendar) { + switch (action.type) { + case 'SELECT_DATES': + return action.selection; + case 'UNSELECT_DATES': + return null; + default: + return currentSelection; + } + } + function reduceSelectedEvent(currentInstanceId, action) { + switch (action.type) { + case 'SELECT_EVENT': + return action.eventInstanceId; + case 'UNSELECT_EVENT': + return ''; + default: + return currentInstanceId; + } + } + function reduceEventDrag(currentDrag, action, sources, calendar) { + switch (action.type) { + case 'SET_EVENT_DRAG': + var newDrag = action.state; + return { + affectedEvents: newDrag.affectedEvents, + mutatedEvents: newDrag.mutatedEvents, + isEvent: newDrag.isEvent, + origSeg: newDrag.origSeg + }; + case 'UNSET_EVENT_DRAG': + return null; + default: + return currentDrag; + } + } + function reduceEventResize(currentResize, action, sources, calendar) { + switch (action.type) { + case 'SET_EVENT_RESIZE': + var newResize = action.state; + return { + affectedEvents: newResize.affectedEvents, + mutatedEvents: newResize.mutatedEvents, + isEvent: newResize.isEvent, + origSeg: newResize.origSeg + }; + case 'UNSET_EVENT_RESIZE': + return null; + default: + return currentResize; + } + } + function computeLoadingLevel(eventSources) { + var cnt = 0; + for (var sourceId in eventSources) { + if (eventSources[sourceId].isFetching) { + cnt++; + } + } + return cnt; + } + + var STANDARD_PROPS = { + start: null, + end: null, + allDay: Boolean + }; + function parseDateSpan(raw, dateEnv, defaultDuration) { + var span = parseOpenDateSpan(raw, dateEnv); + var range = span.range; + if (!range.start) { + return null; + } + if (!range.end) { + if (defaultDuration == null) { + return null; + } + else { + range.end = dateEnv.add(range.start, defaultDuration); + } + } + return span; + } + /* + TODO: somehow combine with parseRange? + Will return null if the start/end props were present but parsed invalidly. + */ + function parseOpenDateSpan(raw, dateEnv) { + var leftovers = {}; + var standardProps = refineProps(raw, STANDARD_PROPS, {}, leftovers); + var startMeta = standardProps.start ? dateEnv.createMarkerMeta(standardProps.start) : null; + var endMeta = standardProps.end ? dateEnv.createMarkerMeta(standardProps.end) : null; + var allDay = standardProps.allDay; + if (allDay == null) { + allDay = (startMeta && startMeta.isTimeUnspecified) && + (!endMeta || endMeta.isTimeUnspecified); + } + // use this leftover object as the selection object + leftovers.range = { + start: startMeta ? startMeta.marker : null, + end: endMeta ? endMeta.marker : null + }; + leftovers.allDay = allDay; + return leftovers; + } + function isDateSpansEqual(span0, span1) { + return rangesEqual(span0.range, span1.range) && + span0.allDay === span1.allDay && + isSpanPropsEqual(span0, span1); + } + // the NON-DATE-RELATED props + function isSpanPropsEqual(span0, span1) { + for (var propName in span1) { + if (propName !== 'range' && propName !== 'allDay') { + if (span0[propName] !== span1[propName]) { + return false; + } + } + } + // are there any props that span0 has that span1 DOESN'T have? + // both have range/allDay, so no need to special-case. + for (var propName in span0) { + if (!(propName in span1)) { + return false; + } + } + return true; + } + function buildDateSpanApi(span, dateEnv) { + return { + start: dateEnv.toDate(span.range.start), + end: dateEnv.toDate(span.range.end), + startStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }), + endStr: dateEnv.formatIso(span.range.end, { omitTime: span.allDay }), + allDay: span.allDay + }; + } + function buildDatePointApi(span, dateEnv) { + return { + date: dateEnv.toDate(span.range.start), + dateStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }), + allDay: span.allDay + }; + } + function fabricateEventRange(dateSpan, eventUiBases, calendar) { + var def = parseEventDef({ editable: false }, '', // sourceId + dateSpan.allDay, true, // hasEnd + calendar); + return { + def: def, + ui: compileEventUi(def, eventUiBases), + instance: createEventInstance(def.defId, dateSpan.range), + range: dateSpan.range, + isStart: true, + isEnd: true + }; + } + + function compileViewDefs(defaultConfigs, overrideConfigs) { + var hash = {}; + var viewType; + for (viewType in defaultConfigs) { + ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs); + } + for (viewType in overrideConfigs) { + ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs); + } + return hash; + } + function ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs) { + if (hash[viewType]) { + return hash[viewType]; + } + var viewDef = buildViewDef(viewType, hash, defaultConfigs, overrideConfigs); + if (viewDef) { + hash[viewType] = viewDef; + } + return viewDef; + } + function buildViewDef(viewType, hash, defaultConfigs, overrideConfigs) { + var defaultConfig = defaultConfigs[viewType]; + var overrideConfig = overrideConfigs[viewType]; + var queryProp = function (name) { + return (defaultConfig && defaultConfig[name] !== null) ? defaultConfig[name] : + ((overrideConfig && overrideConfig[name] !== null) ? overrideConfig[name] : null); + }; + var theClass = queryProp('class'); + var superType = queryProp('superType'); + if (!superType && theClass) { + superType = + findViewNameBySubclass(theClass, overrideConfigs) || + findViewNameBySubclass(theClass, defaultConfigs); + } + var superDef = null; + if (superType) { + if (superType === viewType) { + throw new Error('Can\'t have a custom view type that references itself'); + } + superDef = ensureViewDef(superType, hash, defaultConfigs, overrideConfigs); + } + if (!theClass && superDef) { + theClass = superDef.class; + } + if (!theClass) { + return null; // don't throw a warning, might be settings for a single-unit view + } + return { + type: viewType, + class: theClass, + defaults: __assign({}, (superDef ? superDef.defaults : {}), (defaultConfig ? defaultConfig.options : {})), + overrides: __assign({}, (superDef ? superDef.overrides : {}), (overrideConfig ? overrideConfig.options : {})) + }; + } + function findViewNameBySubclass(viewSubclass, configs) { + var superProto = Object.getPrototypeOf(viewSubclass.prototype); + for (var viewType in configs) { + var parsed = configs[viewType]; + // need DIRECT subclass, so instanceof won't do it + if (parsed.class && parsed.class.prototype === superProto) { + return viewType; + } + } + return ''; + } + + function parseViewConfigs(inputs) { + return mapHash(inputs, parseViewConfig); + } + var VIEW_DEF_PROPS = { + type: String, + class: null + }; + function parseViewConfig(input) { + if (typeof input === 'function') { + input = { class: input }; + } + var options = {}; + var props = refineProps(input, VIEW_DEF_PROPS, {}, options); + return { + superType: props.type, + class: props.class, + options: options + }; + } + + function buildViewSpecs(defaultInputs, optionsManager) { + var defaultConfigs = parseViewConfigs(defaultInputs); + var overrideConfigs = parseViewConfigs(optionsManager.overrides.views); + var viewDefs = compileViewDefs(defaultConfigs, overrideConfigs); + return mapHash(viewDefs, function (viewDef) { + return buildViewSpec(viewDef, overrideConfigs, optionsManager); + }); + } + function buildViewSpec(viewDef, overrideConfigs, optionsManager) { + var durationInput = viewDef.overrides.duration || + viewDef.defaults.duration || + optionsManager.dynamicOverrides.duration || + optionsManager.overrides.duration; + var duration = null; + var durationUnit = ''; + var singleUnit = ''; + var singleUnitOverrides = {}; + if (durationInput) { + duration = createDuration(durationInput); + if (duration) { // valid? + var denom = greatestDurationDenominator(duration, !getWeeksFromInput(durationInput)); + durationUnit = denom.unit; + if (denom.value === 1) { + singleUnit = durationUnit; + singleUnitOverrides = overrideConfigs[durationUnit] ? overrideConfigs[durationUnit].options : {}; + } + } + } + var queryButtonText = function (options) { + var buttonTextMap = options.buttonText || {}; + var buttonTextKey = viewDef.defaults.buttonTextKey; + if (buttonTextKey != null && buttonTextMap[buttonTextKey] != null) { + return buttonTextMap[buttonTextKey]; + } + if (buttonTextMap[viewDef.type] != null) { + return buttonTextMap[viewDef.type]; + } + if (buttonTextMap[singleUnit] != null) { + return buttonTextMap[singleUnit]; + } + }; + return { + type: viewDef.type, + class: viewDef.class, + duration: duration, + durationUnit: durationUnit, + singleUnit: singleUnit, + options: __assign({}, globalDefaults, viewDef.defaults, optionsManager.dirDefaults, optionsManager.localeDefaults, optionsManager.overrides, singleUnitOverrides, viewDef.overrides, optionsManager.dynamicOverrides), + buttonTextOverride: queryButtonText(optionsManager.dynamicOverrides) || + queryButtonText(optionsManager.overrides) || // constructor-specified buttonText lookup hash takes precedence + viewDef.overrides.buttonText, + buttonTextDefault: queryButtonText(optionsManager.localeDefaults) || + queryButtonText(optionsManager.dirDefaults) || + viewDef.defaults.buttonText || + queryButtonText(globalDefaults) || + viewDef.type // fall back to given view name + }; + } + + var Toolbar = /** @class */ (function (_super) { + __extends(Toolbar, _super); + function Toolbar(context, extraClassName) { + var _this = _super.call(this, context) || this; + _this._renderLayout = memoizeRendering(_this.renderLayout, _this.unrenderLayout); + _this._updateTitle = memoizeRendering(_this.updateTitle, null, [_this._renderLayout]); + _this._updateActiveButton = memoizeRendering(_this.updateActiveButton, null, [_this._renderLayout]); + _this._updateToday = memoizeRendering(_this.updateToday, null, [_this._renderLayout]); + _this._updatePrev = memoizeRendering(_this.updatePrev, null, [_this._renderLayout]); + _this._updateNext = memoizeRendering(_this.updateNext, null, [_this._renderLayout]); + _this.el = createElement('div', { className: 'fc-toolbar ' + extraClassName }); + return _this; + } + Toolbar.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this._renderLayout.unrender(); // should unrender everything else + removeElement(this.el); + }; + Toolbar.prototype.render = function (props) { + this._renderLayout(props.layout); + this._updateTitle(props.title); + this._updateActiveButton(props.activeButton); + this._updateToday(props.isTodayEnabled); + this._updatePrev(props.isPrevEnabled); + this._updateNext(props.isNextEnabled); + }; + Toolbar.prototype.renderLayout = function (layout) { + var el = this.el; + this.viewsWithButtons = []; + appendToElement(el, this.renderSection('left', layout.left)); + appendToElement(el, this.renderSection('center', layout.center)); + appendToElement(el, this.renderSection('right', layout.right)); + }; + Toolbar.prototype.unrenderLayout = function () { + this.el.innerHTML = ''; + }; + Toolbar.prototype.renderSection = function (position, buttonStr) { + var _this = this; + var _a = this, theme = _a.theme, calendar = _a.calendar; + var optionsManager = calendar.optionsManager; + var viewSpecs = calendar.viewSpecs; + var sectionEl = createElement('div', { className: 'fc-' + position }); + var calendarCustomButtons = optionsManager.computed.customButtons || {}; + var calendarButtonTextOverrides = optionsManager.overrides.buttonText || {}; + var calendarButtonText = optionsManager.computed.buttonText || {}; + if (buttonStr) { + buttonStr.split(' ').forEach(function (buttonGroupStr, i) { + var groupChildren = []; + var isOnlyButtons = true; + var groupEl; + buttonGroupStr.split(',').forEach(function (buttonName, j) { + var customButtonProps; + var viewSpec; + var buttonClick; + var buttonIcon; // only one of these will be set + var buttonText; // " + var buttonInnerHtml; + var buttonClasses; + var buttonEl; + var buttonAriaAttr; + if (buttonName === 'title') { + groupChildren.push(htmlToElement('<h2> </h2>')); // we always want it to take up height + isOnlyButtons = false; + } + else { + if ((customButtonProps = calendarCustomButtons[buttonName])) { + buttonClick = function (ev) { + if (customButtonProps.click) { + customButtonProps.click.call(buttonEl, ev); + } + }; + (buttonIcon = theme.getCustomButtonIconClass(customButtonProps)) || + (buttonIcon = theme.getIconClass(buttonName)) || + (buttonText = customButtonProps.text); + } + else if ((viewSpec = viewSpecs[buttonName])) { + _this.viewsWithButtons.push(buttonName); + buttonClick = function () { + calendar.changeView(buttonName); + }; + (buttonText = viewSpec.buttonTextOverride) || + (buttonIcon = theme.getIconClass(buttonName)) || + (buttonText = viewSpec.buttonTextDefault); + } + else if (calendar[buttonName]) { // a calendar method + buttonClick = function () { + calendar[buttonName](); + }; + (buttonText = calendarButtonTextOverrides[buttonName]) || + (buttonIcon = theme.getIconClass(buttonName)) || + (buttonText = calendarButtonText[buttonName]); + // ^ everything else is considered default + } + if (buttonClick) { + buttonClasses = [ + 'fc-' + buttonName + '-button', + theme.getClass('button') + ]; + if (buttonText) { + buttonInnerHtml = htmlEscape(buttonText); + buttonAriaAttr = ''; + } + else if (buttonIcon) { + buttonInnerHtml = "<span class='" + buttonIcon + "'></span>"; + buttonAriaAttr = ' aria-label="' + buttonName + '"'; + } + buttonEl = htmlToElement(// type="button" so that it doesn't submit a form + '<button type="button" class="' + buttonClasses.join(' ') + '"' + + buttonAriaAttr + + '>' + buttonInnerHtml + '</button>'); + buttonEl.addEventListener('click', buttonClick); + groupChildren.push(buttonEl); + } + } + }); + if (groupChildren.length > 1) { + groupEl = document.createElement('div'); + var buttonGroupClassName = theme.getClass('buttonGroup'); + if (isOnlyButtons && buttonGroupClassName) { + groupEl.classList.add(buttonGroupClassName); + } + appendToElement(groupEl, groupChildren); + sectionEl.appendChild(groupEl); + } + else { + appendToElement(sectionEl, groupChildren); // 1 or 0 children + } + }); + } + return sectionEl; + }; + Toolbar.prototype.updateToday = function (isTodayEnabled) { + this.toggleButtonEnabled('today', isTodayEnabled); + }; + Toolbar.prototype.updatePrev = function (isPrevEnabled) { + this.toggleButtonEnabled('prev', isPrevEnabled); + }; + Toolbar.prototype.updateNext = function (isNextEnabled) { + this.toggleButtonEnabled('next', isNextEnabled); + }; + Toolbar.prototype.updateTitle = function (text) { + findElements(this.el, 'h2').forEach(function (titleEl) { + titleEl.innerText = text; + }); + }; + Toolbar.prototype.updateActiveButton = function (buttonName) { + var className = this.theme.getClass('buttonActive'); + findElements(this.el, 'button').forEach(function (buttonEl) { + if (buttonName && buttonEl.classList.contains('fc-' + buttonName + '-button')) { + buttonEl.classList.add(className); + } + else { + buttonEl.classList.remove(className); + } + }); + }; + Toolbar.prototype.toggleButtonEnabled = function (buttonName, bool) { + findElements(this.el, '.fc-' + buttonName + '-button').forEach(function (buttonEl) { + buttonEl.disabled = !bool; + }); + }; + return Toolbar; + }(Component)); + + var CalendarComponent = /** @class */ (function (_super) { + __extends(CalendarComponent, _super); + function CalendarComponent(context, el) { + var _this = _super.call(this, context) || this; + _this._renderToolbars = memoizeRendering(_this.renderToolbars); + _this.buildViewPropTransformers = memoize(buildViewPropTransformers); + _this.el = el; + prependToElement(el, _this.contentEl = createElement('div', { className: 'fc-view-container' })); + var calendar = _this.calendar; + for (var _i = 0, _a = calendar.pluginSystem.hooks.viewContainerModifiers; _i < _a.length; _i++) { + var modifyViewContainer = _a[_i]; + modifyViewContainer(_this.contentEl, calendar); + } + _this.toggleElClassNames(true); + _this.computeTitle = memoize(computeTitle); + _this.parseBusinessHours = memoize(function (input) { + return parseBusinessHours(input, _this.calendar); + }); + return _this; + } + CalendarComponent.prototype.destroy = function () { + if (this.header) { + this.header.destroy(); + } + if (this.footer) { + this.footer.destroy(); + } + if (this.view) { + this.view.destroy(); + } + removeElement(this.contentEl); + this.toggleElClassNames(false); + _super.prototype.destroy.call(this); + }; + CalendarComponent.prototype.toggleElClassNames = function (bool) { + var classList = this.el.classList; + var dirClassName = 'fc-' + this.opt('dir'); + var themeClassName = this.theme.getClass('widget'); + if (bool) { + classList.add('fc'); + classList.add(dirClassName); + classList.add(themeClassName); + } + else { + classList.remove('fc'); + classList.remove(dirClassName); + classList.remove(themeClassName); + } + }; + CalendarComponent.prototype.render = function (props) { + this.freezeHeight(); + var title = this.computeTitle(props.dateProfile, props.viewSpec.options); + this._renderToolbars(props.viewSpec, props.dateProfile, props.currentDate, props.dateProfileGenerator, title); + this.renderView(props, title); + this.updateSize(); + this.thawHeight(); + }; + CalendarComponent.prototype.renderToolbars = function (viewSpec, dateProfile, currentDate, dateProfileGenerator, title) { + var headerLayout = this.opt('header'); + var footerLayout = this.opt('footer'); + var now = this.calendar.getNow(); + var todayInfo = dateProfileGenerator.build(now); + var prevInfo = dateProfileGenerator.buildPrev(dateProfile, currentDate); + var nextInfo = dateProfileGenerator.buildNext(dateProfile, currentDate); + var toolbarProps = { + title: title, + activeButton: viewSpec.type, + isTodayEnabled: todayInfo.isValid && !rangeContainsMarker(dateProfile.currentRange, now), + isPrevEnabled: prevInfo.isValid, + isNextEnabled: nextInfo.isValid + }; + if (headerLayout) { + if (!this.header) { + this.header = new Toolbar(this.context, 'fc-header-toolbar'); + prependToElement(this.el, this.header.el); + } + this.header.receiveProps(__assign({ layout: headerLayout }, toolbarProps)); + } + else if (this.header) { + this.header.destroy(); + this.header = null; + } + if (footerLayout) { + if (!this.footer) { + this.footer = new Toolbar(this.context, 'fc-footer-toolbar'); + appendToElement(this.el, this.footer.el); + } + this.footer.receiveProps(__assign({ layout: footerLayout }, toolbarProps)); + } + else if (this.footer) { + this.footer.destroy(); + this.footer = null; + } + }; + CalendarComponent.prototype.renderView = function (props, title) { + var view = this.view; + var viewSpec = props.viewSpec, dateProfileGenerator = props.dateProfileGenerator; + if (!view || view.viewSpec !== viewSpec) { + if (view) { + view.destroy(); + } + view = this.view = new viewSpec['class']({ + calendar: this.calendar, + view: null, + dateEnv: this.dateEnv, + theme: this.theme, + options: viewSpec.options + }, viewSpec, dateProfileGenerator, this.contentEl); + } + else { + view.addScroll(view.queryScroll()); + } + view.title = title; // for the API + var viewProps = { + dateProfile: props.dateProfile, + businessHours: this.parseBusinessHours(viewSpec.options.businessHours), + eventStore: props.eventStore, + eventUiBases: props.eventUiBases, + dateSelection: props.dateSelection, + eventSelection: props.eventSelection, + eventDrag: props.eventDrag, + eventResize: props.eventResize + }; + var transformers = this.buildViewPropTransformers(this.calendar.pluginSystem.hooks.viewPropsTransformers); + for (var _i = 0, transformers_1 = transformers; _i < transformers_1.length; _i++) { + var transformer = transformers_1[_i]; + __assign(viewProps, transformer.transform(viewProps, viewSpec, props, view)); + } + view.receiveProps(viewProps); + }; + // Sizing + // ----------------------------------------------------------------------------------------------------------------- + CalendarComponent.prototype.updateSize = function (isResize) { + if (isResize === void 0) { isResize = false; } + var view = this.view; + if (isResize) { + view.addScroll(view.queryScroll()); + } + if (isResize || this.isHeightAuto == null) { + this.computeHeightVars(); + } + view.updateSize(isResize, this.viewHeight, this.isHeightAuto); + view.updateNowIndicator(); // we need to guarantee this will run after updateSize + view.popScroll(isResize); + }; + CalendarComponent.prototype.computeHeightVars = function () { + var calendar = this.calendar; // yuck. need to handle dynamic options + var heightInput = calendar.opt('height'); + var contentHeightInput = calendar.opt('contentHeight'); + this.isHeightAuto = heightInput === 'auto' || contentHeightInput === 'auto'; + if (typeof contentHeightInput === 'number') { // exists and not 'auto' + this.viewHeight = contentHeightInput; + } + else if (typeof contentHeightInput === 'function') { // exists and is a function + this.viewHeight = contentHeightInput(); + } + else if (typeof heightInput === 'number') { // exists and not 'auto' + this.viewHeight = heightInput - this.queryToolbarsHeight(); + } + else if (typeof heightInput === 'function') { // exists and is a function + this.viewHeight = heightInput() - this.queryToolbarsHeight(); + } + else if (heightInput === 'parent') { // set to height of parent element + var parentEl = this.el.parentNode; + this.viewHeight = parentEl.getBoundingClientRect().height - this.queryToolbarsHeight(); + } + else { + this.viewHeight = Math.round(this.contentEl.getBoundingClientRect().width / + Math.max(calendar.opt('aspectRatio'), .5)); + } + }; + CalendarComponent.prototype.queryToolbarsHeight = function () { + var height = 0; + if (this.header) { + height += computeHeightAndMargins(this.header.el); + } + if (this.footer) { + height += computeHeightAndMargins(this.footer.el); + } + return height; + }; + // Height "Freezing" + // ----------------------------------------------------------------------------------------------------------------- + CalendarComponent.prototype.freezeHeight = function () { + applyStyle(this.el, { + height: this.el.getBoundingClientRect().height, + overflow: 'hidden' + }); + }; + CalendarComponent.prototype.thawHeight = function () { + applyStyle(this.el, { + height: '', + overflow: '' + }); + }; + return CalendarComponent; + }(Component)); + // Title and Date Formatting + // ----------------------------------------------------------------------------------------------------------------- + // Computes what the title at the top of the calendar should be for this view + function computeTitle(dateProfile, viewOptions) { + var range; + // for views that span a large unit of time, show the proper interval, ignoring stray days before and after + if (/^(year|month)$/.test(dateProfile.currentRangeUnit)) { + range = dateProfile.currentRange; + } + else { // for day units or smaller, use the actual day range + range = dateProfile.activeRange; + } + return this.dateEnv.formatRange(range.start, range.end, createFormatter(viewOptions.titleFormat || computeTitleFormat(dateProfile), viewOptions.titleRangeSeparator), { isEndExclusive: dateProfile.isRangeAllDay }); + } + // Generates the format string that should be used to generate the title for the current date range. + // Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`. + function computeTitleFormat(dateProfile) { + var currentRangeUnit = dateProfile.currentRangeUnit; + if (currentRangeUnit === 'year') { + return { year: 'numeric' }; + } + else if (currentRangeUnit === 'month') { + return { year: 'numeric', month: 'long' }; // like "September 2014" + } + else { + var days = diffWholeDays(dateProfile.currentRange.start, dateProfile.currentRange.end); + if (days !== null && days > 1) { + // multi-day range. shorter, like "Sep 9 - 10 2014" + return { year: 'numeric', month: 'short', day: 'numeric' }; + } + else { + // one day. longer, like "September 9 2014" + return { year: 'numeric', month: 'long', day: 'numeric' }; + } + } + } + // Plugin + // ----------------------------------------------------------------------------------------------------------------- + function buildViewPropTransformers(theClasses) { + return theClasses.map(function (theClass) { + return new theClass(); + }); + } + + var Interaction = /** @class */ (function () { + function Interaction(settings) { + this.component = settings.component; + } + Interaction.prototype.destroy = function () { + }; + return Interaction; + }()); + function parseInteractionSettings(component, input) { + return { + component: component, + el: input.el, + useEventCenter: input.useEventCenter != null ? input.useEventCenter : true + }; + } + function interactionSettingsToStore(settings) { + var _a; + return _a = {}, + _a[settings.component.uid] = settings, + _a; + } + // global state + var interactionSettingsStore = {}; + + /* + Detects when the user clicks on an event within a DateComponent + */ + var EventClicking = /** @class */ (function (_super) { + __extends(EventClicking, _super); + function EventClicking(settings) { + var _this = _super.call(this, settings) || this; + _this.handleSegClick = function (ev, segEl) { + var component = _this.component; + var seg = getElSeg(segEl); + if (seg && // might be the <div> surrounding the more link + component.isValidSegDownEl(ev.target)) { + // our way to simulate a link click for elements that can't be <a> tags + // grab before trigger fired in case trigger trashes DOM thru rerendering + var hasUrlContainer = elementClosest(ev.target, '.fc-has-url'); + var url = hasUrlContainer ? hasUrlContainer.querySelector('a[href]').href : ''; + component.publiclyTrigger('eventClick', [ + { + el: segEl, + event: new EventApi(component.calendar, seg.eventRange.def, seg.eventRange.instance), + jsEvent: ev, + view: component.view + } + ]); + if (url && !ev.defaultPrevented) { + window.location.href = url; + } + } + }; + var component = settings.component; + _this.destroy = listenBySelector(component.el, 'click', component.fgSegSelector + ',' + component.bgSegSelector, _this.handleSegClick); + return _this; + } + return EventClicking; + }(Interaction)); + + /* + Triggers events and adds/removes core classNames when the user's pointer + enters/leaves event-elements of a component. + */ + var EventHovering = /** @class */ (function (_super) { + __extends(EventHovering, _super); + function EventHovering(settings) { + var _this = _super.call(this, settings) || this; + // for simulating an eventMouseLeave when the event el is destroyed while mouse is over it + _this.handleEventElRemove = function (el) { + if (el === _this.currentSegEl) { + _this.handleSegLeave(null, _this.currentSegEl); + } + }; + _this.handleSegEnter = function (ev, segEl) { + if (getElSeg(segEl)) { // TODO: better way to make sure not hovering over more+ link or its wrapper + segEl.classList.add('fc-allow-mouse-resize'); + _this.currentSegEl = segEl; + _this.triggerEvent('eventMouseEnter', ev, segEl); + } + }; + _this.handleSegLeave = function (ev, segEl) { + if (_this.currentSegEl) { + segEl.classList.remove('fc-allow-mouse-resize'); + _this.currentSegEl = null; + _this.triggerEvent('eventMouseLeave', ev, segEl); + } + }; + var component = settings.component; + _this.removeHoverListeners = listenToHoverBySelector(component.el, component.fgSegSelector + ',' + component.bgSegSelector, _this.handleSegEnter, _this.handleSegLeave); + component.calendar.on('eventElRemove', _this.handleEventElRemove); + return _this; + } + EventHovering.prototype.destroy = function () { + this.removeHoverListeners(); + this.component.calendar.off('eventElRemove', this.handleEventElRemove); + }; + EventHovering.prototype.triggerEvent = function (publicEvName, ev, segEl) { + var component = this.component; + var seg = getElSeg(segEl); + if (!ev || component.isValidSegDownEl(ev.target)) { + component.publiclyTrigger(publicEvName, [ + { + el: segEl, + event: new EventApi(this.component.calendar, seg.eventRange.def, seg.eventRange.instance), + jsEvent: ev, + view: component.view + } + ]); + } + }; + return EventHovering; + }(Interaction)); + + var StandardTheme = /** @class */ (function (_super) { + __extends(StandardTheme, _super); + function StandardTheme() { + return _super !== null && _super.apply(this, arguments) || this; + } + return StandardTheme; + }(Theme)); + StandardTheme.prototype.classes = { + widget: 'fc-unthemed', + widgetHeader: 'fc-widget-header', + widgetContent: 'fc-widget-content', + buttonGroup: 'fc-button-group', + button: 'fc-button fc-button-primary', + buttonActive: 'fc-button-active', + popoverHeader: 'fc-widget-header', + popoverContent: 'fc-widget-content', + // day grid + headerRow: 'fc-widget-header', + dayRow: 'fc-widget-content', + // list view + listView: 'fc-widget-content' + }; + StandardTheme.prototype.baseIconClass = 'fc-icon'; + StandardTheme.prototype.iconClasses = { + close: 'fc-icon-x', + prev: 'fc-icon-chevron-left', + next: 'fc-icon-chevron-right', + prevYear: 'fc-icon-chevrons-left', + nextYear: 'fc-icon-chevrons-right' + }; + StandardTheme.prototype.iconOverrideOption = 'buttonIcons'; + StandardTheme.prototype.iconOverrideCustomButtonOption = 'icon'; + StandardTheme.prototype.iconOverridePrefix = 'fc-icon-'; + + var Calendar = /** @class */ (function () { + function Calendar(el, overrides) { + var _this = this; + this.parseRawLocales = memoize(parseRawLocales); + this.buildLocale = memoize(buildLocale); + this.buildDateEnv = memoize(buildDateEnv); + this.buildTheme = memoize(buildTheme); + this.buildEventUiSingleBase = memoize(this._buildEventUiSingleBase); + this.buildSelectionConfig = memoize(this._buildSelectionConfig); + this.buildEventUiBySource = memoizeOutput(buildEventUiBySource, isPropsEqual); + this.buildEventUiBases = memoize(buildEventUiBases); + this.interactionsStore = {}; + this.actionQueue = []; + this.isReducing = false; + // isDisplaying: boolean = false // installed in DOM? accepting renders? + this.needsRerender = false; // needs a render? + this.needsFullRerender = false; + this.isRendering = false; // currently in the executeRender function? + this.renderingPauseDepth = 0; + this.buildDelayedRerender = memoize(buildDelayedRerender); + this.afterSizingTriggers = {}; + this.isViewUpdated = false; + this.isDatesUpdated = false; + this.isEventsUpdated = false; + this.el = el; + this.optionsManager = new OptionsManager(overrides || {}); + this.pluginSystem = new PluginSystem(); + // only do once. don't do in handleOptions. because can't remove plugins + this.addPluginInputs(this.optionsManager.computed.plugins || []); + this.handleOptions(this.optionsManager.computed); + this.publiclyTrigger('_init'); // for tests + this.hydrate(); + this.calendarInteractions = this.pluginSystem.hooks.calendarInteractions + .map(function (calendarInteractionClass) { + return new calendarInteractionClass(_this); + }); + } + Calendar.prototype.addPluginInputs = function (pluginInputs) { + var pluginDefs = refinePluginDefs(pluginInputs); + for (var _i = 0, pluginDefs_1 = pluginDefs; _i < pluginDefs_1.length; _i++) { + var pluginDef = pluginDefs_1[_i]; + this.pluginSystem.add(pluginDef); + } + }; + Object.defineProperty(Calendar.prototype, "view", { + // public API + get: function () { + return this.component ? this.component.view : null; + }, + enumerable: true, + configurable: true + }); + // Public API for rendering + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.render = function () { + if (!this.component) { + this.renderableEventStore = createEmptyEventStore(); + this.bindHandlers(); + this.executeRender(); + } + else { + this.requestRerender(true); + } + }; + Calendar.prototype.destroy = function () { + if (this.component) { + this.unbindHandlers(); + this.component.destroy(); // don't null-out. in case API needs access + this.component = null; // umm ??? + for (var _i = 0, _a = this.calendarInteractions; _i < _a.length; _i++) { + var interaction = _a[_i]; + interaction.destroy(); + } + this.publiclyTrigger('_destroyed'); + } + }; + // Handlers + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.bindHandlers = function () { + var _this = this; + // event delegation for nav links + this.removeNavLinkListener = listenBySelector(this.el, 'click', 'a[data-goto]', function (ev, anchorEl) { + var gotoOptions = anchorEl.getAttribute('data-goto'); + gotoOptions = gotoOptions ? JSON.parse(gotoOptions) : {}; + var dateEnv = _this.dateEnv; + var dateMarker = dateEnv.createMarker(gotoOptions.date); + var viewType = gotoOptions.type; + // property like "navLinkDayClick". might be a string or a function + var customAction = _this.viewOpt('navLink' + capitaliseFirstLetter(viewType) + 'Click'); + if (typeof customAction === 'function') { + customAction(dateEnv.toDate(dateMarker), ev); + } + else { + if (typeof customAction === 'string') { + viewType = customAction; + } + _this.zoomTo(dateMarker, viewType); + } + }); + if (this.opt('handleWindowResize')) { + window.addEventListener('resize', this.windowResizeProxy = debounce(// prevents rapid calls + this.windowResize.bind(this), this.opt('windowResizeDelay'))); + } + }; + Calendar.prototype.unbindHandlers = function () { + this.removeNavLinkListener(); + if (this.windowResizeProxy) { + window.removeEventListener('resize', this.windowResizeProxy); + this.windowResizeProxy = null; + } + }; + // Dispatcher + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.hydrate = function () { + var _this = this; + this.state = this.buildInitialState(); + var rawSources = this.opt('eventSources') || []; + var singleRawSource = this.opt('events'); + var sources = []; // parsed + if (singleRawSource) { + rawSources.unshift(singleRawSource); + } + for (var _i = 0, rawSources_1 = rawSources; _i < rawSources_1.length; _i++) { + var rawSource = rawSources_1[_i]; + var source = parseEventSource(rawSource, this); + if (source) { + sources.push(source); + } + } + this.batchRendering(function () { + _this.dispatch({ type: 'INIT' }); // pass in sources here? + _this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: sources }); + _this.dispatch({ + type: 'SET_VIEW_TYPE', + viewType: _this.opt('defaultView') || _this.pluginSystem.hooks.defaultView + }); + }); + }; + Calendar.prototype.buildInitialState = function () { + return { + viewType: null, + loadingLevel: 0, + eventSourceLoadingLevel: 0, + currentDate: this.getInitialDate(), + dateProfile: null, + eventSources: {}, + eventStore: createEmptyEventStore(), + dateSelection: null, + eventSelection: '', + eventDrag: null, + eventResize: null + }; + }; + Calendar.prototype.dispatch = function (action) { + this.actionQueue.push(action); + if (!this.isReducing) { + this.isReducing = true; + var oldState = this.state; + while (this.actionQueue.length) { + this.state = this.reduce(this.state, this.actionQueue.shift(), this); + } + var newState = this.state; + this.isReducing = false; + if (!oldState.loadingLevel && newState.loadingLevel) { + this.publiclyTrigger('loading', [true]); + } + else if (oldState.loadingLevel && !newState.loadingLevel) { + this.publiclyTrigger('loading', [false]); + } + var view = this.component && this.component.view; + if (oldState.eventStore !== newState.eventStore || this.needsFullRerender) { + if (oldState.eventStore) { + this.isEventsUpdated = true; + } + } + if (oldState.dateProfile !== newState.dateProfile || this.needsFullRerender) { + if (oldState.dateProfile && view) { // why would view be null!? + this.publiclyTrigger('datesDestroy', [ + { + view: view, + el: view.el + } + ]); + } + this.isDatesUpdated = true; + } + if (oldState.viewType !== newState.viewType || this.needsFullRerender) { + if (oldState.viewType && view) { // why would view be null!? + this.publiclyTrigger('viewSkeletonDestroy', [ + { + view: view, + el: view.el + } + ]); + } + this.isViewUpdated = true; + } + this.requestRerender(); + } + }; + Calendar.prototype.reduce = function (state, action, calendar) { + return reduce(state, action, calendar); + }; + // Render Queue + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.requestRerender = function (needsFull) { + if (needsFull === void 0) { needsFull = false; } + this.needsRerender = true; + this.needsFullRerender = this.needsFullRerender || needsFull; + this.delayedRerender(); // will call a debounced-version of tryRerender + }; + Calendar.prototype.tryRerender = function () { + if (this.component && // must be accepting renders + this.needsRerender && // indicates that a rerender was requested + !this.renderingPauseDepth && // not paused + !this.isRendering // not currently in the render loop + ) { + this.executeRender(); + } + }; + Calendar.prototype.batchRendering = function (func) { + this.renderingPauseDepth++; + func(); + this.renderingPauseDepth--; + if (this.needsRerender) { + this.requestRerender(); + } + }; + // Rendering + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.executeRender = function () { + var needsFullRerender = this.needsFullRerender; // save before clearing + // clear these BEFORE the render so that new values will accumulate during render + this.needsRerender = false; + this.needsFullRerender = false; + this.isRendering = true; + this.renderComponent(needsFullRerender); + this.isRendering = false; + // received a rerender request while rendering + if (this.needsRerender) { + this.delayedRerender(); + } + }; + /* + don't call this directly. use executeRender instead + */ + Calendar.prototype.renderComponent = function (needsFull) { + var _a = this, state = _a.state, component = _a.component; + var viewType = state.viewType; + var viewSpec = this.viewSpecs[viewType]; + var savedScroll = (needsFull && component) ? component.view.queryScroll() : null; + if (!viewSpec) { + throw new Error("View type \"" + viewType + "\" is not valid"); + } + // if event sources are still loading and progressive rendering hasn't been enabled, + // keep rendering the last fully loaded set of events + var renderableEventStore = this.renderableEventStore = + (state.eventSourceLoadingLevel && !this.opt('progressiveEventRendering')) ? + this.renderableEventStore : + state.eventStore; + var eventUiSingleBase = this.buildEventUiSingleBase(viewSpec.options); + var eventUiBySource = this.buildEventUiBySource(state.eventSources); + var eventUiBases = this.eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource); + if (needsFull || !component) { + if (component) { + component.freezeHeight(); // next component will unfreeze it + component.destroy(); + } + component = this.component = new CalendarComponent({ + calendar: this, + view: null, + dateEnv: this.dateEnv, + theme: this.theme, + options: this.optionsManager.computed + }, this.el); + this.isViewUpdated = true; + this.isDatesUpdated = true; + this.isEventsUpdated = true; + } + component.receiveProps(__assign({}, state, { viewSpec: viewSpec, dateProfile: state.dateProfile, dateProfileGenerator: this.dateProfileGenerators[viewType], eventStore: renderableEventStore, eventUiBases: eventUiBases, dateSelection: state.dateSelection, eventSelection: state.eventSelection, eventDrag: state.eventDrag, eventResize: state.eventResize })); + if (savedScroll) { + component.view.applyScroll(savedScroll, false); + } + if (this.isViewUpdated) { + this.isViewUpdated = false; + this.publiclyTrigger('viewSkeletonRender', [ + { + view: component.view, + el: component.view.el + } + ]); + } + if (this.isDatesUpdated) { + this.isDatesUpdated = false; + this.publiclyTrigger('datesRender', [ + { + view: component.view, + el: component.view.el + } + ]); + } + if (this.isEventsUpdated) { + this.isEventsUpdated = false; + } + this.releaseAfterSizingTriggers(); + }; + // Options + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.setOption = function (name, val) { + var _a; + this.mutateOptions((_a = {}, _a[name] = val, _a), [], true); + }; + Calendar.prototype.getOption = function (name) { + return this.optionsManager.computed[name]; + }; + Calendar.prototype.opt = function (name) { + return this.optionsManager.computed[name]; + }; + Calendar.prototype.viewOpt = function (name) { + return this.viewOpts()[name]; + }; + Calendar.prototype.viewOpts = function () { + return this.viewSpecs[this.state.viewType].options; + }; + /* + handles option changes (like a diff) + */ + Calendar.prototype.mutateOptions = function (updates, removals, isDynamic, deepEqual) { + var _this = this; + var changeHandlers = this.pluginSystem.hooks.optionChangeHandlers; + var normalUpdates = {}; + var specialUpdates = {}; + var oldDateEnv = this.dateEnv; // do this before handleOptions + var isTimeZoneDirty = false; + var isSizeDirty = false; + var anyDifficultOptions = Boolean(removals.length); + for (var name_1 in updates) { + if (changeHandlers[name_1]) { + specialUpdates[name_1] = updates[name_1]; + } + else { + normalUpdates[name_1] = updates[name_1]; + } + } + for (var name_2 in normalUpdates) { + if (/^(height|contentHeight|aspectRatio)$/.test(name_2)) { + isSizeDirty = true; + } + else if (/^(defaultDate|defaultView)$/.test(name_2)) ; + else { + anyDifficultOptions = true; + if (name_2 === 'timeZone') { + isTimeZoneDirty = true; + } + } + } + this.optionsManager.mutate(normalUpdates, removals, isDynamic); + if (anyDifficultOptions) { + this.handleOptions(this.optionsManager.computed); + this.needsFullRerender = true; + } + this.batchRendering(function () { + if (anyDifficultOptions) { + if (isTimeZoneDirty) { + _this.dispatch({ + type: 'CHANGE_TIMEZONE', + oldDateEnv: oldDateEnv + }); + } + /* HACK + has the same effect as calling this.requestRerender(true) + but recomputes the state's dateProfile + */ + _this.dispatch({ + type: 'SET_VIEW_TYPE', + viewType: _this.state.viewType + }); + } + else if (isSizeDirty) { + _this.updateSize(); + } + // special updates + if (deepEqual) { + for (var name_3 in specialUpdates) { + changeHandlers[name_3](specialUpdates[name_3], _this, deepEqual); + } + } + }); + }; + /* + rebuilds things based off of a complete set of refined options + */ + Calendar.prototype.handleOptions = function (options) { + var _this = this; + var pluginHooks = this.pluginSystem.hooks; + this.defaultAllDayEventDuration = createDuration(options.defaultAllDayEventDuration); + this.defaultTimedEventDuration = createDuration(options.defaultTimedEventDuration); + this.delayedRerender = this.buildDelayedRerender(options.rerenderDelay); + this.theme = this.buildTheme(options); + var available = this.parseRawLocales(options.locales); + this.availableRawLocales = available.map; + var locale = this.buildLocale(options.locale || available.defaultCode, available.map); + this.dateEnv = this.buildDateEnv(locale, options.timeZone, pluginHooks.namedTimeZonedImpl, options.firstDay, options.weekNumberCalculation, options.weekLabel, pluginHooks.cmdFormatter); + this.selectionConfig = this.buildSelectionConfig(options); // needs dateEnv. do after :( + // ineffecient to do every time? + this.viewSpecs = buildViewSpecs(pluginHooks.views, this.optionsManager); + // ineffecient to do every time? + this.dateProfileGenerators = mapHash(this.viewSpecs, function (viewSpec) { + return new viewSpec.class.prototype.dateProfileGeneratorClass(viewSpec, _this); + }); + }; + Calendar.prototype.getAvailableLocaleCodes = function () { + return Object.keys(this.availableRawLocales); + }; + Calendar.prototype._buildSelectionConfig = function (rawOpts) { + return processScopedUiProps('select', rawOpts, this); + }; + Calendar.prototype._buildEventUiSingleBase = function (rawOpts) { + if (rawOpts.editable) { // so 'editable' affected events + rawOpts = __assign({}, rawOpts, { eventEditable: true }); + } + return processScopedUiProps('event', rawOpts, this); + }; + // Trigger + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.hasPublicHandlers = function (name) { + return this.hasHandlers(name) || + this.opt(name); // handler specified in options + }; + Calendar.prototype.publiclyTrigger = function (name, args) { + var optHandler = this.opt(name); + this.triggerWith(name, this, args); + if (optHandler) { + return optHandler.apply(this, args); + } + }; + Calendar.prototype.publiclyTriggerAfterSizing = function (name, args) { + var afterSizingTriggers = this.afterSizingTriggers; + (afterSizingTriggers[name] || (afterSizingTriggers[name] = [])).push(args); + }; + Calendar.prototype.releaseAfterSizingTriggers = function () { + var afterSizingTriggers = this.afterSizingTriggers; + for (var name_4 in afterSizingTriggers) { + for (var _i = 0, _a = afterSizingTriggers[name_4]; _i < _a.length; _i++) { + var args = _a[_i]; + this.publiclyTrigger(name_4, args); + } + } + this.afterSizingTriggers = {}; + }; + // View + // ----------------------------------------------------------------------------------------------------------------- + // Returns a boolean about whether the view is okay to instantiate at some point + Calendar.prototype.isValidViewType = function (viewType) { + return Boolean(this.viewSpecs[viewType]); + }; + Calendar.prototype.changeView = function (viewType, dateOrRange) { + var dateMarker = null; + if (dateOrRange) { + if (dateOrRange.start && dateOrRange.end) { // a range + this.optionsManager.mutate({ visibleRange: dateOrRange }, []); // will not rerender + this.handleOptions(this.optionsManager.computed); // ...but yuck + } + else { // a date + dateMarker = this.dateEnv.createMarker(dateOrRange); // just like gotoDate + } + } + this.unselect(); + this.dispatch({ + type: 'SET_VIEW_TYPE', + viewType: viewType, + dateMarker: dateMarker + }); + }; + // Forces navigation to a view for the given date. + // `viewType` can be a specific view name or a generic one like "week" or "day". + // needs to change + Calendar.prototype.zoomTo = function (dateMarker, viewType) { + var spec; + viewType = viewType || 'day'; // day is default zoom + spec = this.viewSpecs[viewType] || + this.getUnitViewSpec(viewType); + this.unselect(); + if (spec) { + this.dispatch({ + type: 'SET_VIEW_TYPE', + viewType: spec.type, + dateMarker: dateMarker + }); + } + else { + this.dispatch({ + type: 'SET_DATE', + dateMarker: dateMarker + }); + } + }; + // Given a duration singular unit, like "week" or "day", finds a matching view spec. + // Preference is given to views that have corresponding buttons. + Calendar.prototype.getUnitViewSpec = function (unit) { + var component = this.component; + var viewTypes = []; + var i; + var spec; + // put views that have buttons first. there will be duplicates, but oh + if (component.header) { + viewTypes.push.apply(viewTypes, component.header.viewsWithButtons); + } + if (component.footer) { + viewTypes.push.apply(viewTypes, component.footer.viewsWithButtons); + } + for (var viewType in this.viewSpecs) { + viewTypes.push(viewType); + } + for (i = 0; i < viewTypes.length; i++) { + spec = this.viewSpecs[viewTypes[i]]; + if (spec) { + if (spec.singleUnit === unit) { + return spec; + } + } + } + }; + // Current Date + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.getInitialDate = function () { + var defaultDateInput = this.opt('defaultDate'); + // compute the initial ambig-timezone date + if (defaultDateInput != null) { + return this.dateEnv.createMarker(defaultDateInput); + } + else { + return this.getNow(); // getNow already returns unzoned + } + }; + Calendar.prototype.prev = function () { + this.unselect(); + this.dispatch({ type: 'PREV' }); + }; + Calendar.prototype.next = function () { + this.unselect(); + this.dispatch({ type: 'NEXT' }); + }; + Calendar.prototype.prevYear = function () { + this.unselect(); + this.dispatch({ + type: 'SET_DATE', + dateMarker: this.dateEnv.addYears(this.state.currentDate, -1) + }); + }; + Calendar.prototype.nextYear = function () { + this.unselect(); + this.dispatch({ + type: 'SET_DATE', + dateMarker: this.dateEnv.addYears(this.state.currentDate, 1) + }); + }; + Calendar.prototype.today = function () { + this.unselect(); + this.dispatch({ + type: 'SET_DATE', + dateMarker: this.getNow() + }); + }; + Calendar.prototype.gotoDate = function (zonedDateInput) { + this.unselect(); + this.dispatch({ + type: 'SET_DATE', + dateMarker: this.dateEnv.createMarker(zonedDateInput) + }); + }; + Calendar.prototype.incrementDate = function (deltaInput) { + var delta = createDuration(deltaInput); + if (delta) { // else, warn about invalid input? + this.unselect(); + this.dispatch({ + type: 'SET_DATE', + dateMarker: this.dateEnv.add(this.state.currentDate, delta) + }); + } + }; + // for external API + Calendar.prototype.getDate = function () { + return this.dateEnv.toDate(this.state.currentDate); + }; + // Date Formatting Utils + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.formatDate = function (d, formatter) { + var dateEnv = this.dateEnv; + return dateEnv.format(dateEnv.createMarker(d), createFormatter(formatter)); + }; + // `settings` is for formatter AND isEndExclusive + Calendar.prototype.formatRange = function (d0, d1, settings) { + var dateEnv = this.dateEnv; + return dateEnv.formatRange(dateEnv.createMarker(d0), dateEnv.createMarker(d1), createFormatter(settings, this.opt('defaultRangeSeparator')), settings); + }; + Calendar.prototype.formatIso = function (d, omitTime) { + var dateEnv = this.dateEnv; + return dateEnv.formatIso(dateEnv.createMarker(d), { omitTime: omitTime }); + }; + // Sizing + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.windowResize = function (ev) { + if (!this.isHandlingWindowResize && + this.component && // why? + ev.target === window // not a jqui resize event + ) { + this.isHandlingWindowResize = true; + this.updateSize(); + this.publiclyTrigger('windowResize', [this.view]); + this.isHandlingWindowResize = false; + } + }; + Calendar.prototype.updateSize = function () { + if (this.component) { // when? + this.component.updateSize(true); + } + }; + // Component Registration + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.registerInteractiveComponent = function (component, settingsInput) { + var settings = parseInteractionSettings(component, settingsInput); + var DEFAULT_INTERACTIONS = [ + EventClicking, + EventHovering + ]; + var interactionClasses = DEFAULT_INTERACTIONS.concat(this.pluginSystem.hooks.componentInteractions); + var interactions = interactionClasses.map(function (interactionClass) { + return new interactionClass(settings); + }); + this.interactionsStore[component.uid] = interactions; + interactionSettingsStore[component.uid] = settings; + }; + Calendar.prototype.unregisterInteractiveComponent = function (component) { + for (var _i = 0, _a = this.interactionsStore[component.uid]; _i < _a.length; _i++) { + var listener = _a[_i]; + listener.destroy(); + } + delete this.interactionsStore[component.uid]; + delete interactionSettingsStore[component.uid]; + }; + // Date Selection / Event Selection / DayClick + // ----------------------------------------------------------------------------------------------------------------- + // this public method receives start/end dates in any format, with any timezone + // NOTE: args were changed from v3 + Calendar.prototype.select = function (dateOrObj, endDate) { + var selectionInput; + if (endDate == null) { + if (dateOrObj.start != null) { + selectionInput = dateOrObj; + } + else { + selectionInput = { + start: dateOrObj, + end: null + }; + } + } + else { + selectionInput = { + start: dateOrObj, + end: endDate + }; + } + var selection = parseDateSpan(selectionInput, this.dateEnv, createDuration({ days: 1 }) // TODO: cache this? + ); + if (selection) { // throw parse error otherwise? + this.dispatch({ type: 'SELECT_DATES', selection: selection }); + this.triggerDateSelect(selection); + } + }; + // public method + Calendar.prototype.unselect = function (pev) { + if (this.state.dateSelection) { + this.dispatch({ type: 'UNSELECT_DATES' }); + this.triggerDateUnselect(pev); + } + }; + Calendar.prototype.triggerDateSelect = function (selection, pev) { + var arg = __assign({}, this.buildDateSpanApi(selection), { jsEvent: pev ? pev.origEvent : null, view: this.view }); + this.publiclyTrigger('select', [arg]); + }; + Calendar.prototype.triggerDateUnselect = function (pev) { + this.publiclyTrigger('unselect', [ + { + jsEvent: pev ? pev.origEvent : null, + view: this.view + } + ]); + }; + // TODO: receive pev? + Calendar.prototype.triggerDateClick = function (dateSpan, dayEl, view, ev) { + var arg = __assign({}, this.buildDatePointApi(dateSpan), { dayEl: dayEl, jsEvent: ev, // Is this always a mouse event? See #4655 + view: view }); + this.publiclyTrigger('dateClick', [arg]); + }; + Calendar.prototype.buildDatePointApi = function (dateSpan) { + var props = {}; + for (var _i = 0, _a = this.pluginSystem.hooks.datePointTransforms; _i < _a.length; _i++) { + var transform = _a[_i]; + __assign(props, transform(dateSpan, this)); + } + __assign(props, buildDatePointApi(dateSpan, this.dateEnv)); + return props; + }; + Calendar.prototype.buildDateSpanApi = function (dateSpan) { + var props = {}; + for (var _i = 0, _a = this.pluginSystem.hooks.dateSpanTransforms; _i < _a.length; _i++) { + var transform = _a[_i]; + __assign(props, transform(dateSpan, this)); + } + __assign(props, buildDateSpanApi(dateSpan, this.dateEnv)); + return props; + }; + // Date Utils + // ----------------------------------------------------------------------------------------------------------------- + // Returns a DateMarker for the current date, as defined by the client's computer or from the `now` option + Calendar.prototype.getNow = function () { + var now = this.opt('now'); + if (typeof now === 'function') { + now = now(); + } + if (now == null) { + return this.dateEnv.createNowMarker(); + } + return this.dateEnv.createMarker(now); + }; + // Event-Date Utilities + // ----------------------------------------------------------------------------------------------------------------- + // Given an event's allDay status and start date, return what its fallback end date should be. + // TODO: rename to computeDefaultEventEnd + Calendar.prototype.getDefaultEventEnd = function (allDay, marker) { + var end = marker; + if (allDay) { + end = startOfDay(end); + end = this.dateEnv.add(end, this.defaultAllDayEventDuration); + } + else { + end = this.dateEnv.add(end, this.defaultTimedEventDuration); + } + return end; + }; + // Public Events API + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.addEvent = function (eventInput, sourceInput) { + if (eventInput instanceof EventApi) { + var def = eventInput._def; + var instance = eventInput._instance; + // not already present? don't want to add an old snapshot + if (!this.state.eventStore.defs[def.defId]) { + this.dispatch({ + type: 'ADD_EVENTS', + eventStore: eventTupleToStore({ def: def, instance: instance }) // TODO: better util for two args? + }); + } + return eventInput; + } + var sourceId; + if (sourceInput instanceof EventSourceApi) { + sourceId = sourceInput.internalEventSource.sourceId; + } + else if (sourceInput != null) { + var sourceApi = this.getEventSourceById(sourceInput); // TODO: use an internal function + if (!sourceApi) { + console.warn('Could not find an event source with ID "' + sourceInput + '"'); // TODO: test + return null; + } + else { + sourceId = sourceApi.internalEventSource.sourceId; + } + } + var tuple = parseEvent(eventInput, sourceId, this); + if (tuple) { + this.dispatch({ + type: 'ADD_EVENTS', + eventStore: eventTupleToStore(tuple) + }); + return new EventApi(this, tuple.def, tuple.def.recurringDef ? null : tuple.instance); + } + return null; + }; + // TODO: optimize + Calendar.prototype.getEventById = function (id) { + var _a = this.state.eventStore, defs = _a.defs, instances = _a.instances; + id = String(id); + for (var defId in defs) { + var def = defs[defId]; + if (def.publicId === id) { + if (def.recurringDef) { + return new EventApi(this, def, null); + } + else { + for (var instanceId in instances) { + var instance = instances[instanceId]; + if (instance.defId === def.defId) { + return new EventApi(this, def, instance); + } + } + } + } + } + return null; + }; + Calendar.prototype.getEvents = function () { + var _a = this.state.eventStore, defs = _a.defs, instances = _a.instances; + var eventApis = []; + for (var id in instances) { + var instance = instances[id]; + var def = defs[instance.defId]; + eventApis.push(new EventApi(this, def, instance)); + } + return eventApis; + }; + Calendar.prototype.removeAllEvents = function () { + this.dispatch({ type: 'REMOVE_ALL_EVENTS' }); + }; + Calendar.prototype.rerenderEvents = function () { + this.dispatch({ type: 'RESET_EVENTS' }); + }; + // Public Event Sources API + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.getEventSources = function () { + var sourceHash = this.state.eventSources; + var sourceApis = []; + for (var internalId in sourceHash) { + sourceApis.push(new EventSourceApi(this, sourceHash[internalId])); + } + return sourceApis; + }; + Calendar.prototype.getEventSourceById = function (id) { + var sourceHash = this.state.eventSources; + id = String(id); + for (var sourceId in sourceHash) { + if (sourceHash[sourceId].publicId === id) { + return new EventSourceApi(this, sourceHash[sourceId]); + } + } + return null; + }; + Calendar.prototype.addEventSource = function (sourceInput) { + if (sourceInput instanceof EventSourceApi) { + // not already present? don't want to add an old snapshot + if (!this.state.eventSources[sourceInput.internalEventSource.sourceId]) { + this.dispatch({ + type: 'ADD_EVENT_SOURCES', + sources: [sourceInput.internalEventSource] + }); + } + return sourceInput; + } + var eventSource = parseEventSource(sourceInput, this); + if (eventSource) { // TODO: error otherwise? + this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: [eventSource] }); + return new EventSourceApi(this, eventSource); + } + return null; + }; + Calendar.prototype.removeAllEventSources = function () { + this.dispatch({ type: 'REMOVE_ALL_EVENT_SOURCES' }); + }; + Calendar.prototype.refetchEvents = function () { + this.dispatch({ type: 'FETCH_EVENT_SOURCES' }); + }; + // Scroll + // ----------------------------------------------------------------------------------------------------------------- + Calendar.prototype.scrollToTime = function (timeInput) { + var duration = createDuration(timeInput); + if (duration) { + this.component.view.scrollToDuration(duration); + } + }; + return Calendar; + }()); + EmitterMixin.mixInto(Calendar); + // for memoizers + // ----------------------------------------------------------------------------------------------------------------- + function buildDateEnv(locale, timeZone, namedTimeZoneImpl, firstDay, weekNumberCalculation, weekLabel, cmdFormatter) { + return new DateEnv({ + calendarSystem: 'gregory', + timeZone: timeZone, + namedTimeZoneImpl: namedTimeZoneImpl, + locale: locale, + weekNumberCalculation: weekNumberCalculation, + firstDay: firstDay, + weekLabel: weekLabel, + cmdFormatter: cmdFormatter + }); + } + function buildTheme(calendarOptions) { + var themeClass = this.pluginSystem.hooks.themeClasses[calendarOptions.themeSystem] || StandardTheme; + return new themeClass(calendarOptions); + } + function buildDelayedRerender(wait) { + var func = this.tryRerender.bind(this); + if (wait != null) { + func = debounce(func, wait); + } + return func; + } + function buildEventUiBySource(eventSources) { + return mapHash(eventSources, function (eventSource) { + return eventSource.ui; + }); + } + function buildEventUiBases(eventDefs, eventUiSingleBase, eventUiBySource) { + var eventUiBases = { '': eventUiSingleBase }; + for (var defId in eventDefs) { + var def = eventDefs[defId]; + if (def.sourceId && eventUiBySource[def.sourceId]) { + eventUiBases[defId] = eventUiBySource[def.sourceId]; + } + } + return eventUiBases; + } + + var View = /** @class */ (function (_super) { + __extends(View, _super); + function View(context, viewSpec, dateProfileGenerator, parentEl) { + var _this = _super.call(this, context, createElement('div', { className: 'fc-view fc-' + viewSpec.type + '-view' }), true // isView (HACK) + ) || this; + _this.renderDatesMem = memoizeRendering(_this.renderDatesWrap, _this.unrenderDatesWrap); + _this.renderBusinessHoursMem = memoizeRendering(_this.renderBusinessHours, _this.unrenderBusinessHours, [_this.renderDatesMem]); + _this.renderDateSelectionMem = memoizeRendering(_this.renderDateSelectionWrap, _this.unrenderDateSelectionWrap, [_this.renderDatesMem]); + _this.renderEventsMem = memoizeRendering(_this.renderEvents, _this.unrenderEvents, [_this.renderDatesMem]); + _this.renderEventSelectionMem = memoizeRendering(_this.renderEventSelectionWrap, _this.unrenderEventSelectionWrap, [_this.renderEventsMem]); + _this.renderEventDragMem = memoizeRendering(_this.renderEventDragWrap, _this.unrenderEventDragWrap, [_this.renderDatesMem]); + _this.renderEventResizeMem = memoizeRendering(_this.renderEventResizeWrap, _this.unrenderEventResizeWrap, [_this.renderDatesMem]); + _this.viewSpec = viewSpec; + _this.dateProfileGenerator = dateProfileGenerator; + _this.type = viewSpec.type; + _this.eventOrderSpecs = parseFieldSpecs(_this.opt('eventOrder')); + _this.nextDayThreshold = createDuration(_this.opt('nextDayThreshold')); + parentEl.appendChild(_this.el); + _this.initialize(); + return _this; + } + View.prototype.initialize = function () { + }; + Object.defineProperty(View.prototype, "activeStart", { + // Date Setting/Unsetting + // ----------------------------------------------------------------------------------------------------------------- + get: function () { + return this.dateEnv.toDate(this.props.dateProfile.activeRange.start); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(View.prototype, "activeEnd", { + get: function () { + return this.dateEnv.toDate(this.props.dateProfile.activeRange.end); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(View.prototype, "currentStart", { + get: function () { + return this.dateEnv.toDate(this.props.dateProfile.currentRange.start); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(View.prototype, "currentEnd", { + get: function () { + return this.dateEnv.toDate(this.props.dateProfile.currentRange.end); + }, + enumerable: true, + configurable: true + }); + // General Rendering + // ----------------------------------------------------------------------------------------------------------------- + View.prototype.render = function (props) { + this.renderDatesMem(props.dateProfile); + this.renderBusinessHoursMem(props.businessHours); + this.renderDateSelectionMem(props.dateSelection); + this.renderEventsMem(props.eventStore); + this.renderEventSelectionMem(props.eventSelection); + this.renderEventDragMem(props.eventDrag); + this.renderEventResizeMem(props.eventResize); + }; + View.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.renderDatesMem.unrender(); // should unrender everything else + }; + // Sizing + // ----------------------------------------------------------------------------------------------------------------- + View.prototype.updateSize = function (isResize, viewHeight, isAuto) { + var calendar = this.calendar; + if (isResize || // HACKS... + calendar.isViewUpdated || + calendar.isDatesUpdated || + calendar.isEventsUpdated) { + // sort of the catch-all sizing + // anything that might cause dimension changes + this.updateBaseSize(isResize, viewHeight, isAuto); + } + }; + View.prototype.updateBaseSize = function (isResize, viewHeight, isAuto) { + }; + // Date Rendering + // ----------------------------------------------------------------------------------------------------------------- + View.prototype.renderDatesWrap = function (dateProfile) { + this.renderDates(dateProfile); + this.addScroll({ + duration: createDuration(this.opt('scrollTime')) + }); + this.startNowIndicator(dateProfile); // shouldn't render yet because updateSize will be called soon + }; + View.prototype.unrenderDatesWrap = function () { + this.stopNowIndicator(); + this.unrenderDates(); + }; + View.prototype.renderDates = function (dateProfile) { }; + View.prototype.unrenderDates = function () { }; + // Business Hours + // ----------------------------------------------------------------------------------------------------------------- + View.prototype.renderBusinessHours = function (businessHours) { }; + View.prototype.unrenderBusinessHours = function () { }; + // Date Selection + // ----------------------------------------------------------------------------------------------------------------- + View.prototype.renderDateSelectionWrap = function (selection) { + if (selection) { + this.renderDateSelection(selection); + } + }; + View.prototype.unrenderDateSelectionWrap = function (selection) { + if (selection) { + this.unrenderDateSelection(selection); + } + }; + View.prototype.renderDateSelection = function (selection) { }; + View.prototype.unrenderDateSelection = function (selection) { }; + // Event Rendering + // ----------------------------------------------------------------------------------------------------------------- + View.prototype.renderEvents = function (eventStore) { }; + View.prototype.unrenderEvents = function () { }; + // util for subclasses + View.prototype.sliceEvents = function (eventStore, allDay) { + var props = this.props; + return sliceEventStore(eventStore, props.eventUiBases, props.dateProfile.activeRange, allDay ? this.nextDayThreshold : null).fg; + }; + View.prototype.computeEventDraggable = function (eventDef, eventUi) { + var transformers = this.calendar.pluginSystem.hooks.isDraggableTransformers; + var val = eventUi.startEditable; + for (var _i = 0, transformers_1 = transformers; _i < transformers_1.length; _i++) { + var transformer = transformers_1[_i]; + val = transformer(val, eventDef, eventUi, this); + } + return val; + }; + View.prototype.computeEventStartResizable = function (eventDef, eventUi) { + return eventUi.durationEditable && this.opt('eventResizableFromStart'); + }; + View.prototype.computeEventEndResizable = function (eventDef, eventUi) { + return eventUi.durationEditable; + }; + // Event Selection + // ----------------------------------------------------------------------------------------------------------------- + View.prototype.renderEventSelectionWrap = function (instanceId) { + if (instanceId) { + this.renderEventSelection(instanceId); + } + }; + View.prototype.unrenderEventSelectionWrap = function (instanceId) { + if (instanceId) { + this.unrenderEventSelection(instanceId); + } + }; + View.prototype.renderEventSelection = function (instanceId) { }; + View.prototype.unrenderEventSelection = function (instanceId) { }; + // Event Drag + // ----------------------------------------------------------------------------------------------------------------- + View.prototype.renderEventDragWrap = function (state) { + if (state) { + this.renderEventDrag(state); + } + }; + View.prototype.unrenderEventDragWrap = function (state) { + if (state) { + this.unrenderEventDrag(state); + } + }; + View.prototype.renderEventDrag = function (state) { }; + View.prototype.unrenderEventDrag = function (state) { }; + // Event Resize + // ----------------------------------------------------------------------------------------------------------------- + View.prototype.renderEventResizeWrap = function (state) { + if (state) { + this.renderEventResize(state); + } + }; + View.prototype.unrenderEventResizeWrap = function (state) { + if (state) { + this.unrenderEventResize(state); + } + }; + View.prototype.renderEventResize = function (state) { }; + View.prototype.unrenderEventResize = function (state) { }; + /* Now Indicator + ------------------------------------------------------------------------------------------------------------------*/ + // Immediately render the current time indicator and begins re-rendering it at an interval, + // which is defined by this.getNowIndicatorUnit(). + // TODO: somehow do this for the current whole day's background too + View.prototype.startNowIndicator = function (dateProfile) { + var _this = this; + var dateEnv = this.dateEnv; + var unit; + var update; + var delay; // ms wait value + if (this.opt('nowIndicator')) { + unit = this.getNowIndicatorUnit(dateProfile); + if (unit) { + update = this.updateNowIndicator.bind(this); + this.initialNowDate = this.calendar.getNow(); + this.initialNowQueriedMs = new Date().valueOf(); + // wait until the beginning of the next interval + delay = dateEnv.add(dateEnv.startOf(this.initialNowDate, unit), createDuration(1, unit)).valueOf() - this.initialNowDate.valueOf(); + // TODO: maybe always use setTimeout, waiting until start of next unit + this.nowIndicatorTimeoutID = setTimeout(function () { + _this.nowIndicatorTimeoutID = null; + update(); + if (unit === 'second') { + delay = 1000; // every second + } + else { + delay = 1000 * 60; // otherwise, every minute + } + _this.nowIndicatorIntervalID = setInterval(update, delay); // update every interval + }, delay); + } + // rendering will be initiated in updateSize + } + }; + // rerenders the now indicator, computing the new current time from the amount of time that has passed + // since the initial getNow call. + View.prototype.updateNowIndicator = function () { + if (this.props.dateProfile && // a way to determine if dates were rendered yet + this.initialNowDate // activated before? + ) { + this.unrenderNowIndicator(); // won't unrender if unnecessary + this.renderNowIndicator(addMs(this.initialNowDate, new Date().valueOf() - this.initialNowQueriedMs)); + this.isNowIndicatorRendered = true; + } + }; + // Immediately unrenders the view's current time indicator and stops any re-rendering timers. + // Won't cause side effects if indicator isn't rendered. + View.prototype.stopNowIndicator = function () { + if (this.isNowIndicatorRendered) { + if (this.nowIndicatorTimeoutID) { + clearTimeout(this.nowIndicatorTimeoutID); + this.nowIndicatorTimeoutID = null; + } + if (this.nowIndicatorIntervalID) { + clearInterval(this.nowIndicatorIntervalID); + this.nowIndicatorIntervalID = null; + } + this.unrenderNowIndicator(); + this.isNowIndicatorRendered = false; + } + }; + View.prototype.getNowIndicatorUnit = function (dateProfile) { + // subclasses should implement + }; + // Renders a current time indicator at the given datetime + View.prototype.renderNowIndicator = function (date) { + // SUBCLASSES MUST PASS TO CHILDREN! + }; + // Undoes the rendering actions from renderNowIndicator + View.prototype.unrenderNowIndicator = function () { + // SUBCLASSES MUST PASS TO CHILDREN! + }; + /* Scroller + ------------------------------------------------------------------------------------------------------------------*/ + View.prototype.addScroll = function (scroll) { + var queuedScroll = this.queuedScroll || (this.queuedScroll = {}); + __assign(queuedScroll, scroll); + }; + View.prototype.popScroll = function (isResize) { + this.applyQueuedScroll(isResize); + this.queuedScroll = null; + }; + View.prototype.applyQueuedScroll = function (isResize) { + this.applyScroll(this.queuedScroll || {}, isResize); + }; + View.prototype.queryScroll = function () { + var scroll = {}; + if (this.props.dateProfile) { // dates rendered yet? + __assign(scroll, this.queryDateScroll()); + } + return scroll; + }; + View.prototype.applyScroll = function (scroll, isResize) { + var duration = scroll.duration; + if (duration != null) { + delete scroll.duration; + if (this.props.dateProfile) { // dates rendered yet? + __assign(scroll, this.computeDateScroll(duration)); + } + } + if (this.props.dateProfile) { // dates rendered yet? + this.applyDateScroll(scroll); + } + }; + View.prototype.computeDateScroll = function (duration) { + return {}; // subclasses must implement + }; + View.prototype.queryDateScroll = function () { + return {}; // subclasses must implement + }; + View.prototype.applyDateScroll = function (scroll) { + // subclasses must implement + }; + // for API + View.prototype.scrollToDuration = function (duration) { + this.applyScroll({ duration: duration }, false); + }; + return View; + }(DateComponent)); + EmitterMixin.mixInto(View); + View.prototype.usesMinMaxTime = false; + View.prototype.dateProfileGeneratorClass = DateProfileGenerator; + + var FgEventRenderer = /** @class */ (function () { + function FgEventRenderer(context) { + this.segs = []; + this.isSizeDirty = false; + this.context = context; + } + FgEventRenderer.prototype.renderSegs = function (segs, mirrorInfo) { + this.rangeUpdated(); // called too frequently :( + // render an `.el` on each seg + // returns a subset of the segs. segs that were actually rendered + segs = this.renderSegEls(segs, mirrorInfo); + this.segs = segs; + this.attachSegs(segs, mirrorInfo); + this.isSizeDirty = true; + this.context.view.triggerRenderedSegs(this.segs, Boolean(mirrorInfo)); + }; + FgEventRenderer.prototype.unrender = function (_segs, mirrorInfo) { + this.context.view.triggerWillRemoveSegs(this.segs, Boolean(mirrorInfo)); + this.detachSegs(this.segs); + this.segs = []; + }; + // Updates values that rely on options and also relate to range + FgEventRenderer.prototype.rangeUpdated = function () { + var options = this.context.options; + var displayEventTime; + var displayEventEnd; + this.eventTimeFormat = createFormatter(options.eventTimeFormat || this.computeEventTimeFormat(), options.defaultRangeSeparator); + displayEventTime = options.displayEventTime; + if (displayEventTime == null) { + displayEventTime = this.computeDisplayEventTime(); // might be based off of range + } + displayEventEnd = options.displayEventEnd; + if (displayEventEnd == null) { + displayEventEnd = this.computeDisplayEventEnd(); // might be based off of range + } + this.displayEventTime = displayEventTime; + this.displayEventEnd = displayEventEnd; + }; + // Renders and assigns an `el` property for each foreground event segment. + // Only returns segments that successfully rendered. + FgEventRenderer.prototype.renderSegEls = function (segs, mirrorInfo) { + var html = ''; + var i; + if (segs.length) { // don't build an empty html string + // build a large concatenation of event segment HTML + for (i = 0; i < segs.length; i++) { + html += this.renderSegHtml(segs[i], mirrorInfo); + } + // Grab individual elements from the combined HTML string. Use each as the default rendering. + // Then, compute the 'el' for each segment. An el might be null if the eventRender callback returned false. + htmlToElements(html).forEach(function (el, i) { + var seg = segs[i]; + if (el) { + seg.el = el; + } + }); + segs = filterSegsViaEls(this.context.view, segs, Boolean(mirrorInfo)); + } + return segs; + }; + // Generic utility for generating the HTML classNames for an event segment's element + FgEventRenderer.prototype.getSegClasses = function (seg, isDraggable, isResizable, mirrorInfo) { + var classes = [ + 'fc-event', + seg.isStart ? 'fc-start' : 'fc-not-start', + seg.isEnd ? 'fc-end' : 'fc-not-end' + ].concat(seg.eventRange.ui.classNames); + if (isDraggable) { + classes.push('fc-draggable'); + } + if (isResizable) { + classes.push('fc-resizable'); + } + if (mirrorInfo) { + classes.push('fc-mirror'); + if (mirrorInfo.isDragging) { + classes.push('fc-dragging'); + } + if (mirrorInfo.isResizing) { + classes.push('fc-resizing'); + } + } + return classes; + }; + // Compute the text that should be displayed on an event's element. + // `range` can be the Event object itself, or something range-like, with at least a `start`. + // If event times are disabled, or the event has no time, will return a blank string. + // If not specified, formatter will default to the eventTimeFormat setting, + // and displayEnd will default to the displayEventEnd setting. + FgEventRenderer.prototype.getTimeText = function (eventRange, formatter, displayEnd) { + var def = eventRange.def, instance = eventRange.instance; + return this._getTimeText(instance.range.start, def.hasEnd ? instance.range.end : null, def.allDay, formatter, displayEnd, instance.forcedStartTzo, instance.forcedEndTzo); + }; + FgEventRenderer.prototype._getTimeText = function (start, end, allDay, formatter, displayEnd, forcedStartTzo, forcedEndTzo) { + var dateEnv = this.context.dateEnv; + if (formatter == null) { + formatter = this.eventTimeFormat; + } + if (displayEnd == null) { + displayEnd = this.displayEventEnd; + } + if (this.displayEventTime && !allDay) { + if (displayEnd && end) { + return dateEnv.formatRange(start, end, formatter, { + forcedStartTzo: forcedStartTzo, + forcedEndTzo: forcedEndTzo + }); + } + else { + return dateEnv.format(start, formatter, { + forcedTzo: forcedStartTzo + }); + } + } + return ''; + }; + FgEventRenderer.prototype.computeEventTimeFormat = function () { + return { + hour: 'numeric', + minute: '2-digit', + omitZeroMinute: true + }; + }; + FgEventRenderer.prototype.computeDisplayEventTime = function () { + return true; + }; + FgEventRenderer.prototype.computeDisplayEventEnd = function () { + return true; + }; + // Utility for generating event skin-related CSS properties + FgEventRenderer.prototype.getSkinCss = function (ui) { + return { + 'background-color': ui.backgroundColor, + 'border-color': ui.borderColor, + color: ui.textColor + }; + }; + FgEventRenderer.prototype.sortEventSegs = function (segs) { + var specs = this.context.view.eventOrderSpecs; + var objs = segs.map(buildSegCompareObj); + objs.sort(function (obj0, obj1) { + return compareByFieldSpecs(obj0, obj1, specs); + }); + return objs.map(function (c) { + return c._seg; + }); + }; + FgEventRenderer.prototype.computeSizes = function (force) { + if (force || this.isSizeDirty) { + this.computeSegSizes(this.segs); + } + }; + FgEventRenderer.prototype.assignSizes = function (force) { + if (force || this.isSizeDirty) { + this.assignSegSizes(this.segs); + this.isSizeDirty = false; + } + }; + FgEventRenderer.prototype.computeSegSizes = function (segs) { + }; + FgEventRenderer.prototype.assignSegSizes = function (segs) { + }; + // Manipulation on rendered segs + FgEventRenderer.prototype.hideByHash = function (hash) { + if (hash) { + for (var _i = 0, _a = this.segs; _i < _a.length; _i++) { + var seg = _a[_i]; + if (hash[seg.eventRange.instance.instanceId]) { + seg.el.style.visibility = 'hidden'; + } + } + } + }; + FgEventRenderer.prototype.showByHash = function (hash) { + if (hash) { + for (var _i = 0, _a = this.segs; _i < _a.length; _i++) { + var seg = _a[_i]; + if (hash[seg.eventRange.instance.instanceId]) { + seg.el.style.visibility = ''; + } + } + } + }; + FgEventRenderer.prototype.selectByInstanceId = function (instanceId) { + if (instanceId) { + for (var _i = 0, _a = this.segs; _i < _a.length; _i++) { + var seg = _a[_i]; + var eventInstance = seg.eventRange.instance; + if (eventInstance && eventInstance.instanceId === instanceId && + seg.el // necessary? + ) { + seg.el.classList.add('fc-selected'); + } + } + } + }; + FgEventRenderer.prototype.unselectByInstanceId = function (instanceId) { + if (instanceId) { + for (var _i = 0, _a = this.segs; _i < _a.length; _i++) { + var seg = _a[_i]; + if (seg.el) { // necessary? + seg.el.classList.remove('fc-selected'); + } + } + } + }; + return FgEventRenderer; + }()); + // returns a object with all primitive props that can be compared + function buildSegCompareObj(seg) { + var eventDef = seg.eventRange.def; + var range = seg.eventRange.instance.range; + var start = range.start ? range.start.valueOf() : 0; // TODO: better support for open-range events + var end = range.end ? range.end.valueOf() : 0; // " + return __assign({}, eventDef.extendedProps, eventDef, { id: eventDef.publicId, start: start, + end: end, duration: end - start, allDay: Number(eventDef.allDay), _seg: seg // for later retrieval + }); + } + + var FillRenderer = /** @class */ (function () { + function FillRenderer(context) { + this.fillSegTag = 'div'; + this.dirtySizeFlags = {}; + this.context = context; + this.containerElsByType = {}; + this.segsByType = {}; + } + FillRenderer.prototype.getSegsByType = function (type) { + return this.segsByType[type] || []; + }; + FillRenderer.prototype.renderSegs = function (type, segs) { + var _a; + var renderedSegs = this.renderSegEls(type, segs); // assignes `.el` to each seg. returns successfully rendered segs + var containerEls = this.attachSegs(type, renderedSegs); + if (containerEls) { + (_a = (this.containerElsByType[type] || (this.containerElsByType[type] = []))).push.apply(_a, containerEls); + } + this.segsByType[type] = renderedSegs; + if (type === 'bgEvent') { + this.context.view.triggerRenderedSegs(renderedSegs, false); // isMirror=false + } + this.dirtySizeFlags[type] = true; + }; + // Unrenders a specific type of fill that is currently rendered on the grid + FillRenderer.prototype.unrender = function (type) { + var segs = this.segsByType[type]; + if (segs) { + if (type === 'bgEvent') { + this.context.view.triggerWillRemoveSegs(segs, false); // isMirror=false + } + this.detachSegs(type, segs); + } + }; + // Renders and assigns an `el` property for each fill segment. Generic enough to work with different types. + // Only returns segments that successfully rendered. + FillRenderer.prototype.renderSegEls = function (type, segs) { + var _this = this; + var html = ''; + var i; + if (segs.length) { + // build a large concatenation of segment HTML + for (i = 0; i < segs.length; i++) { + html += this.renderSegHtml(type, segs[i]); + } + // Grab individual elements from the combined HTML string. Use each as the default rendering. + // Then, compute the 'el' for each segment. + htmlToElements(html).forEach(function (el, i) { + var seg = segs[i]; + if (el) { + seg.el = el; + } + }); + if (type === 'bgEvent') { + segs = filterSegsViaEls(this.context.view, segs, false // isMirror. background events can never be mirror elements + ); + } + // correct element type? (would be bad if a non-TD were inserted into a table for example) + segs = segs.filter(function (seg) { + return elementMatches(seg.el, _this.fillSegTag); + }); + } + return segs; + }; + // Builds the HTML needed for one fill segment. Generic enough to work with different types. + FillRenderer.prototype.renderSegHtml = function (type, seg) { + var css = null; + var classNames = []; + if (type !== 'highlight' && type !== 'businessHours') { + css = { + 'background-color': seg.eventRange.ui.backgroundColor + }; + } + if (type !== 'highlight') { + classNames = classNames.concat(seg.eventRange.ui.classNames); + } + if (type === 'businessHours') { + classNames.push('fc-bgevent'); + } + else { + classNames.push('fc-' + type.toLowerCase()); + } + return '<' + this.fillSegTag + + (classNames.length ? ' class="' + classNames.join(' ') + '"' : '') + + (css ? ' style="' + cssToStr(css) + '"' : '') + + '></' + this.fillSegTag + '>'; + }; + FillRenderer.prototype.detachSegs = function (type, segs) { + var containerEls = this.containerElsByType[type]; + if (containerEls) { + containerEls.forEach(removeElement); + delete this.containerElsByType[type]; + } + }; + FillRenderer.prototype.computeSizes = function (force) { + for (var type in this.segsByType) { + if (force || this.dirtySizeFlags[type]) { + this.computeSegSizes(this.segsByType[type]); + } + } + }; + FillRenderer.prototype.assignSizes = function (force) { + for (var type in this.segsByType) { + if (force || this.dirtySizeFlags[type]) { + this.assignSegSizes(this.segsByType[type]); + } + } + this.dirtySizeFlags = {}; + }; + FillRenderer.prototype.computeSegSizes = function (segs) { + }; + FillRenderer.prototype.assignSegSizes = function (segs) { + }; + return FillRenderer; + }()); + + var NamedTimeZoneImpl = /** @class */ (function () { + function NamedTimeZoneImpl(timeZoneName) { + this.timeZoneName = timeZoneName; + } + return NamedTimeZoneImpl; + }()); + + /* + An abstraction for a dragging interaction originating on an event. + Does higher-level things than PointerDragger, such as possibly: + - a "mirror" that moves with the pointer + - a minimum number of pixels or other criteria for a true drag to begin + + subclasses must emit: + - pointerdown + - dragstart + - dragmove + - pointerup + - dragend + */ + var ElementDragging = /** @class */ (function () { + function ElementDragging(el) { + this.emitter = new EmitterMixin(); + } + ElementDragging.prototype.destroy = function () { + }; + ElementDragging.prototype.setMirrorIsVisible = function (bool) { + // optional if subclass doesn't want to support a mirror + }; + ElementDragging.prototype.setMirrorNeedsRevert = function (bool) { + // optional if subclass doesn't want to support a mirror + }; + ElementDragging.prototype.setAutoScrollEnabled = function (bool) { + // optional + }; + return ElementDragging; + }()); + + function formatDate(dateInput, settings) { + if (settings === void 0) { settings = {}; } + var dateEnv = buildDateEnv$1(settings); + var formatter = createFormatter(settings); + var dateMeta = dateEnv.createMarkerMeta(dateInput); + if (!dateMeta) { // TODO: warning? + return ''; + } + return dateEnv.format(dateMeta.marker, formatter, { + forcedTzo: dateMeta.forcedTzo + }); + } + function formatRange(startInput, endInput, settings // mixture of env and formatter settings + ) { + var dateEnv = buildDateEnv$1(typeof settings === 'object' && settings ? settings : {}); // pass in if non-null object + var formatter = createFormatter(settings, globalDefaults.defaultRangeSeparator); + var startMeta = dateEnv.createMarkerMeta(startInput); + var endMeta = dateEnv.createMarkerMeta(endInput); + if (!startMeta || !endMeta) { // TODO: warning? + return ''; + } + return dateEnv.formatRange(startMeta.marker, endMeta.marker, formatter, { + forcedStartTzo: startMeta.forcedTzo, + forcedEndTzo: endMeta.forcedTzo, + isEndExclusive: settings.isEndExclusive + }); + } + // TODO: more DRY and optimized + function buildDateEnv$1(settings) { + var locale = buildLocale(settings.locale || 'en', parseRawLocales([]).map); // TODO: don't hardcode 'en' everywhere + // ensure required settings + settings = __assign({ timeZone: globalDefaults.timeZone, calendarSystem: 'gregory' }, settings, { locale: locale }); + return new DateEnv(settings); + } + + var DRAG_META_PROPS = { + startTime: createDuration, + duration: createDuration, + create: Boolean, + sourceId: String + }; + var DRAG_META_DEFAULTS = { + create: true + }; + function parseDragMeta(raw) { + var leftoverProps = {}; + var refined = refineProps(raw, DRAG_META_PROPS, DRAG_META_DEFAULTS, leftoverProps); + refined.leftoverProps = leftoverProps; + return refined; + } + + // Computes a default column header formatting string if `colFormat` is not explicitly defined + function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) { + // if more than one week row, or if there are a lot of columns with not much space, + // put just the day numbers will be in each cell + if (!datesRepDistinctDays || dayCnt > 10) { + return { weekday: 'short' }; // "Sat" + } + else if (dayCnt > 1) { + return { weekday: 'short', month: 'numeric', day: 'numeric', omitCommas: true }; // "Sat 11/12" + } + else { + return { weekday: 'long' }; // "Saturday" + } + } + function renderDateCell(dateMarker, dateProfile, datesRepDistinctDays, colCnt, colHeadFormat, context, colspan, otherAttrs) { + var view = context.view, dateEnv = context.dateEnv, theme = context.theme, options = context.options; + var isDateValid = rangeContainsMarker(dateProfile.activeRange, dateMarker); // TODO: called too frequently. cache somehow. + var classNames = [ + 'fc-day-header', + theme.getClass('widgetHeader') + ]; + var innerHtml; + if (typeof options.columnHeaderHtml === 'function') { + innerHtml = options.columnHeaderHtml(dateEnv.toDate(dateMarker)); + } + else if (typeof options.columnHeaderText === 'function') { + innerHtml = htmlEscape(options.columnHeaderText(dateEnv.toDate(dateMarker))); + } + else { + innerHtml = htmlEscape(dateEnv.format(dateMarker, colHeadFormat)); + } + // if only one row of days, the classNames on the header can represent the specific days beneath + if (datesRepDistinctDays) { + classNames = classNames.concat( + // includes the day-of-week class + // noThemeHighlight=true (don't highlight the header) + getDayClasses(dateMarker, dateProfile, context, true)); + } + else { + classNames.push('fc-' + DAY_IDS[dateMarker.getUTCDay()]); // only add the day-of-week class + } + return '' + + '<th class="' + classNames.join(' ') + '"' + + ((isDateValid && datesRepDistinctDays) ? + ' data-date="' + dateEnv.formatIso(dateMarker, { omitTime: true }) + '"' : + '') + + (colspan > 1 ? + ' colspan="' + colspan + '"' : + '') + + (otherAttrs ? + ' ' + otherAttrs : + '') + + '>' + + (isDateValid ? + // don't make a link if the heading could represent multiple days, or if there's only one day (forceOff) + buildGotoAnchorHtml(view, { date: dateMarker, forceOff: !datesRepDistinctDays || colCnt === 1 }, innerHtml) : + // if not valid, display text, but no link + innerHtml) + + '</th>'; + } + + var DayHeader = /** @class */ (function (_super) { + __extends(DayHeader, _super); + function DayHeader(context, parentEl) { + var _this = _super.call(this, context) || this; + parentEl.innerHTML = ''; // because might be nbsp + parentEl.appendChild(_this.el = htmlToElement('<div class="fc-row ' + _this.theme.getClass('headerRow') + '">' + + '<table class="' + _this.theme.getClass('tableGrid') + '">' + + '<thead></thead>' + + '</table>' + + '</div>')); + _this.thead = _this.el.querySelector('thead'); + return _this; + } + DayHeader.prototype.destroy = function () { + removeElement(this.el); + }; + DayHeader.prototype.render = function (props) { + var dates = props.dates, datesRepDistinctDays = props.datesRepDistinctDays; + var parts = []; + if (props.renderIntroHtml) { + parts.push(props.renderIntroHtml()); + } + var colHeadFormat = createFormatter(this.opt('columnHeaderFormat') || + computeFallbackHeaderFormat(datesRepDistinctDays, dates.length)); + for (var _i = 0, dates_1 = dates; _i < dates_1.length; _i++) { + var date = dates_1[_i]; + parts.push(renderDateCell(date, props.dateProfile, datesRepDistinctDays, dates.length, colHeadFormat, this.context)); + } + if (this.isRtl) { + parts.reverse(); + } + this.thead.innerHTML = '<tr>' + parts.join('') + '</tr>'; + }; + return DayHeader; + }(Component)); + + var DaySeries = /** @class */ (function () { + function DaySeries(range, dateProfileGenerator) { + var date = range.start; + var end = range.end; + var indices = []; + var dates = []; + var dayIndex = -1; + while (date < end) { // loop each day from start to end + if (dateProfileGenerator.isHiddenDay(date)) { + indices.push(dayIndex + 0.5); // mark that it's between indices + } + else { + dayIndex++; + indices.push(dayIndex); + dates.push(date); + } + date = addDays(date, 1); + } + this.dates = dates; + this.indices = indices; + this.cnt = dates.length; + } + DaySeries.prototype.sliceRange = function (range) { + var firstIndex = this.getDateDayIndex(range.start); // inclusive first index + var lastIndex = this.getDateDayIndex(addDays(range.end, -1)); // inclusive last index + var clippedFirstIndex = Math.max(0, firstIndex); + var clippedLastIndex = Math.min(this.cnt - 1, lastIndex); + // deal with in-between indices + clippedFirstIndex = Math.ceil(clippedFirstIndex); // in-between starts round to next cell + clippedLastIndex = Math.floor(clippedLastIndex); // in-between ends round to prev cell + if (clippedFirstIndex <= clippedLastIndex) { + return { + firstIndex: clippedFirstIndex, + lastIndex: clippedLastIndex, + isStart: firstIndex === clippedFirstIndex, + isEnd: lastIndex === clippedLastIndex + }; + } + else { + return null; + } + }; + // Given a date, returns its chronolocial cell-index from the first cell of the grid. + // If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets. + // If before the first offset, returns a negative number. + // If after the last offset, returns an offset past the last cell offset. + // Only works for *start* dates of cells. Will not work for exclusive end dates for cells. + DaySeries.prototype.getDateDayIndex = function (date) { + var indices = this.indices; + var dayOffset = Math.floor(diffDays(this.dates[0], date)); + if (dayOffset < 0) { + return indices[0] - 1; + } + else if (dayOffset >= indices.length) { + return indices[indices.length - 1] + 1; + } + else { + return indices[dayOffset]; + } + }; + return DaySeries; + }()); + + var DayTable = /** @class */ (function () { + function DayTable(daySeries, breakOnWeeks) { + var dates = daySeries.dates; + var daysPerRow; + var firstDay; + var rowCnt; + if (breakOnWeeks) { + // count columns until the day-of-week repeats + firstDay = dates[0].getUTCDay(); + for (daysPerRow = 1; daysPerRow < dates.length; daysPerRow++) { + if (dates[daysPerRow].getUTCDay() === firstDay) { + break; + } + } + rowCnt = Math.ceil(dates.length / daysPerRow); + } + else { + rowCnt = 1; + daysPerRow = dates.length; + } + this.rowCnt = rowCnt; + this.colCnt = daysPerRow; + this.daySeries = daySeries; + this.cells = this.buildCells(); + this.headerDates = this.buildHeaderDates(); + } + DayTable.prototype.buildCells = function () { + var rows = []; + for (var row = 0; row < this.rowCnt; row++) { + var cells = []; + for (var col = 0; col < this.colCnt; col++) { + cells.push(this.buildCell(row, col)); + } + rows.push(cells); + } + return rows; + }; + DayTable.prototype.buildCell = function (row, col) { + return { + date: this.daySeries.dates[row * this.colCnt + col] + }; + }; + DayTable.prototype.buildHeaderDates = function () { + var dates = []; + for (var col = 0; col < this.colCnt; col++) { + dates.push(this.cells[0][col].date); + } + return dates; + }; + DayTable.prototype.sliceRange = function (range) { + var colCnt = this.colCnt; + var seriesSeg = this.daySeries.sliceRange(range); + var segs = []; + if (seriesSeg) { + var firstIndex = seriesSeg.firstIndex, lastIndex = seriesSeg.lastIndex; + var index = firstIndex; + while (index <= lastIndex) { + var row = Math.floor(index / colCnt); + var nextIndex = Math.min((row + 1) * colCnt, lastIndex + 1); + segs.push({ + row: row, + firstCol: index % colCnt, + lastCol: (nextIndex - 1) % colCnt, + isStart: seriesSeg.isStart && index === firstIndex, + isEnd: seriesSeg.isEnd && (nextIndex - 1) === lastIndex + }); + index = nextIndex; + } + } + return segs; + }; + return DayTable; + }()); + + var Slicer = /** @class */ (function () { + function Slicer() { + this.sliceBusinessHours = memoize(this._sliceBusinessHours); + this.sliceDateSelection = memoize(this._sliceDateSpan); + this.sliceEventStore = memoize(this._sliceEventStore); + this.sliceEventDrag = memoize(this._sliceInteraction); + this.sliceEventResize = memoize(this._sliceInteraction); + } + Slicer.prototype.sliceProps = function (props, dateProfile, nextDayThreshold, component) { + var extraArgs = []; + for (var _i = 4; _i < arguments.length; _i++) { + extraArgs[_i - 4] = arguments[_i]; + } + var eventUiBases = props.eventUiBases; + var eventSegs = this.sliceEventStore.apply(this, [props.eventStore, eventUiBases, dateProfile, nextDayThreshold, component].concat(extraArgs)); + return { + dateSelectionSegs: this.sliceDateSelection.apply(this, [props.dateSelection, eventUiBases, component].concat(extraArgs)), + businessHourSegs: this.sliceBusinessHours.apply(this, [props.businessHours, dateProfile, nextDayThreshold, component].concat(extraArgs)), + fgEventSegs: eventSegs.fg, + bgEventSegs: eventSegs.bg, + eventDrag: this.sliceEventDrag.apply(this, [props.eventDrag, eventUiBases, dateProfile, nextDayThreshold, component].concat(extraArgs)), + eventResize: this.sliceEventResize.apply(this, [props.eventResize, eventUiBases, dateProfile, nextDayThreshold, component].concat(extraArgs)), + eventSelection: props.eventSelection + }; // TODO: give interactionSegs? + }; + Slicer.prototype.sliceNowDate = function (// does not memoize + date, component) { + var extraArgs = []; + for (var _i = 2; _i < arguments.length; _i++) { + extraArgs[_i - 2] = arguments[_i]; + } + return this._sliceDateSpan.apply(this, [{ range: { start: date, end: addMs(date, 1) }, allDay: false }, + {}, + component].concat(extraArgs)); + }; + Slicer.prototype._sliceBusinessHours = function (businessHours, dateProfile, nextDayThreshold, component) { + var extraArgs = []; + for (var _i = 4; _i < arguments.length; _i++) { + extraArgs[_i - 4] = arguments[_i]; + } + if (!businessHours) { + return []; + } + return this._sliceEventStore.apply(this, [expandRecurring(businessHours, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), component.calendar), + {}, + dateProfile, + nextDayThreshold, + component].concat(extraArgs)).bg; + }; + Slicer.prototype._sliceEventStore = function (eventStore, eventUiBases, dateProfile, nextDayThreshold, component) { + var extraArgs = []; + for (var _i = 5; _i < arguments.length; _i++) { + extraArgs[_i - 5] = arguments[_i]; + } + if (eventStore) { + var rangeRes = sliceEventStore(eventStore, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold); + return { + bg: this.sliceEventRanges(rangeRes.bg, component, extraArgs), + fg: this.sliceEventRanges(rangeRes.fg, component, extraArgs) + }; + } + else { + return { bg: [], fg: [] }; + } + }; + Slicer.prototype._sliceInteraction = function (interaction, eventUiBases, dateProfile, nextDayThreshold, component) { + var extraArgs = []; + for (var _i = 5; _i < arguments.length; _i++) { + extraArgs[_i - 5] = arguments[_i]; + } + if (!interaction) { + return null; + } + var rangeRes = sliceEventStore(interaction.mutatedEvents, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold); + return { + segs: this.sliceEventRanges(rangeRes.fg, component, extraArgs), + affectedInstances: interaction.affectedEvents.instances, + isEvent: interaction.isEvent, + sourceSeg: interaction.origSeg + }; + }; + Slicer.prototype._sliceDateSpan = function (dateSpan, eventUiBases, component) { + var extraArgs = []; + for (var _i = 3; _i < arguments.length; _i++) { + extraArgs[_i - 3] = arguments[_i]; + } + if (!dateSpan) { + return []; + } + var eventRange = fabricateEventRange(dateSpan, eventUiBases, component.calendar); + var segs = this.sliceRange.apply(this, [dateSpan.range].concat(extraArgs)); + for (var _a = 0, segs_1 = segs; _a < segs_1.length; _a++) { + var seg = segs_1[_a]; + seg.component = component; + seg.eventRange = eventRange; + } + return segs; + }; + /* + "complete" seg means it has component and eventRange + */ + Slicer.prototype.sliceEventRanges = function (eventRanges, component, // TODO: kill + extraArgs) { + var segs = []; + for (var _i = 0, eventRanges_1 = eventRanges; _i < eventRanges_1.length; _i++) { + var eventRange = eventRanges_1[_i]; + segs.push.apply(segs, this.sliceEventRange(eventRange, component, extraArgs)); + } + return segs; + }; + /* + "complete" seg means it has component and eventRange + */ + Slicer.prototype.sliceEventRange = function (eventRange, component, // TODO: kill + extraArgs) { + var segs = this.sliceRange.apply(this, [eventRange.range].concat(extraArgs)); + for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { + var seg = segs_2[_i]; + seg.component = component; + seg.eventRange = eventRange; + seg.isStart = eventRange.isStart && seg.isStart; + seg.isEnd = eventRange.isEnd && seg.isEnd; + } + return segs; + }; + return Slicer; + }()); + /* + for incorporating minTime/maxTime if appropriate + TODO: should be part of DateProfile! + TimelineDateProfile already does this btw + */ + function computeActiveRange(dateProfile, isComponentAllDay) { + var range = dateProfile.activeRange; + if (isComponentAllDay) { + return range; + } + return { + start: addMs(range.start, dateProfile.minTime.milliseconds), + end: addMs(range.end, dateProfile.maxTime.milliseconds - 864e5) // 864e5 = ms in a day + }; + } + + // exports + // -------------------------------------------------------------------------------------------------- + var version = '4.3.1'; + + exports.Calendar = Calendar; + exports.Component = Component; + exports.DateComponent = DateComponent; + exports.DateEnv = DateEnv; + exports.DateProfileGenerator = DateProfileGenerator; + exports.DayHeader = DayHeader; + exports.DaySeries = DaySeries; + exports.DayTable = DayTable; + exports.ElementDragging = ElementDragging; + exports.ElementScrollController = ElementScrollController; + exports.EmitterMixin = EmitterMixin; + exports.EventApi = EventApi; + exports.FgEventRenderer = FgEventRenderer; + exports.FillRenderer = FillRenderer; + exports.Interaction = Interaction; + exports.Mixin = Mixin; + exports.NamedTimeZoneImpl = NamedTimeZoneImpl; + exports.PositionCache = PositionCache; + exports.ScrollComponent = ScrollComponent; + exports.ScrollController = ScrollController; + exports.Slicer = Slicer; + exports.Splitter = Splitter; + exports.Theme = Theme; + exports.View = View; + exports.WindowScrollController = WindowScrollController; + exports.addDays = addDays; + exports.addDurations = addDurations; + exports.addMs = addMs; + exports.addWeeks = addWeeks; + exports.allowContextMenu = allowContextMenu; + exports.allowSelection = allowSelection; + exports.appendToElement = appendToElement; + exports.applyAll = applyAll; + exports.applyMutationToEventStore = applyMutationToEventStore; + exports.applyStyle = applyStyle; + exports.applyStyleProp = applyStyleProp; + exports.asRoughMinutes = asRoughMinutes; + exports.asRoughMs = asRoughMs; + exports.asRoughSeconds = asRoughSeconds; + exports.buildGotoAnchorHtml = buildGotoAnchorHtml; + exports.buildSegCompareObj = buildSegCompareObj; + exports.capitaliseFirstLetter = capitaliseFirstLetter; + exports.combineEventUis = combineEventUis; + exports.compareByFieldSpec = compareByFieldSpec; + exports.compareByFieldSpecs = compareByFieldSpecs; + exports.compareNumbers = compareNumbers; + exports.compensateScroll = compensateScroll; + exports.computeClippingRect = computeClippingRect; + exports.computeEdges = computeEdges; + exports.computeFallbackHeaderFormat = computeFallbackHeaderFormat; + exports.computeHeightAndMargins = computeHeightAndMargins; + exports.computeInnerRect = computeInnerRect; + exports.computeRect = computeRect; + exports.computeVisibleDayRange = computeVisibleDayRange; + exports.config = config; + exports.constrainPoint = constrainPoint; + exports.createDuration = createDuration; + exports.createElement = createElement; + exports.createEmptyEventStore = createEmptyEventStore; + exports.createEventInstance = createEventInstance; + exports.createFormatter = createFormatter; + exports.createPlugin = createPlugin; + exports.cssToStr = cssToStr; + exports.debounce = debounce; + exports.diffDates = diffDates; + exports.diffDayAndTime = diffDayAndTime; + exports.diffDays = diffDays; + exports.diffPoints = diffPoints; + exports.diffWeeks = diffWeeks; + exports.diffWholeDays = diffWholeDays; + exports.diffWholeWeeks = diffWholeWeeks; + exports.disableCursor = disableCursor; + exports.distributeHeight = distributeHeight; + exports.elementClosest = elementClosest; + exports.elementMatches = elementMatches; + exports.enableCursor = enableCursor; + exports.eventTupleToStore = eventTupleToStore; + exports.filterEventStoreDefs = filterEventStoreDefs; + exports.filterHash = filterHash; + exports.findChildren = findChildren; + exports.findElements = findElements; + exports.flexibleCompare = flexibleCompare; + exports.forceClassName = forceClassName; + exports.formatDate = formatDate; + exports.formatIsoTimeString = formatIsoTimeString; + exports.formatRange = formatRange; + exports.getAllDayHtml = getAllDayHtml; + exports.getClippingParents = getClippingParents; + exports.getDayClasses = getDayClasses; + exports.getElSeg = getElSeg; + exports.getRectCenter = getRectCenter; + exports.getRelevantEvents = getRelevantEvents; + exports.globalDefaults = globalDefaults; + exports.greatestDurationDenominator = greatestDurationDenominator; + exports.hasBgRendering = hasBgRendering; + exports.htmlEscape = htmlEscape; + exports.htmlToElement = htmlToElement; + exports.insertAfterElement = insertAfterElement; + exports.interactionSettingsStore = interactionSettingsStore; + exports.interactionSettingsToStore = interactionSettingsToStore; + exports.intersectRanges = intersectRanges; + exports.intersectRects = intersectRects; + exports.isArraysEqual = isArraysEqual; + exports.isDateSpansEqual = isDateSpansEqual; + exports.isInt = isInt; + exports.isInteractionValid = isInteractionValid; + exports.isMultiDayRange = isMultiDayRange; + exports.isPropsEqual = isPropsEqual; + exports.isPropsValid = isPropsValid; + exports.isSingleDay = isSingleDay; + exports.isValidDate = isValidDate; + exports.listenBySelector = listenBySelector; + exports.mapHash = mapHash; + exports.matchCellWidths = matchCellWidths; + exports.memoize = memoize; + exports.memoizeOutput = memoizeOutput; + exports.memoizeRendering = memoizeRendering; + exports.mergeEventStores = mergeEventStores; + exports.multiplyDuration = multiplyDuration; + exports.padStart = padStart; + exports.parseBusinessHours = parseBusinessHours; + exports.parseDragMeta = parseDragMeta; + exports.parseEventDef = parseEventDef; + exports.parseFieldSpecs = parseFieldSpecs; + exports.parseMarker = parse; + exports.pointInsideRect = pointInsideRect; + exports.prependToElement = prependToElement; + exports.preventContextMenu = preventContextMenu; + exports.preventDefault = preventDefault; + exports.preventSelection = preventSelection; + exports.processScopedUiProps = processScopedUiProps; + exports.rangeContainsMarker = rangeContainsMarker; + exports.rangeContainsRange = rangeContainsRange; + exports.rangesEqual = rangesEqual; + exports.rangesIntersect = rangesIntersect; + exports.refineProps = refineProps; + exports.removeElement = removeElement; + exports.removeExact = removeExact; + exports.renderDateCell = renderDateCell; + exports.requestJson = requestJson; + exports.sliceEventStore = sliceEventStore; + exports.startOfDay = startOfDay; + exports.subtractInnerElHeight = subtractInnerElHeight; + exports.translateRect = translateRect; + exports.uncompensateScroll = uncompensateScroll; + exports.undistributeHeight = undistributeHeight; + exports.unpromisify = unpromisify; + exports.version = version; + exports.whenTransitionDone = whenTransitionDone; + exports.wholeDivideDurations = wholeDivideDurations; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/core/main.min.css b/AKPlan/static/AKPlan/fullcalendar/core/main.min.css new file mode 100644 index 00000000..8948b534 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/main.min.css @@ -0,0 +1 @@ +@charset "UTF-8";.fc-button:not(:disabled),.fc-event.fc-draggable,.fc-event[href],.fc-popover .fc-header .fc-close,a.fc-more,a[data-goto]{cursor:pointer}.fc-bg,.fc-row .fc-bgevent-skeleton,.fc-row .fc-highlight-skeleton{bottom:0}.fc{direction:ltr;text-align:left}.fc-rtl{text-align:right}body .fc{font-size:1em}.fc-highlight{background:#bce8f1;opacity:.3}.fc-bgevent{background:#8fdf82;opacity:.3}.fc-nonbusiness{background:#d7d7d7}.fc-popover{position:absolute;box-shadow:0 2px 6px rgba(0,0,0,.15)}.fc-popover .fc-header{display:flex;flex-direction:row;justify-content:space-between;align-items:center;padding:2px 4px}.fc-rtl .fc-popover .fc-header{flex-direction:row-reverse}.fc-popover .fc-header .fc-title{margin:0 2px}.fc-popover .fc-header .fc-close{opacity:.65;font-size:1.1em}.fc-divider{border-style:solid;border-width:1px}hr.fc-divider{height:0;margin:0;padding:0 0 2px;border-width:1px 0}.fc-bg table,.fc-row .fc-bgevent-skeleton table,.fc-row .fc-highlight-skeleton table{height:100%}.fc-bg,.fc-bgevent-skeleton,.fc-highlight-skeleton,.fc-mirror-skeleton{position:absolute;top:0;left:0;right:0}.fc table{width:100%;box-sizing:border-box;table-layout:fixed;border-collapse:collapse;border-spacing:0;font-size:1em}.fc th{text-align:center}.fc td,.fc th{border-style:solid;border-width:1px;padding:0;vertical-align:top}.fc td.fc-today{border-style:double}a[data-goto]:hover{text-decoration:underline}.fc .fc-row{border-style:solid;border-width:0}.fc-row table{border-left:0 hidden transparent;border-right:0 hidden transparent;border-bottom:0 hidden transparent}.fc-row:first-child table{border-top:0 hidden transparent}.fc-row{position:relative}.fc-row .fc-bg{z-index:1}.fc-row .fc-bgevent-skeleton td,.fc-row .fc-highlight-skeleton td{border-color:transparent}.fc-row .fc-bgevent-skeleton{z-index:2}.fc-row .fc-highlight-skeleton{z-index:3}.fc-row .fc-content-skeleton{position:relative;z-index:4;padding-bottom:2px}.fc-row .fc-mirror-skeleton{z-index:5}.fc .fc-row .fc-content-skeleton table,.fc .fc-row .fc-content-skeleton td,.fc .fc-row .fc-mirror-skeleton td{background:0 0;border-color:transparent}.fc-row .fc-content-skeleton td,.fc-row .fc-mirror-skeleton td{border-bottom:0}.fc-row .fc-content-skeleton tbody td,.fc-row .fc-mirror-skeleton tbody td{border-top:0}.fc-scroller{-webkit-overflow-scrolling:touch}.fc-scroller>.fc-day-grid,.fc-scroller>.fc-time-grid{position:relative;width:100%}.fc-event{position:relative;display:block;font-size:.85em;line-height:1.4;border-radius:3px;border:1px solid #3788d8}.fc-event,.fc-event-dot{background-color:#3788d8}.fc-event,.fc-event:hover{color:#fff;text-decoration:none}.fc-not-allowed,.fc-not-allowed .fc-event{cursor:not-allowed}.fc-event .fc-content{position:relative;z-index:2}.fc-event .fc-resizer{position:absolute;z-index:4;display:none}.fc-event.fc-allow-mouse-resize .fc-resizer,.fc-event.fc-selected .fc-resizer{display:block}.fc-event.fc-selected .fc-resizer:before{content:"";position:absolute;z-index:9999;top:50%;left:50%;width:40px;height:40px;margin-left:-20px;margin-top:-20px}.fc-event.fc-selected{z-index:9999!important;box-shadow:0 2px 5px rgba(0,0,0,.2)}.fc-event.fc-selected:after{content:"";position:absolute;z-index:1;top:-1px;right:-1px;bottom:-1px;left:-1px;background:#000;opacity:.25}.fc-event.fc-dragging.fc-selected{box-shadow:0 2px 7px rgba(0,0,0,.3)}.fc-event.fc-dragging:not(.fc-selected){opacity:.75}.fc-h-event.fc-selected:before{content:"";position:absolute;z-index:3;top:-10px;bottom:-10px;left:0;right:0}.fc-ltr .fc-h-event.fc-not-start,.fc-rtl .fc-h-event.fc-not-end{margin-left:0;border-left-width:0;padding-left:1px;border-top-left-radius:0;border-bottom-left-radius:0}.fc-ltr .fc-h-event.fc-not-end,.fc-rtl .fc-h-event.fc-not-start{margin-right:0;border-right-width:0;padding-right:1px;border-top-right-radius:0;border-bottom-right-radius:0}.fc-ltr .fc-h-event .fc-start-resizer,.fc-rtl .fc-h-event .fc-end-resizer{cursor:w-resize;left:-1px}.fc-ltr .fc-h-event .fc-end-resizer,.fc-rtl .fc-h-event .fc-start-resizer{cursor:e-resize;right:-1px}.fc-h-event.fc-allow-mouse-resize .fc-resizer{width:7px;top:-1px;bottom:-1px}.fc-h-event.fc-selected .fc-resizer{border-radius:4px;border-width:1px;width:6px;height:6px;border-style:solid;border-color:inherit;background:#fff;top:50%;margin-top:-4px}.fc-ltr .fc-h-event.fc-selected .fc-start-resizer,.fc-rtl .fc-h-event.fc-selected .fc-end-resizer{margin-left:-4px}.fc-ltr .fc-h-event.fc-selected .fc-end-resizer,.fc-rtl .fc-h-event.fc-selected .fc-start-resizer{margin-right:-4px}.fc-day-grid-event{margin:1px 2px 0;padding:0 1px}tr:first-child>td>.fc-day-grid-event{margin-top:2px}.fc-mirror-skeleton tr:first-child>td>.fc-day-grid-event{margin-top:0}.fc-day-grid-event .fc-content{white-space:nowrap;overflow:hidden}.fc-day-grid-event .fc-time{font-weight:700}.fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer,.fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer{margin-left:-2px}.fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer,.fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer{margin-right:-2px}a.fc-more{margin:1px 3px;font-size:.85em;text-decoration:none}a.fc-more:hover{text-decoration:underline}.fc-limited{display:none}.fc-button,.fc-icon{display:inline-block;font-weight:400;text-align:center}.fc-day-grid .fc-row{z-index:1}.fc-more-popover{z-index:2;width:220px}.fc-more-popover .fc-event-container{padding:10px}.fc-now-indicator{position:absolute;border:0 solid red}.fc-unselectable{-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent}.fc-unthemed .fc-content,.fc-unthemed .fc-divider,.fc-unthemed .fc-list-heading td,.fc-unthemed .fc-list-view,.fc-unthemed .fc-popover,.fc-unthemed .fc-row,.fc-unthemed tbody,.fc-unthemed td,.fc-unthemed th,.fc-unthemed thead{border-color:#ddd}.fc-unthemed .fc-popover{background-color:#fff}.fc-unthemed .fc-divider,.fc-unthemed .fc-list-heading td,.fc-unthemed .fc-popover .fc-header{background:#eee}.fc-unthemed td.fc-today{background:#fcf8e3}.fc-unthemed .fc-disabled-day{background:#d7d7d7;opacity:.3}@font-face{font-family:fcicons;src:url("data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SBfAAAAC8AAAAYGNtYXAXVtKNAAABHAAAAFRnYXNwAAAAEAAAAXAAAAAIZ2x5ZgYydxIAAAF4AAAFNGhlYWQUJ7cIAAAGrAAAADZoaGVhB20DzAAABuQAAAAkaG10eCIABhQAAAcIAAAALGxvY2ED4AU6AAAHNAAAABhtYXhwAA8AjAAAB0wAAAAgbmFtZXsr690AAAdsAAABhnBvc3QAAwAAAAAI9AAAACAAAwPAAZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADpBgPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAADAAAAAwAAABwAAQADAAAAHAADAAEAAAAcAAQAOAAAAAoACAACAAIAAQAg6Qb//f//AAAAAAAg6QD//f//AAH/4xcEAAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAABAWIAjQKeAskAEwAAJSc3NjQnJiIHAQYUFwEWMjc2NCcCnuLiDQ0MJAz/AA0NAQAMJAwNDcni4gwjDQwM/wANIwz/AA0NDCMNAAAAAQFiAI0CngLJABMAACUBNjQnASYiBwYUHwEHBhQXFjI3AZ4BAA0N/wAMJAwNDeLiDQ0MJAyNAQAMIw0BAAwMDSMM4uINIwwNDQAAAAIA4gC3Ax4CngATACcAACUnNzY0JyYiDwEGFB8BFjI3NjQnISc3NjQnJiIPAQYUHwEWMjc2NCcB87e3DQ0MIw3VDQ3VDSMMDQ0BK7e3DQ0MJAzVDQ3VDCQMDQ3zuLcMJAwNDdUNIwzWDAwNIwy4twwkDA0N1Q0jDNYMDA0jDAAAAgDiALcDHgKeABMAJwAAJTc2NC8BJiIHBhQfAQcGFBcWMjchNzY0LwEmIgcGFB8BBwYUFxYyNwJJ1Q0N1Q0jDA0Nt7cNDQwjDf7V1Q0N1QwkDA0Nt7cNDQwkDLfWDCMN1Q0NDCQMt7gMIw0MDNYMIw3VDQ0MJAy3uAwjDQwMAAADAFUAAAOrA1UAMwBoAHcAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMhMjY1NCYjISIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAAVYRGRkR/qoRGRkRA1UFBAUOCQkVDAsZDf2rDRkLDBUJCA4FBQUFBQUOCQgVDAsZDQJVDRkLDBUJCQ4FBAVVAgECBQMCBwQECAX9qwQJAwQHAwMFAQICAgIBBQMDBwQDCQQCVQUIBAQHAgMFAgEC/oAZEhEZGRESGQAAAAADAFUAAAOrA1UAMwBoAIkAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMzFRQWMzI2PQEzMjY1NCYrATU0JiMiBh0BIyIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAgBkSEhmAERkZEYAZEhIZgBEZGREDVQUEBQ4JCRUMCxkN/asNGQsMFQkIDgUFBQUFBQ4JCBUMCxkNAlUNGQsMFQkJDgUEBVUCAQIFAwIHBAQIBf2rBAkDBAcDAwUBAgICAgEFAwMHBAMJBAJVBQgEBAcCAwUCAQL+gIASGRkSgBkSERmAEhkZEoAZERIZAAABAOIAjQMeAskAIAAAExcHBhQXFjI/ARcWMjc2NC8BNzY0JyYiDwEnJiIHBhQX4uLiDQ0MJAzi4gwkDA0N4uINDQwkDOLiDCQMDQ0CjeLiDSMMDQ3h4Q0NDCMN4uIMIw0MDOLiDAwNIwwAAAABAAAAAQAAa5n0y18PPPUACwQAAAAAANivOVsAAAAA2K85WwAAAAADqwNVAAAACAACAAAAAAAAAAEAAAPA/8AAAAQAAAAAAAOrAAEAAAAAAAAAAAAAAAAAAAALBAAAAAAAAAAAAAAAAgAAAAQAAWIEAAFiBAAA4gQAAOIEAABVBAAAVQQAAOIAAAAAAAoAFAAeAEQAagCqAOoBngJkApoAAQAAAAsAigADAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA4ArgABAAAAAAABAAcAAAABAAAAAAACAAcAYAABAAAAAAADAAcANgABAAAAAAAEAAcAdQABAAAAAAAFAAsAFQABAAAAAAAGAAcASwABAAAAAAAKABoAigADAAEECQABAA4ABwADAAEECQACAA4AZwADAAEECQADAA4APQADAAEECQAEAA4AfAADAAEECQAFABYAIAADAAEECQAGAA4AUgADAAEECQAKADQApGZjaWNvbnMAZgBjAGkAYwBvAG4Ac1ZlcnNpb24gMS4wAFYAZQByAHMAaQBvAG4AIAAxAC4AMGZjaWNvbnMAZgBjAGkAYwBvAG4Ac2ZjaWNvbnMAZgBjAGkAYwBvAG4Ac1JlZ3VsYXIAUgBlAGcAdQBsAGEAcmZjaWNvbnMAZgBjAGkAYwBvAG4Ac0ZvbnQgZ2VuZXJhdGVkIGJ5IEljb01vb24uAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") format("truetype");font-weight:400;font-style:normal}.fc-icon{font-family:fcicons!important;speak:none;font-style:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;width:1em;height:1em}.fc-icon-chevron-left:before{content:""}.fc-icon-chevron-right:before{content:"î¤"}.fc-icon-chevrons-left:before{content:""}.fc-icon-chevrons-right:before{content:""}.fc-icon-minus-square:before{content:""}.fc-icon-plus-square:before{content:""}.fc-icon-x:before{content:""}.fc-button{overflow:visible;text-transform:none;margin:0;font-family:inherit}.fc-button::-moz-focus-inner{padding:0;border-style:none}.fc-button{-webkit-appearance:button;color:#212529;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.4em .65em;font-size:1em;line-height:1.5;border-radius:.25em}.fc-button:hover{color:#212529;text-decoration:none}.fc-button:focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(44,62,80,.25);box-shadow:0 0 0 .2rem rgba(44,62,80,.25)}.fc-button:disabled{opacity:.65}.fc-button-primary{color:#fff;background-color:#2C3E50;border-color:#2C3E50}.fc-button-primary:hover{color:#fff;background-color:#1e2b37;border-color:#1a252f}.fc-button-primary:focus{-webkit-box-shadow:0 0 0 .2rem rgba(76,91,106,.5);box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc-button-primary:disabled{color:#fff;background-color:#2C3E50;border-color:#2C3E50}.fc-button-primary:not(:disabled).fc-button-active,.fc-button-primary:not(:disabled):active{color:#fff;background-color:#1a252f;border-color:#151e27}.fc-button-primary:not(:disabled).fc-button-active:focus,.fc-button-primary:not(:disabled):active:focus{-webkit-box-shadow:0 0 0 .2rem rgba(76,91,106,.5);box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc-button .fc-icon{vertical-align:middle;font-size:1.5em}.fc-button-group{position:relative;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.fc-button-group>.fc-button{position:relative;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.fc-button-group>.fc-button.fc-button-active,.fc-button-group>.fc-button:active,.fc-button-group>.fc-button:focus,.fc-button-group>.fc-button:hover{z-index:1}.fc-button-group>.fc-button:not(:first-child){margin-left:-1px;border-top-left-radius:0;border-bottom-left-radius:0}.fc-button-group>.fc-button:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.fc-unthemed .fc-popover{border-width:1px;border-style:solid}.fc-unthemed .fc-list-item:hover td{background-color:#f5f5f5}.fc-toolbar{display:flex;justify-content:space-between;align-items:center}.fc-toolbar.fc-header-toolbar{margin-bottom:1.5em}.fc-toolbar.fc-footer-toolbar{margin-top:1.5em}.fc-toolbar>*>:not(:first-child){margin-left:.75em}.fc-toolbar h2{font-size:1.75em;margin:0}.fc-view-container{position:relative}.fc-view-container *,.fc-view-container :after,.fc-view-container :before{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.fc-view,.fc-view>table{position:relative;z-index:1}@media print{.fc-bg,.fc-bgevent-container,.fc-bgevent-skeleton,.fc-business-container,.fc-event .fc-resizer,.fc-highlight-container,.fc-highlight-skeleton,.fc-mirror-container,.fc-mirror-skeleton{display:none}.fc tbody .fc-row,.fc-time-grid{min-height:0!important}.fc-time-grid .fc-event.fc-not-end:after,.fc-time-grid .fc-event.fc-not-start:before{content:"..."}.fc{max-width:100%!important}.fc-event{background:#fff!important;color:#000!important;page-break-inside:avoid}.fc hr,.fc tbody,.fc td,.fc th,.fc thead,.fc-row{border-color:#ccc!important;background:#fff!important}.fc tbody .fc-row{height:auto!important}.fc tbody .fc-row .fc-content-skeleton{position:static;padding-bottom:0!important}.fc tbody .fc-row .fc-content-skeleton tbody tr:last-child td{padding-bottom:1em}.fc tbody .fc-row .fc-content-skeleton table{height:1em}.fc-more,.fc-more-cell{display:none!important}.fc tr.fc-limited{display:table-row!important}.fc td.fc-limited{display:table-cell!important}.fc-popover,.fc-timeGrid-view .fc-axis{display:none}.fc-slats,.fc-time-grid hr{display:none!important}.fc button,.fc-button-group,.fc-time-grid .fc-event .fc-time span{display:none}.fc-time-grid .fc-content-skeleton{position:static}.fc-time-grid .fc-content-skeleton table{height:4em}.fc-time-grid .fc-event-container{margin:0!important}.fc-time-grid .fc-event{position:static!important;margin:3px 2px!important}.fc-time-grid .fc-event.fc-not-end{border-bottom-width:1px!important}.fc-time-grid .fc-event.fc-not-start{border-top-width:1px!important}.fc-time-grid .fc-event .fc-time{white-space:normal!important}.fc-time-grid .fc-event .fc-time:after{content:attr(data-full)}.fc-day-grid-container,.fc-scroller,.fc-time-grid-container{overflow:visible!important;height:auto!important}.fc-row{border:0!important;margin:0!important}} \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/core/main.min.js b/AKPlan/static/AKPlan/fullcalendar/core/main.min.js new file mode 100644 index 00000000..6b72fff6 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/main.min.js @@ -0,0 +1,6 @@ +/*! +FullCalendar Core Package v4.3.1 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e=e||self).FullCalendar={})}(this,function(e){"use strict";var t={className:!0,colSpan:!0,rowSpan:!0},n={"<tr":"tbody","<td":"tr"};function r(e,n,r){var i=document.createElement(e);if(n)for(var o in n)"style"===o?y(i,n[o]):t[o]?i[o]=n[o]:i.setAttribute(o,n[o]);return"string"==typeof r?i.innerHTML=r:null!=r&&s(i,r),i}function i(e){e=e.trim();var t=document.createElement(a(e));return t.innerHTML=e,t.firstChild}function o(e){return Array.prototype.slice.call(function(e){e=e.trim();var t=document.createElement(a(e));return t.innerHTML=e,t.childNodes}(e))}function a(e){return n[e.substr(0,3)]||"div"}function s(e,t){for(var n=l(t),r=0;r<n.length;r++)e.appendChild(n[r])}function u(e,t){for(var n=l(t),r=e.firstChild||null,i=0;i<n.length;i++)e.insertBefore(n[i],r)}function l(e){return"string"==typeof e?o(e):e instanceof Node?[e]:Array.prototype.slice.call(e)}function c(e){e.parentNode&&e.parentNode.removeChild(e)}var d=Element.prototype.matches||Element.prototype.matchesSelector||Element.prototype.msMatchesSelector,f=Element.prototype.closest||function(e){var t=this;if(!document.documentElement.contains(t))return null;do{if(h(t,e))return t;t=t.parentElement||t.parentNode}while(null!==t&&1===t.nodeType);return null};function p(e,t){return f.call(e,t)}function h(e,t){return d.call(e,t)}function v(e,t){for(var n=e instanceof HTMLElement?[e]:e,r=[],i=0;i<n.length;i++)for(var o=n[i].querySelectorAll(t),a=0;a<o.length;a++)r.push(o[a]);return r}var g=/(top|left|right|bottom|width|height)$/i;function y(e,t){for(var n in t)m(e,n,t[n])}function m(e,t,n){null==n?e.style[t]="":"number"==typeof n&&g.test(t)?e.style[t]=n+"px":e.style[t]=n}function E(e,t){var n={left:Math.max(e.left,t.left),right:Math.min(e.right,t.right),top:Math.max(e.top,t.top),bottom:Math.min(e.bottom,t.bottom)};return n.left<n.right&&n.top<n.bottom&&n}var S=null;function b(){return null===S&&(S=function(){var e=r("div",{style:{position:"absolute",top:-1e3,left:0,border:0,padding:0,overflow:"scroll",direction:"rtl"}},"<div></div>");document.body.appendChild(e);var t=e.firstChild.getBoundingClientRect().left>e.getBoundingClientRect().left;return c(e),t}()),S}function D(e){return e=Math.max(0,e),e=Math.round(e)}function T(e,t){void 0===t&&(t=!1);var n=window.getComputedStyle(e),r=parseInt(n.borderLeftWidth,10)||0,i=parseInt(n.borderRightWidth,10)||0,o=parseInt(n.borderTopWidth,10)||0,a=parseInt(n.borderBottomWidth,10)||0,s=D(e.offsetWidth-e.clientWidth-r-i),u={borderLeft:r,borderRight:i,borderTop:o,borderBottom:a,scrollbarBottom:D(e.offsetHeight-e.clientHeight-o-a),scrollbarLeft:0,scrollbarRight:0};return b()&&"rtl"===n.direction?u.scrollbarLeft=s:u.scrollbarRight=s,t&&(u.paddingLeft=parseInt(n.paddingLeft,10)||0,u.paddingRight=parseInt(n.paddingRight,10)||0,u.paddingTop=parseInt(n.paddingTop,10)||0,u.paddingBottom=parseInt(n.paddingBottom,10)||0),u}function w(e,t){void 0===t&&(t=!1);var n=R(e),r=T(e,t),i={left:n.left+r.borderLeft+r.scrollbarLeft,right:n.right-r.borderRight-r.scrollbarRight,top:n.top+r.borderTop,bottom:n.bottom-r.borderBottom-r.scrollbarBottom};return t&&(i.left+=r.paddingLeft,i.right-=r.paddingRight,i.top+=r.paddingTop,i.bottom-=r.paddingBottom),i}function R(e){var t=e.getBoundingClientRect();return{left:t.left+window.pageXOffset,top:t.top+window.pageYOffset,right:t.right+window.pageXOffset,bottom:t.bottom+window.pageYOffset}}function I(e){return e.getBoundingClientRect().height+C(e)}function C(e){var t=window.getComputedStyle(e);return parseInt(t.marginTop,10)+parseInt(t.marginBottom,10)}function M(e){for(var t=[];e instanceof HTMLElement;){var n=window.getComputedStyle(e);if("fixed"===n.position)break;/(auto|scroll)/.test(n.overflow+n.overflowY+n.overflowX)&&t.push(e),e=e.parentNode}return t}function k(e){e.preventDefault()}function O(e,t,n,r){function i(e){var t=p(e.target,n);t&&r.call(t,e,t)}return e.addEventListener(t,i),function(){e.removeEventListener(t,i)}}var _=["webkitTransitionEnd","otransitionend","oTransitionEnd","msTransitionEnd","transitionend"];var P=["sun","mon","tue","wed","thu","fri","sat"];function x(e,t){var n=Z(e);return n[2]+=t,j(n)}function H(e,t){var n=Z(e);return n[6]+=t,j(n)}function N(e,t){return(t.valueOf()-e.valueOf())/864e5}function z(e,t){var n=B(e),r=B(t);return{years:0,months:0,days:Math.round(N(n,r)),milliseconds:t.valueOf()-r.valueOf()-(e.valueOf()-n.valueOf())}}function U(e,t){var n=L(e,t);return null!==n&&n%7==0?n/7:null}function L(e,t){return q(e)===q(t)?Math.round(N(e,t)):null}function B(e){return j([e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()])}function V(e,t,n,r){var i=j([t,0,1+A(t,n,r)]),o=B(e),a=Math.round(N(i,o));return Math.floor(a/7)+1}function A(e,t,n){var r=7+t-n;return-((7+j([e,0,r]).getUTCDay()-t)%7)+r-1}function F(e){return[e.getFullYear(),e.getMonth(),e.getDate(),e.getHours(),e.getMinutes(),e.getSeconds(),e.getMilliseconds()]}function W(e){return new Date(e[0],e[1]||0,null==e[2]?1:e[2],e[3]||0,e[4]||0,e[5]||0)}function Z(e){return[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours(),e.getUTCMinutes(),e.getUTCSeconds(),e.getUTCMilliseconds()]}function j(e){return 1===e.length&&(e=e.concat([0])),new Date(Date.UTC.apply(Date,e))}function Y(e){return!isNaN(e.valueOf())}function q(e){return 1e3*e.getUTCHours()*60*60+1e3*e.getUTCMinutes()*60+1e3*e.getUTCSeconds()+e.getUTCMilliseconds()}var G=["years","months","days","milliseconds"],X=/^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/;function J(e,t){var n;return"string"==typeof e?function(e){var t=X.exec(e);if(t){var n=t[1]?-1:1;return{years:0,months:0,days:n*(t[2]?parseInt(t[2],10):0),milliseconds:n*(60*(t[3]?parseInt(t[3],10):0)*60*1e3+60*(t[4]?parseInt(t[4],10):0)*1e3+1e3*(t[5]?parseInt(t[5],10):0)+(t[6]?parseInt(t[6],10):0))}}return null}(e):"object"==typeof e&&e?K(e):"number"==typeof e?K(((n={})[t||"milliseconds"]=e,n)):null}function K(e){return{years:e.years||e.year||0,months:e.months||e.month||0,days:(e.days||e.day||0)+7*Q(e),milliseconds:60*(e.hours||e.hour||0)*60*1e3+60*(e.minutes||e.minute||0)*1e3+1e3*(e.seconds||e.second||0)+(e.milliseconds||e.millisecond||e.ms||0)}}function Q(e){return e.weeks||e.week||0}function $(e,t){return e.years===t.years&&e.months===t.months&&e.days===t.days&&e.milliseconds===t.milliseconds}function ee(e){return te(e)/864e5}function te(e){return 31536e6*e.years+2592e6*e.months+864e5*e.days+e.milliseconds}function ne(e,t){var n=e.milliseconds;if(n){if(n%1e3!=0)return{unit:"millisecond",value:n};if(n%6e4!=0)return{unit:"second",value:n/1e3};if(n%36e5!=0)return{unit:"minute",value:n/6e4};if(n)return{unit:"hour",value:n/36e5}}return e.days?t||e.days%7!=0?{unit:"day",value:e.days}:{unit:"week",value:e.days/7}:e.months?{unit:"month",value:e.months}:e.years?{unit:"year",value:e.years}:{unit:"millisecond",value:0}}function re(e){e.forEach(function(e){e.style.height=""})}function ie(e){var t,n,r=[],i=[];for("string"==typeof e?i=e.split(/\s*,\s*/):"function"==typeof e?i=[e]:Array.isArray(e)&&(i=e),t=0;t<i.length;t++)"string"==typeof(n=i[t])?r.push("-"===n.charAt(0)?{field:n.substring(1),order:-1}:{field:n,order:1}):"function"==typeof n&&r.push({func:n});return r}function oe(e,t,n){var r,i;for(r=0;r<n.length;r++)if(i=ae(e,t,n[r]))return i;return 0}function ae(e,t,n){return n.func?n.func(e,t):se(e[n.field],t[n.field])*(n.order||1)}function se(e,t){return e||t?null==t?-1:null==e?1:"string"==typeof e||"string"==typeof t?String(e).localeCompare(String(t)):e-t:0}function ue(e){return e.charAt(0).toUpperCase()+e.slice(1)}function le(e,t){var n=String(e);return"000".substr(0,t-n.length)+n}function ce(e){return e%1==0}function de(e,t,n){if("function"==typeof e&&(e=[e]),e){var r=void 0,i=void 0;for(r=0;r<e.length;r++)i=e[r].apply(t,n)||i;return i}}function fe(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];for(var n=0;n<e.length;n++)if(void 0!==e[n])return e[n]}function pe(e,t){var n,r,i,o,a,s=function(){var u=(new Date).valueOf()-o;u<t?n=setTimeout(s,t-u):(n=null,a=e.apply(i,r),i=r=null)};return function(){return i=this,r=arguments,o=(new Date).valueOf(),n||(n=setTimeout(s,t)),a}}function he(e,t,n,r){void 0===n&&(n={});var i={};for(var o in t){var a=t[o];void 0!==e[o]?a===Function?i[o]="function"==typeof e[o]?e[o]:null:i[o]=a?a(e[o]):e[o]:void 0!==n[o]?i[o]=n[o]:a===String?i[o]="":a&&a!==Number&&a!==Boolean&&a!==Function?i[o]=a(null):i[o]=null}if(r)for(var o in e)void 0===t[o]&&(r[o]=e[o]);return i}function ve(e){var t=Math.floor(N(e.start,e.end))||1,n=B(e.start);return{start:n,end:x(n,t)}}function ge(e,t){void 0===t&&(t=J(0));var n=null,r=null;if(e.end){r=B(e.end);var i=e.end.valueOf()-r.valueOf();i&&i>=te(t)&&(r=x(r,1))}return e.start&&(n=B(e.start),r&&r<=n&&(r=x(n,1))),{start:n,end:r}}function ye(e,t,n,r){return"year"===r?J(n.diffWholeYears(e,t),"year"):"month"===r?J(n.diffWholeMonths(e,t),"month"):z(e,t)}var me=function(e,t){return(me=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)};function Ee(e,t){function n(){this.constructor=e}me(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var Se=function(){return(Se=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)};function be(e,t,n,r,i){var o=i[e.recurringDef.typeId].expand(e.recurringDef.typeData,{start:r.subtract(n.start,t),end:n.end},r);return e.allDay&&(o=o.map(B)),o}var De=Object.prototype.hasOwnProperty;function Te(e,t){var n,r,i,o,a,s,u={};if(t)for(n=0;n<t.length;n++){for(r=t[n],i=[],o=e.length-1;o>=0;o--)if("object"==typeof(a=e[o][r])&&a)i.unshift(a);else if(void 0!==a){u[r]=a;break}i.length&&(u[r]=Te(i))}for(n=e.length-1;n>=0;n--)for(r in s=e[n])r in u||(u[r]=s[r]);return u}function we(e,t){var n={};for(var r in e)t(e[r],r)&&(n[r]=e[r]);return n}function Re(e,t){var n={};for(var r in e)n[r]=t(e[r],r);return n}function Ie(e){for(var t={},n=0,r=e;n<r.length;n++){t[r[n]]=!0}return t}function Ce(e){var t=[];for(var n in e)t.push(e[n]);return t}function Me(e,t){for(var n in e)if(De.call(e,n)&&!(n in t))return!1;for(var n in t)if(De.call(t,n)&&e[n]!==t[n])return!1;return!0}function ke(e,t,n,r){for(var i={defs:{},instances:{}},o=0,a=e;o<a.length;o++){var s=Ft(a[o],t,n,r);s&&Oe(s,i)}return i}function Oe(e,t){return void 0===t&&(t={defs:{},instances:{}}),t.defs[e.def.defId]=e.def,e.instance&&(t.instances[e.instance.instanceId]=e.instance),t}function _e(e,t,n){var r=n.dateEnv,i=e.defs,o=e.instances;for(var a in o=we(o,function(e){return!i[e.defId].recurringDef}),i){var s=i[a];if(s.recurringDef){var u=s.recurringDef.duration;u||(u=s.allDay?n.defaultAllDayEventDuration:n.defaultTimedEventDuration);for(var l=0,c=be(s,u,t,n.dateEnv,n.pluginSystem.hooks.recurringTypes);l<c.length;l++){var d=c[l],f=Zt(a,{start:d,end:r.add(d,u)});o[f.instanceId]=f}}}return{defs:i,instances:o}}function Pe(e,t){var n=e.instances[t];if(n){var r=e.defs[n.defId],i=ze(e,function(e){return t=r,n=e,Boolean(t.groupId&&t.groupId===n.groupId);var t,n});return i.defs[r.defId]=r,i.instances[n.instanceId]=n,i}return{defs:{},instances:{}}}function xe(e,t){var n;if(t){n=[];for(var r=0,i=e;r<i.length;r++){var o=i[r],a=t(o);a?n.push(a):null==a&&n.push(o)}}else n=e;return n}function He(){return{defs:{},instances:{}}}function Ne(e,t){return{defs:Se({},e.defs,t.defs),instances:Se({},e.instances,t.instances)}}function ze(e,t){var n=we(e.defs,t),r=we(e.instances,function(e){return n[e.defId]});return{defs:n,instances:r}}function Ue(e,t){var n=null,r=null;return e.start&&(n=t.createMarker(e.start)),e.end&&(r=t.createMarker(e.end)),n||r?n&&r&&r<n?null:{start:n,end:r}:null}function Le(e,t){var n,r,i=[],o=t.start;for(e.sort(Be),n=0;n<e.length;n++)(r=e[n]).start>o&&i.push({start:o,end:r.start}),r.end>o&&(o=r.end);return o<t.end&&i.push({start:o,end:t.end}),i}function Be(e,t){return e.start.valueOf()-t.start.valueOf()}function Ve(e,t){var n=e.start,r=e.end,i=null;return null!==t.start&&(n=null===n?t.start:new Date(Math.max(n.valueOf(),t.start.valueOf()))),null!=t.end&&(r=null===r?t.end:new Date(Math.min(r.valueOf(),t.end.valueOf()))),(null===n||null===r||n<r)&&(i={start:n,end:r}),i}function Ae(e,t){return(null===e.start?null:e.start.valueOf())===(null===t.start?null:t.start.valueOf())&&(null===e.end?null:e.end.valueOf())===(null===t.end?null:t.end.valueOf())}function Fe(e,t){return(null===e.end||null===t.start||e.end>t.start)&&(null===e.start||null===t.end||e.start<t.end)}function We(e,t){return(null===e.start||null!==t.start&&t.start>=e.start)&&(null===e.end||null!==t.end&&t.end<=e.end)}function Ze(e,t){return(null===e.start||t>=e.start)&&(null===e.end||t<e.end)}function je(e,t){var n,r=e.length;if(r!==t.length)return!1;for(n=0;n<r;n++)if(e[n]!==t[n])return!1;return!0}function Ye(e){var t,n;return function(){return t&&je(t,arguments)||(t=arguments,n=e.apply(this,arguments)),n}}function qe(e,t){var n=null;return function(){var r=e.apply(this,arguments);return(null===n||n!==r&&!t(n,r))&&(n=r),n}}var Ge={week:3,separator:0,omitZeroMinute:0,meridiem:0,omitCommas:0},Xe={timeZoneName:7,era:6,year:5,month:4,day:2,weekday:2,hour:1,minute:1,second:1},Je=/\s*([ap])\.?m\.?/i,Ke=/,/g,Qe=/\s+/g,$e=/\u200e/g,et=/UTC|GMT/,tt=function(){function e(e){var t={},n={},r=0;for(var i in e)i in Ge?(n[i]=e[i],r=Math.max(Ge[i],r)):(t[i]=e[i],i in Xe&&(r=Math.max(Xe[i],r)));this.standardDateProps=t,this.extendedSettings=n,this.severity=r,this.buildFormattingFunc=Ye(nt)}return e.prototype.format=function(e,t){return this.buildFormattingFunc(this.standardDateProps,this.extendedSettings,t)(e)},e.prototype.formatRange=function(e,t,n){var r=this.standardDateProps,i=this.extendedSettings,o=function(e,t,n){if(n.getMarkerYear(e)!==n.getMarkerYear(t))return 5;if(n.getMarkerMonth(e)!==n.getMarkerMonth(t))return 4;if(n.getMarkerDay(e)!==n.getMarkerDay(t))return 2;if(q(e)!==q(t))return 1;return 0}(e.marker,t.marker,n.calendarSystem);if(!o)return this.format(e,n);var a=o;!(a>1)||"numeric"!==r.year&&"2-digit"!==r.year||"numeric"!==r.month&&"2-digit"!==r.month||"numeric"!==r.day&&"2-digit"!==r.day||(a=1);var s=this.format(e,n),u=this.format(t,n);if(s===u)return s;var l=nt(function(e,t){var n={};for(var r in e)r in Xe&&!(Xe[r]<=t)||(n[r]=e[r]);return n}(r,a),i,n),c=l(e),d=l(t),f=function(e,t,n,r){var i=0;for(;i<e.length;){var o=e.indexOf(t,i);if(-1===o)break;var a=e.substr(0,o);i=o+t.length;for(var s=e.substr(i),u=0;u<n.length;){var l=n.indexOf(r,u);if(-1===l)break;var c=n.substr(0,l);u=l+r.length;var d=n.substr(u);if(a===c&&s===d)return{before:a,after:s}}}return null}(s,c,u,d),p=i.separator||"";return f?f.before+c+p+d+f.after:s+p+u},e.prototype.getLargestUnit=function(){switch(this.severity){case 7:case 6:case 5:return"year";case 4:return"month";case 3:return"week";default:return"day"}},e}();function nt(e,t,n){var r=Object.keys(e).length;return 1===r&&"short"===e.timeZoneName?function(e){return at(e.timeZoneOffset)}:0===r&&t.week?function(e){return function(e,t,n,r){var i=[];"narrow"===r?i.push(t):"short"===r&&i.push(t," ");i.push(n.simpleNumberFormat.format(e)),n.options.isRtl&&i.reverse();return i.join("")}(n.computeWeekNumber(e.marker),n.weekLabel,n.locale,t.week)}:function(e,t,n){e=Se({},e),t=Se({},t),function(e,t){e.timeZoneName&&(e.hour||(e.hour="2-digit"),e.minute||(e.minute="2-digit"));"long"===e.timeZoneName&&(e.timeZoneName="short");t.omitZeroMinute&&(e.second||e.millisecond)&&delete t.omitZeroMinute}(e,t),e.timeZone="UTC";var r,i=new Intl.DateTimeFormat(n.locale.codes,e);if(t.omitZeroMinute){var o=Se({},e);delete o.minute,r=new Intl.DateTimeFormat(n.locale.codes,o)}return function(o){var a=o.marker,s=(r&&!a.getUTCMinutes()?r:i).format(a);return function(e,t,n,r,i){e=e.replace($e,""),"short"===n.timeZoneName&&(e=function(e,t){var n=!1;e=e.replace(et,function(){return n=!0,t}),n||(e+=" "+t);return e}(e,"UTC"===i.timeZone||null==t.timeZoneOffset?"UTC":at(t.timeZoneOffset)));r.omitCommas&&(e=e.replace(Ke,"").trim());r.omitZeroMinute&&(e=e.replace(":00",""));!1===r.meridiem?e=e.replace(Je,"").trim():"narrow"===r.meridiem?e=e.replace(Je,function(e,t){return t.toLocaleLowerCase()}):"short"===r.meridiem?e=e.replace(Je,function(e,t){return t.toLocaleLowerCase()+"m"}):"lowercase"===r.meridiem&&(e=e.replace(Je,function(e){return e.toLocaleLowerCase()}));return e=(e=e.replace(Qe," ")).trim()}(s,o,e,t,n)}}(e,t,n)}var rt=function(){function e(e,t){this.cmdStr=e,this.separator=t}return e.prototype.format=function(e,t){return t.cmdFormatter(this.cmdStr,st(e,null,t,this.separator))},e.prototype.formatRange=function(e,t,n){return n.cmdFormatter(this.cmdStr,st(e,t,n,this.separator))},e}(),it=function(){function e(e){this.func=e}return e.prototype.format=function(e,t){return this.func(st(e,null,t))},e.prototype.formatRange=function(e,t,n){return this.func(st(e,t,n))},e}();function ot(e,t){return"object"==typeof e&&e?("string"==typeof t&&(e=Se({separator:t},e)),new tt(e)):"string"==typeof e?new rt(e,t):"function"==typeof e?new it(e):void 0}function at(e,t){void 0===t&&(t=!1);var n=e<0?"-":"+",r=Math.abs(e),i=Math.floor(r/60),o=Math.round(r%60);return t?n+le(i,2)+":"+le(o,2):"GMT"+n+i+(o?":"+le(o,2):"")}function st(e,t,n,r){var i=ut(e,n.calendarSystem);return{date:i,start:i,end:t?ut(t,n.calendarSystem):null,timeZone:n.timeZone,localeCodes:n.locale.codes,separator:r}}function ut(e,t){var n=t.markerToArray(e.marker);return{marker:e.marker,timeZoneOffset:e.timeZoneOffset,array:n,year:n[0],month:n[1],day:n[2],hour:n[3],minute:n[4],second:n[5],millisecond:n[6]}}var lt=function(){function e(e,t){this.calendar=e,this.internalEventSource=t}return e.prototype.remove=function(){this.calendar.dispatch({type:"REMOVE_EVENT_SOURCE",sourceId:this.internalEventSource.sourceId})},e.prototype.refetch=function(){this.calendar.dispatch({type:"FETCH_EVENT_SOURCES",sourceIds:[this.internalEventSource.sourceId]})},Object.defineProperty(e.prototype,"id",{get:function(){return this.internalEventSource.publicId},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"url",{get:function(){return this.internalEventSource.meta.url},enumerable:!0,configurable:!0}),e}(),ct=function(){function e(e,t,n){this._calendar=e,this._def=t,this._instance=n||null}return e.prototype.setProp=function(e,t){var n,r;if(e in Vt);else if(e in Bt)"function"==typeof Bt[e]&&(t=Bt[e](t)),this.mutate({standardProps:(n={},n[e]=t,n)});else if(e in xt){var i=void 0;"function"==typeof xt[e]&&(t=xt[e](t)),"color"===e?i={backgroundColor:t,borderColor:t}:"editable"===e?i={startEditable:t,durationEditable:t}:((r={})[e]=t,i=r),this.mutate({standardProps:{ui:i}})}},e.prototype.setExtendedProp=function(e,t){var n;this.mutate({extendedProps:(n={},n[e]=t,n)})},e.prototype.setStart=function(e,t){void 0===t&&(t={});var n=this._calendar.dateEnv,r=n.createMarker(e);if(r&&this._instance){var i=ye(this._instance.range.start,r,n,t.granularity);t.maintainDuration?this.mutate({datesDelta:i}):this.mutate({startDelta:i})}},e.prototype.setEnd=function(e,t){void 0===t&&(t={});var n,r=this._calendar.dateEnv;if((null==e||(n=r.createMarker(e)))&&this._instance)if(n){var i=ye(this._instance.range.end,n,r,t.granularity);this.mutate({endDelta:i})}else this.mutate({standardProps:{hasEnd:!1}})},e.prototype.setDates=function(e,t,n){void 0===n&&(n={});var r,i=this._calendar.dateEnv,o={allDay:n.allDay},a=i.createMarker(e);if(a&&(null==t||(r=i.createMarker(t)))&&this._instance){var s=this._instance.range;!0===n.allDay&&(s=ve(s));var u=ye(s.start,a,i,n.granularity);if(r){var l=ye(s.end,r,i,n.granularity);$(u,l)?this.mutate({datesDelta:u,standardProps:o}):this.mutate({startDelta:u,endDelta:l,standardProps:o})}else o.hasEnd=!1,this.mutate({datesDelta:u,standardProps:o})}},e.prototype.moveStart=function(e){var t=J(e);t&&this.mutate({startDelta:t})},e.prototype.moveEnd=function(e){var t=J(e);t&&this.mutate({endDelta:t})},e.prototype.moveDates=function(e){var t=J(e);t&&this.mutate({datesDelta:t})},e.prototype.setAllDay=function(e,t){void 0===t&&(t={});var n={allDay:e},r=t.maintainDuration;null==r&&(r=this._calendar.opt("allDayMaintainDuration")),this._def.allDay!==e&&(n.hasEnd=r),this.mutate({standardProps:n})},e.prototype.formatRange=function(e){var t=this._calendar.dateEnv,n=this._instance,r=ot(e,this._calendar.opt("defaultRangeSeparator"));return this._def.hasEnd?t.formatRange(n.range.start,n.range.end,r,{forcedStartTzo:n.forcedStartTzo,forcedEndTzo:n.forcedEndTzo}):t.format(n.range.start,r,{forcedTzo:n.forcedStartTzo})},e.prototype.mutate=function(e){var t=this._def,n=this._instance;if(n){this._calendar.dispatch({type:"MUTATE_EVENTS",instanceId:n.instanceId,mutation:e,fromApi:!0});var r=this._calendar.state.eventStore;this._def=r.defs[t.defId],this._instance=r.instances[n.instanceId]}},e.prototype.remove=function(){this._calendar.dispatch({type:"REMOVE_EVENT_DEF",defId:this._def.defId})},Object.defineProperty(e.prototype,"source",{get:function(){var e=this._def.sourceId;return e?new lt(this._calendar,this._calendar.state.eventSources[e]):null},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"start",{get:function(){return this._instance?this._calendar.dateEnv.toDate(this._instance.range.start):null},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"end",{get:function(){return this._instance&&this._def.hasEnd?this._calendar.dateEnv.toDate(this._instance.range.end):null},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"id",{get:function(){return this._def.publicId},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"groupId",{get:function(){return this._def.groupId},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"allDay",{get:function(){return this._def.allDay},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"title",{get:function(){return this._def.title},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"url",{get:function(){return this._def.url},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"rendering",{get:function(){return this._def.rendering},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"startEditable",{get:function(){return this._def.ui.startEditable},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"durationEditable",{get:function(){return this._def.ui.durationEditable},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"constraint",{get:function(){return this._def.ui.constraints[0]||null},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"overlap",{get:function(){return this._def.ui.overlap},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"allow",{get:function(){return this._def.ui.allows[0]||null},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"backgroundColor",{get:function(){return this._def.ui.backgroundColor},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"borderColor",{get:function(){return this._def.ui.borderColor},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"textColor",{get:function(){return this._def.ui.textColor},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"classNames",{get:function(){return this._def.ui.classNames},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"extendedProps",{get:function(){return this._def.extendedProps},enumerable:!0,configurable:!0}),e}();function dt(e,t,n,r){var i={},o={},a={},s=[],u=[],l=vt(e.defs,t);for(var c in e.defs){"inverse-background"===(S=e.defs[c]).rendering&&(S.groupId?(i[S.groupId]=[],a[S.groupId]||(a[S.groupId]=S)):o[c]=[])}for(var d in e.instances){var f=e.instances[d],p=l[(S=e.defs[f.defId]).defId],h=f.range,v=!S.allDay&&r?ge(h,r):h,g=Ve(v,n);g&&("inverse-background"===S.rendering?S.groupId?i[S.groupId].push(g):o[f.defId].push(g):("background"===S.rendering?s:u).push({def:S,ui:p,instance:f,range:g,isStart:v.start&&v.start.valueOf()===g.start.valueOf(),isEnd:v.end&&v.end.valueOf()===g.end.valueOf()}))}for(var y in i)for(var m=0,E=Le(i[y],n);m<E.length;m++){var S,b=E[m];p=l[(S=a[y]).defId];s.push({def:S,ui:p,instance:null,range:b,isStart:!1,isEnd:!1})}for(var c in o)for(var D=0,T=Le(o[c],n);D<T.length;D++){b=T[D];s.push({def:e.defs[c],ui:l[c],instance:null,range:b,isStart:!1,isEnd:!1})}return{bg:s,fg:u}}function ft(e,t,n){e.hasPublicHandlers("eventRender")&&(t=t.filter(function(t){var r=e.publiclyTrigger("eventRender",[{event:new ct(e.calendar,t.eventRange.def,t.eventRange.instance),isMirror:n,isStart:t.isStart,isEnd:t.isEnd,el:t.el,view:e}]);return!1!==r&&(r&&!0!==r&&(t.el=r),!0)}));for(var r=0,i=t;r<i.length;r++){var o=i[r];pt(o.el,o)}return t}function pt(e,t){e.fcSeg=t}function ht(e){return e.fcSeg||null}function vt(e,t){return Re(e,function(e){return gt(e,t)})}function gt(e,t){var n=[];return t[""]&&n.push(t[""]),t[e.defId]&&n.push(t[e.defId]),n.push(e.ui),Ut(n)}function yt(e,t,n,r){var i=vt(e.defs,t),o={defs:{},instances:{}};for(var a in e.defs){var s=e.defs[a];o.defs[a]=mt(s,i[a],n,r.pluginSystem.hooks.eventDefMutationAppliers,r)}for(var u in e.instances){var l=e.instances[u];s=o.defs[l.defId];o.instances[u]=Et(l,s,i[l.defId],n,r)}return o}function mt(e,t,n,r,i){var o=n.standardProps||{};null==o.hasEnd&&t.durationEditable&&(n.startDelta||n.endDelta)&&(o.hasEnd=!0);var a=Se({},e,o,{ui:Se({},e.ui,o.ui)});n.extendedProps&&(a.extendedProps=Se({},a.extendedProps,n.extendedProps));for(var s=0,u=r;s<u.length;s++){(0,u[s])(a,n,i)}return!a.hasEnd&&i.opt("forceEventDuration")&&(a.hasEnd=!0),a}function Et(e,t,n,r,i){var o=i.dateEnv,a=r.standardProps&&!0===r.standardProps.allDay,s=r.standardProps&&!1===r.standardProps.hasEnd,u=Se({},e);return a&&(u.range=ve(u.range)),r.datesDelta&&n.startEditable&&(u.range={start:o.add(u.range.start,r.datesDelta),end:o.add(u.range.end,r.datesDelta)}),r.startDelta&&n.durationEditable&&(u.range={start:o.add(u.range.start,r.startDelta),end:u.range.end}),r.endDelta&&n.durationEditable&&(u.range={start:u.range.start,end:o.add(u.range.end,r.endDelta)}),s&&(u.range={start:u.range.start,end:i.getDefaultEventEnd(t.allDay,u.range.start)}),t.allDay&&(u.range={start:B(u.range.start),end:B(u.range.end)}),u.range.end<u.range.start&&(u.range.end=i.getDefaultEventEnd(t.allDay,u.range.start)),u}function St(e,t,n,r,i){switch(t.type){case"RECEIVE_EVENTS":return function(e,t,n,r,i,o){if(t&&n===t.latestFetchId){var a=ke(function(e,t,n){var r=n.opt("eventDataTransform"),i=t?t.eventDataTransform:null;return i&&(e=xe(e,i)),r&&(e=xe(e,r)),e}(i,t,o),t.sourceId,o);return r&&(a=_e(a,r,o)),Ne(bt(e,t.sourceId),a)}return e}(e,n[t.sourceId],t.fetchId,t.fetchRange,t.rawEvents,i);case"ADD_EVENTS":return function(e,t,n,r){n&&(t=_e(t,n,r));return Ne(e,t)}(e,t.eventStore,r?r.activeRange:null,i);case"MERGE_EVENTS":return Ne(e,t.eventStore);case"PREV":case"NEXT":case"SET_DATE":case"SET_VIEW_TYPE":return r?_e(e,r.activeRange,i):e;case"CHANGE_TIMEZONE":return function(e,t,n){var r=e.defs,i=Re(e.instances,function(e){var i=r[e.defId];return i.allDay||i.recurringDef?e:Se({},e,{range:{start:n.createMarker(t.toDate(e.range.start,e.forcedStartTzo)),end:n.createMarker(t.toDate(e.range.end,e.forcedEndTzo))},forcedStartTzo:n.canComputeOffset?null:e.forcedStartTzo,forcedEndTzo:n.canComputeOffset?null:e.forcedEndTzo})});return{defs:r,instances:i}}(e,t.oldDateEnv,i.dateEnv);case"MUTATE_EVENTS":return function(e,t,n,r,i){var o=Pe(e,t),a=r?{"":{startEditable:!0,durationEditable:!0,constraints:[],overlap:null,allows:[],backgroundColor:"",borderColor:"",textColor:"",classNames:[]}}:i.eventUiBases;return o=yt(o,a,n,i),Ne(e,o)}(e,t.instanceId,t.mutation,t.fromApi,i);case"REMOVE_EVENT_INSTANCES":return Dt(e,t.instances);case"REMOVE_EVENT_DEF":return ze(e,function(e){return e.defId!==t.defId});case"REMOVE_EVENT_SOURCE":return bt(e,t.sourceId);case"REMOVE_ALL_EVENT_SOURCES":return ze(e,function(e){return!e.sourceId});case"REMOVE_ALL_EVENTS":return{defs:{},instances:{}};case"RESET_EVENTS":return{defs:e.defs,instances:e.instances};default:return e}}function bt(e,t){return ze(e,function(e){return e.sourceId!==t})}function Dt(e,t){return{defs:e.defs,instances:we(e.instances,function(e){return!t[e.instanceId]})}}function Tt(e,t){return wt({eventDrag:e},t)}function wt(e,t){var n=t.view,r=Se({businessHours:n?n.props.businessHours:{defs:{},instances:{}},dateSelection:"",eventStore:t.state.eventStore,eventUiBases:t.eventUiBases,eventSelection:"",eventDrag:null,eventResize:null},e);return(t.pluginSystem.hooks.isPropsValid||Rt)(r,t)}function Rt(e,t,n,r){return void 0===n&&(n={}),!(e.eventDrag&&!function(e,t,n,r){var i=e.eventDrag,o=i.mutatedEvents,a=o.defs,s=o.instances,u=vt(a,i.isEvent?e.eventUiBases:{"":t.selectionConfig});r&&(u=Re(u,r));var l=Dt(e.eventStore,i.affectedEvents.instances),c=l.defs,d=l.instances,f=vt(c,e.eventUiBases);for(var p in s){var h=s[p],v=h.range,g=u[h.defId],y=a[h.defId];if(!It(g.constraints,v,l,e.businessHours,t))return!1;var m=t.opt("eventOverlap");for(var E in"function"!=typeof m&&(m=null),d){var S=d[E];if(Fe(v,S.range)){var b=f[S.defId].overlap;if(!1===b&&i.isEvent)return!1;if(!1===g.overlap)return!1;if(m&&!m(new ct(t,c[S.defId],S),new ct(t,y,h)))return!1}}for(var D=t.state.eventStore,T=0,w=g.allows;T<w.length;T++){var R=w[T],I=Se({},n,{range:h.range,allDay:y.allDay}),C=D.defs[y.defId],M=D.instances[p],k=void 0;if(k=C?new ct(t,C,M):new ct(t,y),!R(t.buildDateSpanApi(I),k))return!1}}return!0}(e,t,n,r))&&!(e.dateSelection&&!function(e,t,n,r){var i=e.eventStore,o=i.defs,a=i.instances,s=e.dateSelection,u=s.range,l=t.selectionConfig;r&&(l=r(l));if(!It(l.constraints,u,i,e.businessHours,t))return!1;var c=t.opt("selectOverlap");"function"!=typeof c&&(c=null);for(var d in a){var f=a[d];if(Fe(u,f.range)){if(!1===l.overlap)return!1;if(c&&!c(new ct(t,o[f.defId],f)))return!1}}for(var p=0,h=l.allows;p<h.length;p++){var v=h[p],g=Se({},n,s);if(!v(t.buildDateSpanApi(g),null))return!1}return!0}(e,t,n,r))}function It(e,t,n,r,i){for(var o=0,a=e;o<a.length;o++){if(!kt(Ct(a[o],t,n,r,i),t))return!1}return!0}function Ct(e,t,n,r,i){return"businessHours"===e?Mt(_e(r,t,i)):"string"==typeof e?Mt(ze(n,function(t){return t.groupId===e})):"object"==typeof e&&e?Mt(_e(e,t,i)):[]}function Mt(e){var t=e.instances,n=[];for(var r in t)n.push(t[r].range);return n}function kt(e,t){for(var n=0,r=e;n<r.length;n++){if(We(r[n],t))return!0}return!1}function Ot(e){return(e+"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/'/g,"'").replace(/"/g,""").replace(/\n/g,"<br />")}function _t(e){var t=[];for(var n in e){var r=e[n];null!=r&&""!==r&&t.push(n+":"+r)}return t.join(";")}function Pt(e){return Array.isArray(e)?e:"string"==typeof e?e.split(/\s+/):[]}var xt={editable:Boolean,startEditable:Boolean,durationEditable:Boolean,constraint:null,overlap:null,allow:null,className:Pt,classNames:Pt,color:String,backgroundColor:String,borderColor:String,textColor:String};function Ht(e,t,n){var r=he(e,xt,{},n),i=function(e,t){return Array.isArray(e)?ke(e,"",t,!0):"object"==typeof e&&e?ke([e],"",t,!0):null!=e?String(e):null}(r.constraint,t);return{startEditable:null!=r.startEditable?r.startEditable:r.editable,durationEditable:null!=r.durationEditable?r.durationEditable:r.editable,constraints:null!=i?[i]:[],overlap:r.overlap,allows:null!=r.allow?[r.allow]:[],backgroundColor:r.backgroundColor||r.color,borderColor:r.borderColor||r.color,textColor:r.textColor,classNames:r.classNames.concat(r.className)}}function Nt(e,t,n,r){var i={},o={};for(var a in xt){var s=e+ue(a);i[a]=t[s],o[s]=!0}if("event"===e&&(i.editable=t.editable),r)for(var a in t)o[a]||(r[a]=t[a]);return Ht(i,n)}var zt={startEditable:null,durationEditable:null,constraints:[],overlap:null,allows:[],backgroundColor:"",borderColor:"",textColor:"",classNames:[]};function Ut(e){return e.reduce(Lt,zt)}function Lt(e,t){return{startEditable:null!=t.startEditable?t.startEditable:e.startEditable,durationEditable:null!=t.durationEditable?t.durationEditable:e.durationEditable,constraints:e.constraints.concat(t.constraints),overlap:"boolean"==typeof t.overlap?t.overlap:e.overlap,allows:e.allows.concat(t.allows),backgroundColor:t.backgroundColor||e.backgroundColor,borderColor:t.borderColor||e.borderColor,textColor:t.textColor||e.textColor,classNames:e.classNames.concat(t.classNames)}}var Bt={id:String,groupId:String,title:String,url:String,rendering:String,extendedProps:null},Vt={start:null,date:null,end:null,allDay:null},At=0;function Ft(e,t,n,r){var i=function(e,t){var n=null;if(e){var r=t.state.eventSources[e];n=r.allDayDefault}null==n&&(n=t.opt("allDayDefault"));return n}(t,n),o={},a=function(e,t,n,r,i){for(var o=0;o<r.length;o++){var a={},s=r[o].parse(e,a,n);if(s){var u=a.allDay;return delete a.allDay,null==u&&null==(u=t)&&null==(u=s.allDayGuess)&&(u=!1),Se(i,a),{allDay:u,duration:s.duration,typeData:s.typeData,typeId:o}}}return null}(e,i,n.dateEnv,n.pluginSystem.hooks.recurringTypes,o);if(a)return(s=Wt(o,t,a.allDay,Boolean(a.duration),n)).recurringDef={typeId:a.typeId,typeData:a.typeData,duration:a.duration},{def:s,instance:null};var s,u={},l=function(e,t,n,r,i){var o,a,s=function(e,t){var n=he(e,Vt,{},t);return n.start=null!==n.start?n.start:n.date,delete n.date,n}(e,r),u=s.allDay,l=null,c=!1,d=null;if(o=n.dateEnv.createMarkerMeta(s.start))l=o.marker;else if(!i)return null;null!=s.end&&(a=n.dateEnv.createMarkerMeta(s.end));null==u&&(u=null!=t?t:(!o||o.isTimeUnspecified)&&(!a||a.isTimeUnspecified));u&&l&&(l=B(l));a&&(d=a.marker,u&&(d=B(d)),l&&d<=l&&(d=null));d?c=!0:i||(c=n.opt("forceEventDuration")||!1,d=n.dateEnv.add(l,u?n.defaultAllDayEventDuration:n.defaultTimedEventDuration));return{allDay:u,hasEnd:c,range:{start:l,end:d},forcedStartTzo:o?o.forcedTzo:null,forcedEndTzo:a?a.forcedTzo:null}}(e,i,n,u,r);return l?{def:s=Wt(u,t,l.allDay,l.hasEnd,n),instance:Zt(s.defId,l.range,l.forcedStartTzo,l.forcedEndTzo)}:null}function Wt(e,t,n,r,i){var o={},a=function(e,t,n){var r={},i=he(e,Bt,{},r),o=Ht(r,t,n);return i.publicId=i.id,delete i.id,i.ui=o,i}(e,i,o);a.defId=String(At++),a.sourceId=t,a.allDay=n,a.hasEnd=r;for(var s=0,u=i.pluginSystem.hooks.eventDefParsers;s<u.length;s++){var l={};(0,u[s])(a,o,l),o=l}return a.extendedProps=Se(o,a.extendedProps||{}),Object.freeze(a.ui.classNames),Object.freeze(a.extendedProps),a}function Zt(e,t,n,r){return{instanceId:String(At++),defId:e,range:t,forcedStartTzo:null==n?null:n,forcedEndTzo:null==r?null:r}}var jt={startTime:"09:00",endTime:"17:00",daysOfWeek:[1,2,3,4,5],rendering:"inverse-background",classNames:"fc-nonbusiness",groupId:"_businessHours"};function Yt(e,t){return ke(function(e){var t;t=!0===e?[{}]:Array.isArray(e)?e.filter(function(e){return e.daysOfWeek}):"object"==typeof e&&e?[e]:[];return t=t.map(function(e){return Se({},jt,e)})}(e),"",t)}function qt(e,t,n){void 0===n&&(n=[]);var r,i,o=[];function a(){if(i){for(var e=0,n=o;e<n.length;e++){n[e].unrender()}t&&t.apply(r,i),i=null}}function s(){i&&je(i,arguments)||(a(),r=this,i=arguments,e.apply(this,arguments))}s.dependents=o,s.unrender=a;for(var u=0,l=n;u<l.length;u++){l[u].dependents.push(s)}return s}var Gt={defs:{},instances:{}},Xt=function(){function e(){this.getKeysForEventDefs=Ye(this._getKeysForEventDefs),this.splitDateSelection=Ye(this._splitDateSpan),this.splitEventStore=Ye(this._splitEventStore),this.splitIndividualUi=Ye(this._splitIndividualUi),this.splitEventDrag=Ye(this._splitInteraction),this.splitEventResize=Ye(this._splitInteraction),this.eventUiBuilders={}}return e.prototype.splitProps=function(e){var t=this,n=this.getKeyInfo(e),r=this.getKeysForEventDefs(e.eventStore),i=this.splitDateSelection(e.dateSelection),o=this.splitIndividualUi(e.eventUiBases,r),a=this.splitEventStore(e.eventStore,r),s=this.splitEventDrag(e.eventDrag),u=this.splitEventResize(e.eventResize),l={};for(var c in this.eventUiBuilders=Re(n,function(e,n){return t.eventUiBuilders[n]||Ye(Jt)}),n){var d=n[c],f=a[c]||Gt,p=this.eventUiBuilders[c];l[c]={businessHours:d.businessHours||e.businessHours,dateSelection:i[c]||null,eventStore:f,eventUiBases:p(e.eventUiBases[""],d.ui,o[c]),eventSelection:f.instances[e.eventSelection]?e.eventSelection:"",eventDrag:s[c]||null,eventResize:u[c]||null}}return l},e.prototype._splitDateSpan=function(e){var t={};if(e)for(var n=0,r=this.getKeysForDateSpan(e);n<r.length;n++){t[r[n]]=e}return t},e.prototype._getKeysForEventDefs=function(e){var t=this;return Re(e.defs,function(e){return t.getKeysForEventDef(e)})},e.prototype._splitEventStore=function(e,t){var n=e.defs,r=e.instances,i={};for(var o in n)for(var a=0,s=t[o];a<s.length;a++){i[f=s[a]]||(i[f]={defs:{},instances:{}}),i[f].defs[o]=n[o]}for(var u in r)for(var l=r[u],c=0,d=t[l.defId];c<d.length;c++){var f;i[f=d[c]]&&(i[f].instances[u]=l)}return i},e.prototype._splitIndividualUi=function(e,t){var n={};for(var r in e)if(r)for(var i=0,o=t[r];i<o.length;i++){var a=o[i];n[a]||(n[a]={}),n[a][r]=e[r]}return n},e.prototype._splitInteraction=function(e){var t={};if(e){var n=this._splitEventStore(e.affectedEvents,this._getKeysForEventDefs(e.affectedEvents)),r=this._getKeysForEventDefs(e.mutatedEvents),i=this._splitEventStore(e.mutatedEvents,r),o=function(r){t[r]||(t[r]={affectedEvents:n[r]||Gt,mutatedEvents:i[r]||Gt,isEvent:e.isEvent,origSeg:e.origSeg})};for(var a in n)o(a);for(var a in i)o(a)}return t},e}();function Jt(e,t,n){var r=[];e&&r.push(e),t&&r.push(t);var i={"":Ut(r)};return n&&Se(i,n),i}function Kt(e,t,n,r){var i,o,a,s,u=e.dateEnv;return t instanceof Date?i=t:(i=t.date,o=t.type,a=t.forceOff),s={date:u.formatIso(i,{omitTime:!0}),type:o||"day"},"string"==typeof n&&(r=n,n=null),n=n?" "+function(e){var t=[];for(var n in e){var r=e[n];null!=r&&t.push(n+'="'+Ot(r)+'"')}return t.join(" ")}(n):"",r=r||"",!a&&e.opt("navLinks")?"<a"+n+' data-goto="'+Ot(JSON.stringify(s))+'">'+r+"</a>":"<span"+n+">"+r+"</span>"}function Qt(e,t,n,r){var i,o,a=n.calendar,s=n.view,u=n.theme,l=n.dateEnv,c=[];return Ze(t.activeRange,e)?(c.push("fc-"+P[e.getUTCDay()]),s.opt("monthMode")&&l.getMonth(e)!==l.getMonth(t.currentRange.start)&&c.push("fc-other-month"),o=x(i=B(a.getNow()),1),e<i?c.push("fc-past"):e>=o?c.push("fc-future"):(c.push("fc-today"),!0!==r&&c.push(u.getClass("today")))):c.push("fc-disabled-day"),c}function $t(e,t,n){var r=!1,i=function(){r||(r=!0,t.apply(this,arguments))},o=function(){r||(r=!0,n&&n.apply(this,arguments))},a=e(i,o);a&&"function"==typeof a.then&&a.then(i,o)}var en=function(){function e(){}return e.mixInto=function(e){this.mixIntoObj(e.prototype)},e.mixIntoObj=function(e){var t=this;Object.getOwnPropertyNames(this.prototype).forEach(function(n){e[n]||(e[n]=t.prototype[n])})},e.mixOver=function(e){var t=this;Object.getOwnPropertyNames(this.prototype).forEach(function(n){e.prototype[n]=t.prototype[n]})},e}(),tn=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return Ee(t,e),t.prototype.on=function(e,t){return nn(this._handlers||(this._handlers={}),e,t),this},t.prototype.one=function(e,t){return nn(this._oneHandlers||(this._oneHandlers={}),e,t),this},t.prototype.off=function(e,t){return this._handlers&&rn(this._handlers,e,t),this._oneHandlers&&rn(this._oneHandlers,e,t),this},t.prototype.trigger=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return this.triggerWith(e,this,t),this},t.prototype.triggerWith=function(e,t,n){return this._handlers&&de(this._handlers[e],t,n),this._oneHandlers&&(de(this._oneHandlers[e],t,n),delete this._oneHandlers[e]),this},t.prototype.hasHandlers=function(e){return this._handlers&&this._handlers[e]&&this._handlers[e].length||this._oneHandlers&&this._oneHandlers[e]&&this._oneHandlers[e].length},t}(en);function nn(e,t,n){(e[t]||(e[t]=[])).push(n)}function rn(e,t,n){n?e[t]&&(e[t]=e[t].filter(function(e){return e!==n})):delete e[t]}var on=function(){function e(e,t,n,r){this.originEl=e,this.els=t,this.isHorizontal=n,this.isVertical=r}return e.prototype.build=function(){var e=this.originEl,t=this.originClientRect=e.getBoundingClientRect();this.isHorizontal&&this.buildElHorizontals(t.left),this.isVertical&&this.buildElVerticals(t.top)},e.prototype.buildElHorizontals=function(e){for(var t=[],n=[],r=0,i=this.els;r<i.length;r++){var o=i[r].getBoundingClientRect();t.push(o.left-e),n.push(o.right-e)}this.lefts=t,this.rights=n},e.prototype.buildElVerticals=function(e){for(var t=[],n=[],r=0,i=this.els;r<i.length;r++){var o=i[r].getBoundingClientRect();t.push(o.top-e),n.push(o.bottom-e)}this.tops=t,this.bottoms=n},e.prototype.leftToIndex=function(e){var t,n=this.lefts,r=this.rights,i=n.length;for(t=0;t<i;t++)if(e>=n[t]&&e<r[t])return t},e.prototype.topToIndex=function(e){var t,n=this.tops,r=this.bottoms,i=n.length;for(t=0;t<i;t++)if(e>=n[t]&&e<r[t])return t},e.prototype.getWidth=function(e){return this.rights[e]-this.lefts[e]},e.prototype.getHeight=function(e){return this.bottoms[e]-this.tops[e]},e}(),an=function(){function e(){}return e.prototype.getMaxScrollTop=function(){return this.getScrollHeight()-this.getClientHeight()},e.prototype.getMaxScrollLeft=function(){return this.getScrollWidth()-this.getClientWidth()},e.prototype.canScrollVertically=function(){return this.getMaxScrollTop()>0},e.prototype.canScrollHorizontally=function(){return this.getMaxScrollLeft()>0},e.prototype.canScrollUp=function(){return this.getScrollTop()>0},e.prototype.canScrollDown=function(){return this.getScrollTop()<this.getMaxScrollTop()},e.prototype.canScrollLeft=function(){return this.getScrollLeft()>0},e.prototype.canScrollRight=function(){return this.getScrollLeft()<this.getMaxScrollLeft()},e}(),sn=function(e){function t(t){var n=e.call(this)||this;return n.el=t,n}return Ee(t,e),t.prototype.getScrollTop=function(){return this.el.scrollTop},t.prototype.getScrollLeft=function(){return this.el.scrollLeft},t.prototype.setScrollTop=function(e){this.el.scrollTop=e},t.prototype.setScrollLeft=function(e){this.el.scrollLeft=e},t.prototype.getScrollWidth=function(){return this.el.scrollWidth},t.prototype.getScrollHeight=function(){return this.el.scrollHeight},t.prototype.getClientHeight=function(){return this.el.clientHeight},t.prototype.getClientWidth=function(){return this.el.clientWidth},t}(an),un=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return Ee(t,e),t.prototype.getScrollTop=function(){return window.pageYOffset},t.prototype.getScrollLeft=function(){return window.pageXOffset},t.prototype.setScrollTop=function(e){window.scroll(window.pageXOffset,e)},t.prototype.setScrollLeft=function(e){window.scroll(e,window.pageYOffset)},t.prototype.getScrollWidth=function(){return document.documentElement.scrollWidth},t.prototype.getScrollHeight=function(){return document.documentElement.scrollHeight},t.prototype.getClientHeight=function(){return document.documentElement.clientHeight},t.prototype.getClientWidth=function(){return document.documentElement.clientWidth},t}(an),ln=function(e){function t(t,n){var i=e.call(this,r("div",{className:"fc-scroller"}))||this;return i.overflowX=t,i.overflowY=n,i.applyOverflow(),i}return Ee(t,e),t.prototype.clear=function(){this.setHeight("auto"),this.applyOverflow()},t.prototype.destroy=function(){c(this.el)},t.prototype.applyOverflow=function(){y(this.el,{overflowX:this.overflowX,overflowY:this.overflowY})},t.prototype.lockOverflow=function(e){var t=this.overflowX,n=this.overflowY;e=e||this.getScrollbarWidths(),"auto"===t&&(t=e.bottom||this.canScrollHorizontally()?"scroll":"hidden"),"auto"===n&&(n=e.left||e.right||this.canScrollVertically()?"scroll":"hidden"),y(this.el,{overflowX:t,overflowY:n})},t.prototype.setHeight=function(e){m(this.el,"height",e)},t.prototype.getScrollbarWidths=function(){var e=T(this.el);return{left:e.scrollbarLeft,right:e.scrollbarRight,bottom:e.scrollbarBottom}},t}(sn),cn=function(){function e(e){this.calendarOptions=e,this.processIconOverride()}return e.prototype.processIconOverride=function(){this.iconOverrideOption&&this.setIconOverride(this.calendarOptions[this.iconOverrideOption])},e.prototype.setIconOverride=function(e){var t,n;if("object"==typeof e&&e){for(n in t=Se({},this.iconClasses),e)t[n]=this.applyIconOverridePrefix(e[n]);this.iconClasses=t}else!1===e&&(this.iconClasses={})},e.prototype.applyIconOverridePrefix=function(e){var t=this.iconOverridePrefix;return t&&0!==e.indexOf(t)&&(e=t+e),e},e.prototype.getClass=function(e){return this.classes[e]||""},e.prototype.getIconClass=function(e){var t=this.iconClasses[e];return t?this.baseIconClass+" "+t:""},e.prototype.getCustomButtonIconClass=function(e){var t;return this.iconOverrideCustomButtonOption&&(t=e[this.iconOverrideCustomButtonOption])?this.baseIconClass+" "+this.applyIconOverridePrefix(t):""},e}();cn.prototype.classes={},cn.prototype.iconClasses={},cn.prototype.baseIconClass="",cn.prototype.iconOverridePrefix="";var dn=0,fn=function(){function e(e,t){t&&(e.view=this),this.uid=String(dn++),this.context=e,this.dateEnv=e.dateEnv,this.theme=e.theme,this.view=e.view,this.calendar=e.calendar,this.isRtl="rtl"===this.opt("dir")}return e.addEqualityFuncs=function(e){this.prototype.equalityFuncs=Se({},this.prototype.equalityFuncs,e)},e.prototype.opt=function(e){return this.context.options[e]},e.prototype.receiveProps=function(e){var t=function(e,t,n){var r={},i=!1;for(var o in t)o in e&&(e[o]===t[o]||n[o]&&n[o](e[o],t[o]))?r[o]=e[o]:(r[o]=t[o],i=!0);for(var o in e)if(!(o in t)){i=!0;break}return{anyChanges:i,comboProps:r}}(this.props||{},e,this.equalityFuncs),n=t.anyChanges,r=t.comboProps;this.props=r,n&&this.render(r)},e.prototype.render=function(e){},e.prototype.destroy=function(){},e}();fn.prototype.equalityFuncs={};var pn=function(e){function t(t,n,r){var i=e.call(this,t,r)||this;return i.el=n,i}return Ee(t,e),t.prototype.destroy=function(){e.prototype.destroy.call(this),c(this.el)},t.prototype.buildPositionCaches=function(){},t.prototype.queryHit=function(e,t,n,r){return null},t.prototype.isInteractionValid=function(e){var t=this.calendar,n=this.props.dateProfile,r=e.mutatedEvents.instances;if(n)for(var i in r)if(!We(n.validRange,r[i].range))return!1;return Tt(e,t)},t.prototype.isDateSelectionValid=function(e){var t,n,r=this.props.dateProfile;return!(r&&!We(r.validRange,e.range))&&(t=e,n=this.calendar,wt({dateSelection:t},n))},t.prototype.publiclyTrigger=function(e,t){return this.calendar.publiclyTrigger(e,t)},t.prototype.publiclyTriggerAfterSizing=function(e,t){return this.calendar.publiclyTriggerAfterSizing(e,t)},t.prototype.hasPublicHandlers=function(e){return this.calendar.hasPublicHandlers(e)},t.prototype.triggerRenderedSegs=function(e,t){var n=this.calendar;if(this.hasPublicHandlers("eventPositioned"))for(var r=0,i=e;r<i.length;r++){var o=i[r];this.publiclyTriggerAfterSizing("eventPositioned",[{event:new ct(n,o.eventRange.def,o.eventRange.instance),isMirror:t,isStart:o.isStart,isEnd:o.isEnd,el:o.el,view:this}])}n.state.loadingLevel||(n.afterSizingTriggers._eventsPositioned=[null])},t.prototype.triggerWillRemoveSegs=function(e,t){for(var n=this.calendar,r=0,i=e;r<i.length;r++){var o=i[r];n.trigger("eventElRemove",o.el)}if(this.hasPublicHandlers("eventDestroy"))for(var a=0,s=e;a<s.length;a++){o=s[a];this.publiclyTrigger("eventDestroy",[{event:new ct(n,o.eventRange.def,o.eventRange.instance),isMirror:t,el:o.el,view:this}])}},t.prototype.isValidSegDownEl=function(e){return!this.props.eventDrag&&!this.props.eventResize&&!p(e,".fc-mirror")&&(this.isPopover()||!this.isInPopover(e))},t.prototype.isValidDateDownEl=function(e){var t=p(e,this.fgSegSelector);return(!t||t.classList.contains("fc-mirror"))&&!p(e,".fc-more")&&!p(e,"a[data-goto]")&&!this.isInPopover(e)},t.prototype.isPopover=function(){return this.el.classList.contains("fc-popover")},t.prototype.isInPopover=function(e){return Boolean(p(e,".fc-popover"))},t}(fn);pn.prototype.fgSegSelector=".fc-event-container > *",pn.prototype.bgSegSelector=".fc-bgevent:not(.fc-nonbusiness)";var hn=0;function vn(e){return{id:String(hn++),deps:e.deps||[],reducers:e.reducers||[],eventDefParsers:e.eventDefParsers||[],isDraggableTransformers:e.isDraggableTransformers||[],eventDragMutationMassagers:e.eventDragMutationMassagers||[],eventDefMutationAppliers:e.eventDefMutationAppliers||[],dateSelectionTransformers:e.dateSelectionTransformers||[],datePointTransforms:e.datePointTransforms||[],dateSpanTransforms:e.dateSpanTransforms||[],views:e.views||{},viewPropsTransformers:e.viewPropsTransformers||[],isPropsValid:e.isPropsValid||null,externalDefTransforms:e.externalDefTransforms||[],eventResizeJoinTransforms:e.eventResizeJoinTransforms||[],viewContainerModifiers:e.viewContainerModifiers||[],eventDropTransformers:e.eventDropTransformers||[],componentInteractions:e.componentInteractions||[],calendarInteractions:e.calendarInteractions||[],themeClasses:e.themeClasses||{},eventSourceDefs:e.eventSourceDefs||[],cmdFormatter:e.cmdFormatter,recurringTypes:e.recurringTypes||[],namedTimeZonedImpl:e.namedTimeZonedImpl,defaultView:e.defaultView||"",elementDraggingImpl:e.elementDraggingImpl,optionChangeHandlers:e.optionChangeHandlers||{}}}var gn=function(){function e(){this.hooks={reducers:[],eventDefParsers:[],isDraggableTransformers:[],eventDragMutationMassagers:[],eventDefMutationAppliers:[],dateSelectionTransformers:[],datePointTransforms:[],dateSpanTransforms:[],views:{},viewPropsTransformers:[],isPropsValid:null,externalDefTransforms:[],eventResizeJoinTransforms:[],viewContainerModifiers:[],eventDropTransformers:[],componentInteractions:[],calendarInteractions:[],themeClasses:{},eventSourceDefs:[],cmdFormatter:null,recurringTypes:[],namedTimeZonedImpl:null,defaultView:"",elementDraggingImpl:null,optionChangeHandlers:{}},this.addedHash={}}return e.prototype.add=function(e){if(!this.addedHash[e.id]){this.addedHash[e.id]=!0;for(var t=0,n=e.deps;t<n.length;t++){var r=n[t];this.add(r)}this.hooks=(i=this.hooks,o=e,{reducers:i.reducers.concat(o.reducers),eventDefParsers:i.eventDefParsers.concat(o.eventDefParsers),isDraggableTransformers:i.isDraggableTransformers.concat(o.isDraggableTransformers),eventDragMutationMassagers:i.eventDragMutationMassagers.concat(o.eventDragMutationMassagers),eventDefMutationAppliers:i.eventDefMutationAppliers.concat(o.eventDefMutationAppliers),dateSelectionTransformers:i.dateSelectionTransformers.concat(o.dateSelectionTransformers),datePointTransforms:i.datePointTransforms.concat(o.datePointTransforms),dateSpanTransforms:i.dateSpanTransforms.concat(o.dateSpanTransforms),views:Se({},i.views,o.views),viewPropsTransformers:i.viewPropsTransformers.concat(o.viewPropsTransformers),isPropsValid:o.isPropsValid||i.isPropsValid,externalDefTransforms:i.externalDefTransforms.concat(o.externalDefTransforms),eventResizeJoinTransforms:i.eventResizeJoinTransforms.concat(o.eventResizeJoinTransforms),viewContainerModifiers:i.viewContainerModifiers.concat(o.viewContainerModifiers),eventDropTransformers:i.eventDropTransformers.concat(o.eventDropTransformers),calendarInteractions:i.calendarInteractions.concat(o.calendarInteractions),componentInteractions:i.componentInteractions.concat(o.componentInteractions),themeClasses:Se({},i.themeClasses,o.themeClasses),eventSourceDefs:i.eventSourceDefs.concat(o.eventSourceDefs),cmdFormatter:o.cmdFormatter||i.cmdFormatter,recurringTypes:i.recurringTypes.concat(o.recurringTypes),namedTimeZonedImpl:o.namedTimeZonedImpl||i.namedTimeZonedImpl,defaultView:i.defaultView||o.defaultView,elementDraggingImpl:i.elementDraggingImpl||o.elementDraggingImpl,optionChangeHandlers:Se({},i.optionChangeHandlers,o.optionChangeHandlers)})}var i,o},e}();var yn=vn({eventSourceDefs:[{ignoreRange:!0,parseMeta:function(e){return Array.isArray(e)?e:Array.isArray(e.events)?e.events:null},fetch:function(e,t){t({rawEvents:e.eventSource.meta})}}]}),mn=vn({eventSourceDefs:[{parseMeta:function(e){return"function"==typeof e?e:"function"==typeof e.events?e.events:null},fetch:function(e,t,n){var r=e.calendar.dateEnv;$t(e.eventSource.meta.bind(null,{start:r.toDate(e.range.start),end:r.toDate(e.range.end),startStr:r.formatIso(e.range.start),endStr:r.formatIso(e.range.end),timeZone:r.timeZone}),function(e){t({rawEvents:e})},n)}}]});function En(e,t,n,r,i){var o=null;"GET"===(e=e.toUpperCase())?t=function(e,t){return e+(-1===e.indexOf("?")?"?":"&")+Sn(t)}(t,n):o=Sn(n);var a=new XMLHttpRequest;a.open(e,t,!0),"GET"!==e&&a.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),a.onload=function(){if(a.status>=200&&a.status<400)try{var e=JSON.parse(a.responseText);r(e,a)}catch(e){i("Failure parsing JSON",a)}else i("Request failed",a)},a.onerror=function(){i("Request failed",a)},a.send(o)}function Sn(e){var t=[];for(var n in e)t.push(encodeURIComponent(n)+"="+encodeURIComponent(e[n]));return t.join("&")}var bn=vn({eventSourceDefs:[{parseMeta:function(e){if("string"==typeof e)e={url:e};else if(!e||"object"!=typeof e||!e.url)return null;return{url:e.url,method:(e.method||"GET").toUpperCase(),extraParams:e.extraParams,startParam:e.startParam,endParam:e.endParam,timeZoneParam:e.timeZoneParam}},fetch:function(e,t,n){var r=e.eventSource.meta,i=function(e,t,n){var r,i,o,a,s=n.dateEnv,u={};null==(r=e.startParam)&&(r=n.opt("startParam"));null==(i=e.endParam)&&(i=n.opt("endParam"));null==(o=e.timeZoneParam)&&(o=n.opt("timeZoneParam"));a="function"==typeof e.extraParams?e.extraParams():e.extraParams||{};Se(u,a),u[r]=s.formatIso(t.start),u[i]=s.formatIso(t.end),"local"!==s.timeZone&&(u[o]=s.timeZone);return u}(r,e.range,e.calendar);En(r.method,r.url,i,function(e,n){t({rawEvents:e,xhr:n})},function(e,t){n({message:e,xhr:t})})}}]});var Dn=vn({recurringTypes:[{parse:function(e,t,n){var r,i,o=n.createMarker.bind(n),a=he(e,{daysOfWeek:null,startTime:J,endTime:J,startRecur:o,endRecur:o},{},t),s=!1;for(var u in a)if(null!=a[u]){s=!0;break}if(s){var l=null;return"duration"in t&&(l=J(t.duration),delete t.duration),!l&&a.startTime&&a.endTime&&(r=a.endTime,i=a.startTime,l={years:r.years-i.years,months:r.months-i.months,days:r.days-i.days,milliseconds:r.milliseconds-i.milliseconds}),{allDayGuess:Boolean(!a.startTime&&!a.endTime),duration:l,typeData:a}}return null},expand:function(e,t,n){var r=Ve(t,{start:e.startRecur,end:e.endRecur});return r?function(e,t,n,r){var i=e?Ie(e):null,o=B(n.start),a=n.end,s=[];for(;o<a;){var u=void 0;i&&!i[o.getUTCDay()]||(u=t?r.add(o,t):o,s.push(u)),o=x(o,1)}return s}(e.daysOfWeek,e.startTime,r,n):[]}}]});var Tn=vn({optionChangeHandlers:{events:function(e,t,n){wn([e],t,n)},eventSources:wn,plugins:function(e,t){t.addPluginInputs(e)}}});function wn(e,t,n){for(var r=Ce(t.state.eventSources),i=[],o=0,a=e;o<a.length;o++){for(var s=a[o],u=!1,l=0;l<r.length;l++)if(n(r[l]._raw,s)){r.splice(l,1),u=!0;break}u||i.push(s)}for(var c=0,d=r;c<d.length;c++){var f=d[c];t.dispatch({type:"REMOVE_EVENT_SOURCE",sourceId:f.sourceId})}for(var p=0,h=i;p<h.length;p++){var v=h[p];t.addEventSource(v)}}var Rn={defaultRangeSeparator:" - ",titleRangeSeparator:" – ",defaultTimedEventDuration:"01:00:00",defaultAllDayEventDuration:{day:1},forceEventDuration:!1,nextDayThreshold:"00:00:00",columnHeader:!0,defaultView:"",aspectRatio:1.35,header:{left:"title",center:"",right:"today prev,next"},weekends:!0,weekNumbers:!1,weekNumberCalculation:"local",editable:!1,scrollTime:"06:00:00",minTime:"00:00:00",maxTime:"24:00:00",showNonCurrentDates:!0,lazyFetching:!0,startParam:"start",endParam:"end",timeZoneParam:"timeZone",timeZone:"local",locales:[],locale:"",timeGridEventMinHeight:0,themeSystem:"standard",dragRevertDuration:500,dragScroll:!0,allDayMaintainDuration:!1,unselectAuto:!0,dropAccept:"*",eventOrder:"start,-duration,allDay,title",eventLimit:!1,eventLimitClick:"popover",dayPopoverFormat:{month:"long",day:"numeric",year:"numeric"},handleWindowResize:!0,windowResizeDelay:100,longPressDelay:1e3,eventDragMinDistance:5},In={header:{left:"next,prev today",center:"",right:"title"},buttonIcons:{prev:"fc-icon-chevron-right",next:"fc-icon-chevron-left",prevYear:"fc-icon-chevrons-right",nextYear:"fc-icon-chevrons-left"}},Cn=["header","footer","buttonText","buttonIcons"];var Mn=[yn,mn,bn,Dn,Tn];var kn={code:"en",week:{dow:0,doy:4},dir:"ltr",buttonText:{prev:"prev",next:"next",prevYear:"prev year",nextYear:"next year",year:"year",today:"today",month:"month",week:"week",day:"day",list:"list"},weekLabel:"W",allDayText:"all-day",eventLimitText:"more",noEventsMessage:"No events to display"};function On(e){for(var t=e.length>0?e[0].code:"en",n=window.FullCalendarLocalesAll||[],r=window.FullCalendarLocales||{},i=n.concat(Ce(r),e),o={en:kn},a=0,s=i;a<s.length;a++){var u=s[a];o[u.code]=u}return{map:o,defaultCode:t}}function _n(e,t){return"object"!=typeof e||Array.isArray(e)?function(e,t){var n=[].concat(e||[]),r=function(e,t){for(var n=0;n<e.length;n++)for(var r=e[n].toLocaleLowerCase().split("-"),i=r.length;i>0;i--){var o=r.slice(0,i).join("-");if(t[o])return t[o]}return null}(n,t)||kn;return Pn(e,n,r)}(e,t):Pn(e.code,[e.code],e)}function Pn(e,t,n){var r=Te([kn,n],["buttonText"]);delete r.code;var i=r.week;return delete r.week,{codeArg:e,codes:t,week:i,simpleNumberFormat:new Intl.NumberFormat(e),options:r}}var xn=function(){function e(e){this.overrides=Se({},e),this.dynamicOverrides={},this.compute()}return e.prototype.mutate=function(e,t,n){var r=n?this.dynamicOverrides:this.overrides;Se(r,e);for(var i=0,o=t;i<o.length;i++){delete r[o[i]]}this.compute()},e.prototype.compute=function(){var e=fe(this.dynamicOverrides.locales,this.overrides.locales,Rn.locales),t=fe(this.dynamicOverrides.locale,this.overrides.locale,Rn.locale),n=On(e),r=_n(t||n.defaultCode,n.map).options,i="rtl"===fe(this.dynamicOverrides.dir,this.overrides.dir,r.dir)?In:{};this.dirDefaults=i,this.localeDefaults=r,this.computed=Te([Rn,i,r,this.overrides,this.dynamicOverrides],Cn)},e}(),Hn={};var Nn,zn=function(){function e(){}return e.prototype.getMarkerYear=function(e){return e.getUTCFullYear()},e.prototype.getMarkerMonth=function(e){return e.getUTCMonth()},e.prototype.getMarkerDay=function(e){return e.getUTCDate()},e.prototype.arrayToMarker=function(e){return j(e)},e.prototype.markerToArray=function(e){return Z(e)},e}();Nn=zn,Hn["gregory"]=Nn;var Un=/^\s*(\d{4})(-(\d{2})(-(\d{2})([T ](\d{2}):(\d{2})(:(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/;function Ln(e){var t=Un.exec(e);if(t){var n=new Date(Date.UTC(Number(t[1]),t[3]?Number(t[3])-1:0,Number(t[5]||1),Number(t[7]||0),Number(t[8]||0),Number(t[10]||0),t[12]?1e3*Number("0."+t[12]):0));if(Y(n)){var r=null;return t[13]&&(r=("-"===t[15]?-1:1)*(60*Number(t[16]||0)+Number(t[18]||0))),{marker:n,isTimeUnspecified:!t[6],timeZoneOffset:r}}}return null}var Bn=function(){function e(e){var t=this.timeZone=e.timeZone,n="local"!==t&&"UTC"!==t;e.namedTimeZoneImpl&&n&&(this.namedTimeZoneImpl=new e.namedTimeZoneImpl(t)),this.canComputeOffset=Boolean(!n||this.namedTimeZoneImpl),this.calendarSystem=function(e){return new Hn[e]}(e.calendarSystem),this.locale=e.locale,this.weekDow=e.locale.week.dow,this.weekDoy=e.locale.week.doy,"ISO"===e.weekNumberCalculation&&(this.weekDow=1,this.weekDoy=4),"number"==typeof e.firstDay&&(this.weekDow=e.firstDay),"function"==typeof e.weekNumberCalculation&&(this.weekNumberFunc=e.weekNumberCalculation),this.weekLabel=null!=e.weekLabel?e.weekLabel:e.locale.options.weekLabel,this.cmdFormatter=e.cmdFormatter}return e.prototype.createMarker=function(e){var t=this.createMarkerMeta(e);return null===t?null:t.marker},e.prototype.createNowMarker=function(){return this.canComputeOffset?this.timestampToMarker((new Date).valueOf()):j(F(new Date))},e.prototype.createMarkerMeta=function(e){if("string"==typeof e)return this.parse(e);var t=null;return"number"==typeof e?t=this.timestampToMarker(e):e instanceof Date?(e=e.valueOf(),isNaN(e)||(t=this.timestampToMarker(e))):Array.isArray(e)&&(t=j(e)),null!==t&&Y(t)?{marker:t,isTimeUnspecified:!1,forcedTzo:null}:null},e.prototype.parse=function(e){var t=Ln(e);if(null===t)return null;var n=t.marker,r=null;return null!==t.timeZoneOffset&&(this.canComputeOffset?n=this.timestampToMarker(n.valueOf()-60*t.timeZoneOffset*1e3):r=t.timeZoneOffset),{marker:n,isTimeUnspecified:t.isTimeUnspecified,forcedTzo:r}},e.prototype.getYear=function(e){return this.calendarSystem.getMarkerYear(e)},e.prototype.getMonth=function(e){return this.calendarSystem.getMarkerMonth(e)},e.prototype.add=function(e,t){var n=this.calendarSystem.markerToArray(e);return n[0]+=t.years,n[1]+=t.months,n[2]+=t.days,n[6]+=t.milliseconds,this.calendarSystem.arrayToMarker(n)},e.prototype.subtract=function(e,t){var n=this.calendarSystem.markerToArray(e);return n[0]-=t.years,n[1]-=t.months,n[2]-=t.days,n[6]-=t.milliseconds,this.calendarSystem.arrayToMarker(n)},e.prototype.addYears=function(e,t){var n=this.calendarSystem.markerToArray(e);return n[0]+=t,this.calendarSystem.arrayToMarker(n)},e.prototype.addMonths=function(e,t){var n=this.calendarSystem.markerToArray(e);return n[1]+=t,this.calendarSystem.arrayToMarker(n)},e.prototype.diffWholeYears=function(e,t){var n=this.calendarSystem;return q(e)===q(t)&&n.getMarkerDay(e)===n.getMarkerDay(t)&&n.getMarkerMonth(e)===n.getMarkerMonth(t)?n.getMarkerYear(t)-n.getMarkerYear(e):null},e.prototype.diffWholeMonths=function(e,t){var n=this.calendarSystem;return q(e)===q(t)&&n.getMarkerDay(e)===n.getMarkerDay(t)?n.getMarkerMonth(t)-n.getMarkerMonth(e)+12*(n.getMarkerYear(t)-n.getMarkerYear(e)):null},e.prototype.greatestWholeUnit=function(e,t){var n=this.diffWholeYears(e,t);return null!==n?{unit:"year",value:n}:null!==(n=this.diffWholeMonths(e,t))?{unit:"month",value:n}:null!==(n=U(e,t))?{unit:"week",value:n}:null!==(n=L(e,t))?{unit:"day",value:n}:ce(n=function(e,t){return(t.valueOf()-e.valueOf())/36e5}(e,t))?{unit:"hour",value:n}:ce(n=function(e,t){return(t.valueOf()-e.valueOf())/6e4}(e,t))?{unit:"minute",value:n}:ce(n=function(e,t){return(t.valueOf()-e.valueOf())/1e3}(e,t))?{unit:"second",value:n}:{unit:"millisecond",value:t.valueOf()-e.valueOf()}},e.prototype.countDurationsBetween=function(e,t,n){var r;return n.years&&null!==(r=this.diffWholeYears(e,t))?r/(ee(n)/365):n.months&&null!==(r=this.diffWholeMonths(e,t))?r/function(e){return ee(e)/30}(n):n.days&&null!==(r=L(e,t))?r/ee(n):(t.valueOf()-e.valueOf())/te(n)},e.prototype.startOf=function(e,t){return"year"===t?this.startOfYear(e):"month"===t?this.startOfMonth(e):"week"===t?this.startOfWeek(e):"day"===t?B(e):"hour"===t?function(e){return j([e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours()])}(e):"minute"===t?function(e){return j([e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours(),e.getUTCMinutes()])}(e):"second"===t?function(e){return j([e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours(),e.getUTCMinutes(),e.getUTCSeconds()])}(e):void 0},e.prototype.startOfYear=function(e){return this.calendarSystem.arrayToMarker([this.calendarSystem.getMarkerYear(e)])},e.prototype.startOfMonth=function(e){return this.calendarSystem.arrayToMarker([this.calendarSystem.getMarkerYear(e),this.calendarSystem.getMarkerMonth(e)])},e.prototype.startOfWeek=function(e){return this.calendarSystem.arrayToMarker([this.calendarSystem.getMarkerYear(e),this.calendarSystem.getMarkerMonth(e),e.getUTCDate()-(e.getUTCDay()-this.weekDow+7)%7])},e.prototype.computeWeekNumber=function(e){return this.weekNumberFunc?this.weekNumberFunc(this.toDate(e)):function(e,t,n){var r=e.getUTCFullYear(),i=V(e,r,t,n);if(i<1)return V(e,r-1,t,n);var o=V(e,r+1,t,n);return o>=1?Math.min(i,o):i}(e,this.weekDow,this.weekDoy)},e.prototype.format=function(e,t,n){return void 0===n&&(n={}),t.format({marker:e,timeZoneOffset:null!=n.forcedTzo?n.forcedTzo:this.offsetForMarker(e)},this)},e.prototype.formatRange=function(e,t,n,r){return void 0===r&&(r={}),r.isEndExclusive&&(t=H(t,-1)),n.formatRange({marker:e,timeZoneOffset:null!=r.forcedStartTzo?r.forcedStartTzo:this.offsetForMarker(e)},{marker:t,timeZoneOffset:null!=r.forcedEndTzo?r.forcedEndTzo:this.offsetForMarker(t)},this)},e.prototype.formatIso=function(e,t){void 0===t&&(t={});var n=null;return t.omitTimeZoneOffset||(n=null!=t.forcedTzo?t.forcedTzo:this.offsetForMarker(e)),function(e,t,n){void 0===n&&(n=!1);var r=e.toISOString();return r=r.replace(".000",""),n&&(r=r.replace("T00:00:00Z","")),r.length>10&&(null==t?r=r.replace("Z",""):0!==t&&(r=r.replace("Z",at(t,!0)))),r}(e,n,t.omitTime)},e.prototype.timestampToMarker=function(e){return"local"===this.timeZone?j(F(new Date(e))):"UTC"!==this.timeZone&&this.namedTimeZoneImpl?j(this.namedTimeZoneImpl.timestampToArray(e)):new Date(e)},e.prototype.offsetForMarker=function(e){return"local"===this.timeZone?-W(Z(e)).getTimezoneOffset():"UTC"===this.timeZone?0:this.namedTimeZoneImpl?this.namedTimeZoneImpl.offsetForArray(Z(e)):null},e.prototype.toDate=function(e,t){return"local"===this.timeZone?W(Z(e)):"UTC"===this.timeZone?new Date(e.valueOf()):this.namedTimeZoneImpl?new Date(e.valueOf()-1e3*this.namedTimeZoneImpl.offsetForArray(Z(e))*60):new Date(e.valueOf()-(t||0))},e}(),Vn={id:String,allDayDefault:Boolean,eventDataTransform:Function,success:Function,failure:Function},An=0;function Fn(e,t){return!t.pluginSystem.hooks.eventSourceDefs[e.sourceDefId].ignoreRange}function Wn(e,t){for(var n=t.pluginSystem.hooks.eventSourceDefs,r=n.length-1;r>=0;r--){var i=n[r].parseMeta(e);if(i){var o=Zn("object"==typeof e?e:{},i,r,t);return o._raw=e,o}}return null}function Zn(e,t,n,r){var i={},o=he(e,Vn,{},i),a={},s=Ht(i,r,a);return o.isFetching=!1,o.latestFetchId="",o.fetchRange=null,o.publicId=String(e.id||""),o.sourceId=String(An++),o.sourceDefId=n,o.meta=t,o.ui=s,o.extendedProps=a,o}function jn(e,t,n,r){switch(t.type){case"ADD_EVENT_SOURCES":return function(e,t,n,r){for(var i={},o=0,a=t;o<a.length;o++){var s=a[o];i[s.sourceId]=s}n&&(i=qn(i,n,r));return Se({},e,i)}(e,t.sources,n?n.activeRange:null,r);case"REMOVE_EVENT_SOURCE":return i=e,o=t.sourceId,we(i,function(e){return e.sourceId!==o});case"PREV":case"NEXT":case"SET_DATE":case"SET_VIEW_TYPE":return n?qn(e,n.activeRange,r):e;case"FETCH_EVENT_SOURCES":case"CHANGE_TIMEZONE":return Gn(e,t.sourceIds?Ie(t.sourceIds):function(e,t){return we(e,function(e){return Fn(e,t)})}(e,r),n?n.activeRange:null,r);case"RECEIVE_EVENTS":case"RECEIVE_EVENT_ERROR":return function(e,t,n,r){var i,o=e[t];if(o&&n===o.latestFetchId)return Se({},e,((i={})[t]=Se({},o,{isFetching:!1,fetchRange:r}),i));return e}(e,t.sourceId,t.fetchId,t.fetchRange);case"REMOVE_ALL_EVENT_SOURCES":return{};default:return e}var i,o}var Yn=0;function qn(e,t,n){return Gn(e,we(e,function(e){return function(e,t,n){return Fn(e,n)?!n.opt("lazyFetching")||!e.fetchRange||t.start<e.fetchRange.start||t.end>e.fetchRange.end:!e.latestFetchId}(e,t,n)}),t,n)}function Gn(e,t,n,r){var i={};for(var o in e){var a=e[o];t[o]?i[o]=Xn(a,n,r):i[o]=a}return i}function Xn(e,t,n){var r=n.pluginSystem.hooks.eventSourceDefs[e.sourceDefId],i=String(Yn++);return r.fetch({eventSource:e,calendar:n,range:t},function(r){var o,a,s=r.rawEvents,u=n.opt("eventSourceSuccess");e.success&&(a=e.success(s,r.xhr)),u&&(o=u(s,r.xhr)),s=a||o||s,n.dispatch({type:"RECEIVE_EVENTS",sourceId:e.sourceId,fetchId:i,fetchRange:t,rawEvents:s})},function(r){var o=n.opt("eventSourceFailure");console.warn(r.message,r),e.failure&&e.failure(r),o&&o(r),n.dispatch({type:"RECEIVE_EVENT_ERROR",sourceId:e.sourceId,fetchId:i,fetchRange:t,error:r})}),Se({},e,{isFetching:!0,latestFetchId:i})}var Jn=function(){function e(e,t){this.viewSpec=e,this.options=e.options,this.dateEnv=t.dateEnv,this.calendar=t,this.initHiddenDays()}return e.prototype.buildPrev=function(e,t){var n=this.dateEnv,r=n.subtract(n.startOf(t,e.currentRangeUnit),e.dateIncrement);return this.build(r,-1)},e.prototype.buildNext=function(e,t){var n=this.dateEnv,r=n.add(n.startOf(t,e.currentRangeUnit),e.dateIncrement);return this.build(r,1)},e.prototype.build=function(e,t,n){var r;void 0===n&&(n=!1);var i,o,a,s,u,l,c,d,f;return r=this.buildValidRange(),r=this.trimHiddenDays(r),n&&(d=e,e=null!=(f=r).start&&d<f.start?f.start:null!=f.end&&d>=f.end?new Date(f.end.valueOf()-1):d),a=this.buildCurrentRangeInfo(e,t),s=/^(year|month|week|day)$/.test(a.unit),u=this.buildRenderRange(this.trimHiddenDays(a.range),a.unit,s),l=u=this.trimHiddenDays(u),this.options.showNonCurrentDates||(l=Ve(l,a.range)),i=J(this.options.minTime),o=J(this.options.maxTime),l=Ve(l=this.adjustActiveRange(l,i,o),r),c=Fe(a.range,r),{validRange:r,currentRange:a.range,currentRangeUnit:a.unit,isRangeAllDay:s,activeRange:l,renderRange:u,minTime:i,maxTime:o,isValid:c,dateIncrement:this.buildDateIncrement(a.duration)}},e.prototype.buildValidRange=function(){return this.getRangeOption("validRange",this.calendar.getNow())||{start:null,end:null}},e.prototype.buildCurrentRangeInfo=function(e,t){var n,r=this.viewSpec,i=this.dateEnv,o=null,a=null,s=null;return r.duration?(o=r.duration,a=r.durationUnit,s=this.buildRangeFromDuration(e,t,o,a)):(n=this.options.dayCount)?(a="day",s=this.buildRangeFromDayCount(e,t,n)):(s=this.buildCustomVisibleRange(e))?a=i.greatestWholeUnit(s.start,s.end).unit:(a=ne(o=this.getFallbackDuration()).unit,s=this.buildRangeFromDuration(e,t,o,a)),{duration:o,unit:a,range:s}},e.prototype.getFallbackDuration=function(){return J({day:1})},e.prototype.adjustActiveRange=function(e,t,n){var r=this.dateEnv,i=e.start,o=e.end;return this.viewSpec.class.prototype.usesMinMaxTime&&(ee(t)<0&&(i=B(i),i=r.add(i,t)),ee(n)>1&&(o=x(o=B(o),-1),o=r.add(o,n))),{start:i,end:o}},e.prototype.buildRangeFromDuration=function(e,t,n,r){var i,o,a,s,u,l=this.dateEnv,c=this.options.dateAlignment;function d(){a=l.startOf(e,c),s=l.add(a,n),u={start:a,end:s}}return c||((i=this.options.dateIncrement)?(o=J(i),c=te(o)<te(n)?ne(o,!Q(i)).unit:r):c=r),ee(n)<=1&&this.isHiddenDay(a)&&(a=B(a=this.skipHiddenDays(a,t))),d(),this.trimHiddenDays(u)||(e=this.skipHiddenDays(e,t),d()),u},e.prototype.buildRangeFromDayCount=function(e,t,n){var r,i=this.dateEnv,o=this.options.dateAlignment,a=0,s=e;o&&(s=i.startOf(s,o)),s=B(s),r=s=this.skipHiddenDays(s,t);do{r=x(r,1),this.isHiddenDay(r)||a++}while(a<n);return{start:s,end:r}},e.prototype.buildCustomVisibleRange=function(e){var t=this.dateEnv,n=this.getRangeOption("visibleRange",t.toDate(e));return!n||null!=n.start&&null!=n.end?n:null},e.prototype.buildRenderRange=function(e,t,n){return e},e.prototype.buildDateIncrement=function(e){var t,n=this.options.dateIncrement;return n?J(n):(t=this.options.dateAlignment)?J(1,t):e||J({days:1})},e.prototype.getRangeOption=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];var r=this.options[e];return"function"==typeof r&&(r=r.apply(null,t)),r&&(r=Ue(r,this.dateEnv)),r&&(r=ge(r)),r},e.prototype.initHiddenDays=function(){var e,t=this.options.hiddenDays||[],n=[],r=0;for(!1===this.options.weekends&&t.push(0,6),e=0;e<7;e++)(n[e]=-1!==t.indexOf(e))||r++;if(!r)throw new Error("invalid hiddenDays");this.isHiddenDayHash=n},e.prototype.trimHiddenDays=function(e){var t=e.start,n=e.end;return t&&(t=this.skipHiddenDays(t)),n&&(n=this.skipHiddenDays(n,-1,!0)),null==t||null==n||t<n?{start:t,end:n}:null},e.prototype.isHiddenDay=function(e){return e instanceof Date&&(e=e.getUTCDay()),this.isHiddenDayHash[e]},e.prototype.skipHiddenDays=function(e,t,n){for(void 0===t&&(t=1),void 0===n&&(n=!1);this.isHiddenDayHash[(e.getUTCDay()+(n?t:0)+7)%7];)e=x(e,t);return e},e}();function Kn(e,t,n){for(var r=function(e,t){switch(t.type){case"SET_VIEW_TYPE":return t.viewType;default:return e}}(e.viewType,t),i=function(e,t,n,r,i){var o;switch(t.type){case"PREV":o=i.dateProfileGenerators[r].buildPrev(e,n);break;case"NEXT":o=i.dateProfileGenerators[r].buildNext(e,n);break;case"SET_DATE":e.activeRange&&Ze(e.currentRange,t.dateMarker)||(o=i.dateProfileGenerators[r].build(t.dateMarker,void 0,!0));break;case"SET_VIEW_TYPE":var a=i.dateProfileGenerators[r];if(!a)throw new Error(r?'The FullCalendar view "'+r+'" does not exist. Make sure your plugins are loaded correctly.':"No available FullCalendar view plugins.");o=a.build(t.dateMarker||n,void 0,!0)}return!o||!o.isValid||e&&(s=e,u=o,Ae(s.validRange,u.validRange)&&Ae(s.activeRange,u.activeRange)&&Ae(s.renderRange,u.renderRange)&&$(s.minTime,u.minTime)&&$(s.maxTime,u.maxTime))?e:o;var s,u}(e.dateProfile,t,e.currentDate,r,n),o=jn(e.eventSources,t,i,n),a=Se({},e,{viewType:r,dateProfile:i,currentDate:Qn(e.currentDate,t,i),eventSources:o,eventStore:St(e.eventStore,t,o,i,n),dateSelection:$n(e.dateSelection,t,n),eventSelection:er(e.eventSelection,t),eventDrag:tr(e.eventDrag,t,o,n),eventResize:nr(e.eventResize,t,o,n),eventSourceLoadingLevel:rr(o),loadingLevel:rr(o)}),s=0,u=n.pluginSystem.hooks.reducers;s<u.length;s++){a=(0,u[s])(a,t,n)}return a}function Qn(e,t,n){switch(t.type){case"PREV":case"NEXT":return Ze(n.currentRange,e)?e:n.currentRange.start;case"SET_DATE":case"SET_VIEW_TYPE":var r=t.dateMarker||e;return n.activeRange&&!Ze(n.activeRange,r)?n.currentRange.start:r;default:return e}}function $n(e,t,n){switch(t.type){case"SELECT_DATES":return t.selection;case"UNSELECT_DATES":return null;default:return e}}function er(e,t){switch(t.type){case"SELECT_EVENT":return t.eventInstanceId;case"UNSELECT_EVENT":return"";default:return e}}function tr(e,t,n,r){switch(t.type){case"SET_EVENT_DRAG":var i=t.state;return{affectedEvents:i.affectedEvents,mutatedEvents:i.mutatedEvents,isEvent:i.isEvent,origSeg:i.origSeg};case"UNSET_EVENT_DRAG":return null;default:return e}}function nr(e,t,n,r){switch(t.type){case"SET_EVENT_RESIZE":var i=t.state;return{affectedEvents:i.affectedEvents,mutatedEvents:i.mutatedEvents,isEvent:i.isEvent,origSeg:i.origSeg};case"UNSET_EVENT_RESIZE":return null;default:return e}}function rr(e){var t=0;for(var n in e)e[n].isFetching&&t++;return t}var ir={start:null,end:null,allDay:Boolean};function or(e,t,n){var r=function(e,t){var n={},r=he(e,ir,{},n),i=r.start?t.createMarkerMeta(r.start):null,o=r.end?t.createMarkerMeta(r.end):null,a=r.allDay;null==a&&(a=i&&i.isTimeUnspecified&&(!o||o.isTimeUnspecified));return n.range={start:i?i.marker:null,end:o?o.marker:null},n.allDay=a,n}(e,t),i=r.range;if(!i.start)return null;if(!i.end){if(null==n)return null;i.end=t.add(i.start,n)}return r}function ar(e,t,n){var r=Wt({editable:!1},"",e.allDay,!0,n);return{def:r,ui:gt(r,t),instance:Zt(r.defId,e.range),range:e.range,isStart:!0,isEnd:!0}}function sr(e,t,n,r){if(t[e])return t[e];var i=function(e,t,n,r){var i=n[e],o=r[e],a=function(e){return i&&null!==i[e]?i[e]:o&&null!==o[e]?o[e]:null},s=a("class"),u=a("superType");!u&&s&&(u=ur(s,r)||ur(s,n));var l=null;if(u){if(u===e)throw new Error("Can't have a custom view type that references itself");l=sr(u,t,n,r)}!s&&l&&(s=l.class);if(!s)return null;return{type:e,class:s,defaults:Se({},l?l.defaults:{},i?i.options:{}),overrides:Se({},l?l.overrides:{},o?o.options:{})}}(e,t,n,r);return i&&(t[e]=i),i}function ur(e,t){var n=Object.getPrototypeOf(e.prototype);for(var r in t){var i=t[r];if(i.class&&i.class.prototype===n)return r}return""}function lr(e){return Re(e,dr)}var cr={type:String,class:null};function dr(e){"function"==typeof e&&(e={class:e});var t={},n=he(e,cr,{},t);return{superType:n.type,class:n.class,options:t}}function fr(e,t){var n=lr(e),r=lr(t.overrides.views);return Re(function(e,t){var n,r={};for(n in e)sr(n,r,e,t);for(n in t)sr(n,r,e,t);return r}(n,r),function(e){return function(e,t,n){var r=e.overrides.duration||e.defaults.duration||n.dynamicOverrides.duration||n.overrides.duration,i=null,o="",a="",s={};if(r&&(i=J(r))){var u=ne(i,!Q(r));o=u.unit,1===u.value&&(a=o,s=t[o]?t[o].options:{})}var l=function(t){var n=t.buttonText||{},r=e.defaults.buttonTextKey;return null!=r&&null!=n[r]?n[r]:null!=n[e.type]?n[e.type]:null!=n[a]?n[a]:void 0};return{type:e.type,class:e.class,duration:i,durationUnit:o,singleUnit:a,options:Se({},Rn,e.defaults,n.dirDefaults,n.localeDefaults,n.overrides,s,e.overrides,n.dynamicOverrides),buttonTextOverride:l(n.dynamicOverrides)||l(n.overrides)||e.overrides.buttonText,buttonTextDefault:l(n.localeDefaults)||l(n.dirDefaults)||e.defaults.buttonText||l(Rn)||e.type}}(e,r,t)})}var pr=function(e){function t(t,n){var i=e.call(this,t)||this;return i._renderLayout=qt(i.renderLayout,i.unrenderLayout),i._updateTitle=qt(i.updateTitle,null,[i._renderLayout]),i._updateActiveButton=qt(i.updateActiveButton,null,[i._renderLayout]),i._updateToday=qt(i.updateToday,null,[i._renderLayout]),i._updatePrev=qt(i.updatePrev,null,[i._renderLayout]),i._updateNext=qt(i.updateNext,null,[i._renderLayout]),i.el=r("div",{className:"fc-toolbar "+n}),i}return Ee(t,e),t.prototype.destroy=function(){e.prototype.destroy.call(this),this._renderLayout.unrender(),c(this.el)},t.prototype.render=function(e){this._renderLayout(e.layout),this._updateTitle(e.title),this._updateActiveButton(e.activeButton),this._updateToday(e.isTodayEnabled),this._updatePrev(e.isPrevEnabled),this._updateNext(e.isNextEnabled)},t.prototype.renderLayout=function(e){var t=this.el;this.viewsWithButtons=[],s(t,this.renderSection("left",e.left)),s(t,this.renderSection("center",e.center)),s(t,this.renderSection("right",e.right))},t.prototype.unrenderLayout=function(){this.el.innerHTML=""},t.prototype.renderSection=function(e,t){var n=this,o=this.theme,a=this.calendar,u=a.optionsManager,l=a.viewSpecs,c=r("div",{className:"fc-"+e}),d=u.computed.customButtons||{},f=u.overrides.buttonText||{},p=u.computed.buttonText||{};return t&&t.split(" ").forEach(function(e,t){var r,u=[],h=!0;if(e.split(",").forEach(function(e,t){var r,s,c,v,g,y,m,E,S;"title"===e?(u.push(i("<h2> </h2>")),h=!1):((r=d[e])?(c=function(e){r.click&&r.click.call(E,e)},(v=o.getCustomButtonIconClass(r))||(v=o.getIconClass(e))||(g=r.text)):(s=l[e])?(n.viewsWithButtons.push(e),c=function(){a.changeView(e)},(g=s.buttonTextOverride)||(v=o.getIconClass(e))||(g=s.buttonTextDefault)):a[e]&&(c=function(){a[e]()},(g=f[e])||(v=o.getIconClass(e))||(g=p[e])),c&&(m=["fc-"+e+"-button",o.getClass("button")],g?(y=Ot(g),S=""):v&&(y="<span class='"+v+"'></span>",S=' aria-label="'+e+'"'),(E=i('<button type="button" class="'+m.join(" ")+'"'+S+">"+y+"</button>")).addEventListener("click",c),u.push(E)))}),u.length>1){r=document.createElement("div");var v=o.getClass("buttonGroup");h&&v&&r.classList.add(v),s(r,u),c.appendChild(r)}else s(c,u)}),c},t.prototype.updateToday=function(e){this.toggleButtonEnabled("today",e)},t.prototype.updatePrev=function(e){this.toggleButtonEnabled("prev",e)},t.prototype.updateNext=function(e){this.toggleButtonEnabled("next",e)},t.prototype.updateTitle=function(e){v(this.el,"h2").forEach(function(t){t.innerText=e})},t.prototype.updateActiveButton=function(e){var t=this.theme.getClass("buttonActive");v(this.el,"button").forEach(function(n){e&&n.classList.contains("fc-"+e+"-button")?n.classList.add(t):n.classList.remove(t)})},t.prototype.toggleButtonEnabled=function(e,t){v(this.el,".fc-"+e+"-button").forEach(function(e){e.disabled=!t})},t}(fn),hr=function(e){function t(t,n){var i=e.call(this,t)||this;i._renderToolbars=qt(i.renderToolbars),i.buildViewPropTransformers=Ye(gr),i.el=n,u(n,i.contentEl=r("div",{className:"fc-view-container"}));for(var o=i.calendar,a=0,s=o.pluginSystem.hooks.viewContainerModifiers;a<s.length;a++){(0,s[a])(i.contentEl,o)}return i.toggleElClassNames(!0),i.computeTitle=Ye(vr),i.parseBusinessHours=Ye(function(e){return Yt(e,i.calendar)}),i}return Ee(t,e),t.prototype.destroy=function(){this.header&&this.header.destroy(),this.footer&&this.footer.destroy(),this.view&&this.view.destroy(),c(this.contentEl),this.toggleElClassNames(!1),e.prototype.destroy.call(this)},t.prototype.toggleElClassNames=function(e){var t=this.el.classList,n="fc-"+this.opt("dir"),r=this.theme.getClass("widget");e?(t.add("fc"),t.add(n),t.add(r)):(t.remove("fc"),t.remove(n),t.remove(r))},t.prototype.render=function(e){this.freezeHeight();var t=this.computeTitle(e.dateProfile,e.viewSpec.options);this._renderToolbars(e.viewSpec,e.dateProfile,e.currentDate,e.dateProfileGenerator,t),this.renderView(e,t),this.updateSize(),this.thawHeight()},t.prototype.renderToolbars=function(e,t,n,r,i){var o=this.opt("header"),a=this.opt("footer"),l=this.calendar.getNow(),c=r.build(l),d=r.buildPrev(t,n),f=r.buildNext(t,n),p={title:i,activeButton:e.type,isTodayEnabled:c.isValid&&!Ze(t.currentRange,l),isPrevEnabled:d.isValid,isNextEnabled:f.isValid};o?(this.header||(this.header=new pr(this.context,"fc-header-toolbar"),u(this.el,this.header.el)),this.header.receiveProps(Se({layout:o},p))):this.header&&(this.header.destroy(),this.header=null),a?(this.footer||(this.footer=new pr(this.context,"fc-footer-toolbar"),s(this.el,this.footer.el)),this.footer.receiveProps(Se({layout:a},p))):this.footer&&(this.footer.destroy(),this.footer=null)},t.prototype.renderView=function(e,t){var n=this.view,r=e.viewSpec,i=e.dateProfileGenerator;n&&n.viewSpec===r?n.addScroll(n.queryScroll()):(n&&n.destroy(),n=this.view=new r.class({calendar:this.calendar,view:null,dateEnv:this.dateEnv,theme:this.theme,options:r.options},r,i,this.contentEl)),n.title=t;for(var o={dateProfile:e.dateProfile,businessHours:this.parseBusinessHours(r.options.businessHours),eventStore:e.eventStore,eventUiBases:e.eventUiBases,dateSelection:e.dateSelection,eventSelection:e.eventSelection,eventDrag:e.eventDrag,eventResize:e.eventResize},a=0,s=this.buildViewPropTransformers(this.calendar.pluginSystem.hooks.viewPropsTransformers);a<s.length;a++){var u=s[a];Se(o,u.transform(o,r,e,n))}n.receiveProps(o)},t.prototype.updateSize=function(e){void 0===e&&(e=!1);var t=this.view;e&&t.addScroll(t.queryScroll()),(e||null==this.isHeightAuto)&&this.computeHeightVars(),t.updateSize(e,this.viewHeight,this.isHeightAuto),t.updateNowIndicator(),t.popScroll(e)},t.prototype.computeHeightVars=function(){var e=this.calendar,t=e.opt("height"),n=e.opt("contentHeight");if(this.isHeightAuto="auto"===t||"auto"===n,"number"==typeof n)this.viewHeight=n;else if("function"==typeof n)this.viewHeight=n();else if("number"==typeof t)this.viewHeight=t-this.queryToolbarsHeight();else if("function"==typeof t)this.viewHeight=t()-this.queryToolbarsHeight();else if("parent"===t){var r=this.el.parentNode;this.viewHeight=r.getBoundingClientRect().height-this.queryToolbarsHeight()}else this.viewHeight=Math.round(this.contentEl.getBoundingClientRect().width/Math.max(e.opt("aspectRatio"),.5))},t.prototype.queryToolbarsHeight=function(){var e=0;return this.header&&(e+=I(this.header.el)),this.footer&&(e+=I(this.footer.el)),e},t.prototype.freezeHeight=function(){y(this.el,{height:this.el.getBoundingClientRect().height,overflow:"hidden"})},t.prototype.thawHeight=function(){y(this.el,{height:"",overflow:""})},t}(fn);function vr(e,t){var n;return n=/^(year|month)$/.test(e.currentRangeUnit)?e.currentRange:e.activeRange,this.dateEnv.formatRange(n.start,n.end,ot(t.titleFormat||function(e){var t=e.currentRangeUnit;if("year"===t)return{year:"numeric"};if("month"===t)return{year:"numeric",month:"long"};var n=L(e.currentRange.start,e.currentRange.end);return null!==n&&n>1?{year:"numeric",month:"short",day:"numeric"}:{year:"numeric",month:"long",day:"numeric"}}(e),t.titleRangeSeparator),{isEndExclusive:e.isRangeAllDay})}function gr(e){return e.map(function(e){return new e})}var yr=function(){function e(e){this.component=e.component}return e.prototype.destroy=function(){},e}();var mr={},Er=function(e){function t(t){var n=e.call(this,t)||this;n.handleSegClick=function(e,t){var r=n.component,i=ht(t);if(i&&r.isValidSegDownEl(e.target)){var o=p(e.target,".fc-has-url"),a=o?o.querySelector("a[href]").href:"";r.publiclyTrigger("eventClick",[{el:t,event:new ct(r.calendar,i.eventRange.def,i.eventRange.instance),jsEvent:e,view:r.view}]),a&&!e.defaultPrevented&&(window.location.href=a)}};var r=t.component;return n.destroy=O(r.el,"click",r.fgSegSelector+","+r.bgSegSelector,n.handleSegClick),n}return Ee(t,e),t}(yr),Sr=function(e){function t(t){var n=e.call(this,t)||this;n.handleEventElRemove=function(e){e===n.currentSegEl&&n.handleSegLeave(null,n.currentSegEl)},n.handleSegEnter=function(e,t){ht(t)&&(t.classList.add("fc-allow-mouse-resize"),n.currentSegEl=t,n.triggerEvent("eventMouseEnter",e,t))},n.handleSegLeave=function(e,t){n.currentSegEl&&(t.classList.remove("fc-allow-mouse-resize"),n.currentSegEl=null,n.triggerEvent("eventMouseLeave",e,t))};var r,i,o,a,s,u=t.component;return n.removeHoverListeners=(r=u.el,i=u.fgSegSelector+","+u.bgSegSelector,o=n.handleSegEnter,a=n.handleSegLeave,O(r,"mouseover",i,function(e,t){if(t!==s){s=t,o(e,t);var n=function(e){s=null,a(e,t),t.removeEventListener("mouseleave",n)};t.addEventListener("mouseleave",n)}})),u.calendar.on("eventElRemove",n.handleEventElRemove),n}return Ee(t,e),t.prototype.destroy=function(){this.removeHoverListeners(),this.component.calendar.off("eventElRemove",this.handleEventElRemove)},t.prototype.triggerEvent=function(e,t,n){var r=this.component,i=ht(n);t&&!r.isValidSegDownEl(t.target)||r.publiclyTrigger(e,[{el:n,event:new ct(this.component.calendar,i.eventRange.def,i.eventRange.instance),jsEvent:t,view:r.view}])},t}(yr),br=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return Ee(t,e),t}(cn);br.prototype.classes={widget:"fc-unthemed",widgetHeader:"fc-widget-header",widgetContent:"fc-widget-content",buttonGroup:"fc-button-group",button:"fc-button fc-button-primary",buttonActive:"fc-button-active",popoverHeader:"fc-widget-header",popoverContent:"fc-widget-content",headerRow:"fc-widget-header",dayRow:"fc-widget-content",listView:"fc-widget-content"},br.prototype.baseIconClass="fc-icon",br.prototype.iconClasses={close:"fc-icon-x",prev:"fc-icon-chevron-left",next:"fc-icon-chevron-right",prevYear:"fc-icon-chevrons-left",nextYear:"fc-icon-chevrons-right"},br.prototype.iconOverrideOption="buttonIcons",br.prototype.iconOverrideCustomButtonOption="icon",br.prototype.iconOverridePrefix="fc-icon-";var Dr=function(){function e(e,t){var n=this;this.parseRawLocales=Ye(On),this.buildLocale=Ye(_n),this.buildDateEnv=Ye(Tr),this.buildTheme=Ye(wr),this.buildEventUiSingleBase=Ye(this._buildEventUiSingleBase),this.buildSelectionConfig=Ye(this._buildSelectionConfig),this.buildEventUiBySource=qe(Ir,Me),this.buildEventUiBases=Ye(Cr),this.interactionsStore={},this.actionQueue=[],this.isReducing=!1,this.needsRerender=!1,this.needsFullRerender=!1,this.isRendering=!1,this.renderingPauseDepth=0,this.buildDelayedRerender=Ye(Rr),this.afterSizingTriggers={},this.isViewUpdated=!1,this.isDatesUpdated=!1,this.isEventsUpdated=!1,this.el=e,this.optionsManager=new xn(t||{}),this.pluginSystem=new gn,this.addPluginInputs(this.optionsManager.computed.plugins||[]),this.handleOptions(this.optionsManager.computed),this.publiclyTrigger("_init"),this.hydrate(),this.calendarInteractions=this.pluginSystem.hooks.calendarInteractions.map(function(e){return new e(n)})}return e.prototype.addPluginInputs=function(e){for(var t=function(e){for(var t=[],n=0,r=e;n<r.length;n++){var i=r[n];if("string"==typeof i){var o="FullCalendar"+ue(i);window[o]?t.push(window[o].default):console.warn("Plugin file not loaded for "+i)}else t.push(i)}return Mn.concat(t)}(e),n=0,r=t;n<r.length;n++){var i=r[n];this.pluginSystem.add(i)}},Object.defineProperty(e.prototype,"view",{get:function(){return this.component?this.component.view:null},enumerable:!0,configurable:!0}),e.prototype.render=function(){this.component?this.requestRerender(!0):(this.renderableEventStore={defs:{},instances:{}},this.bindHandlers(),this.executeRender())},e.prototype.destroy=function(){if(this.component){this.unbindHandlers(),this.component.destroy(),this.component=null;for(var e=0,t=this.calendarInteractions;e<t.length;e++){t[e].destroy()}this.publiclyTrigger("_destroyed")}},e.prototype.bindHandlers=function(){var e=this;this.removeNavLinkListener=O(this.el,"click","a[data-goto]",function(t,n){var r=n.getAttribute("data-goto");r=r?JSON.parse(r):{};var i=e.dateEnv,o=i.createMarker(r.date),a=r.type,s=e.viewOpt("navLink"+ue(a)+"Click");"function"==typeof s?s(i.toDate(o),t):("string"==typeof s&&(a=s),e.zoomTo(o,a))}),this.opt("handleWindowResize")&&window.addEventListener("resize",this.windowResizeProxy=pe(this.windowResize.bind(this),this.opt("windowResizeDelay")))},e.prototype.unbindHandlers=function(){this.removeNavLinkListener(),this.windowResizeProxy&&(window.removeEventListener("resize",this.windowResizeProxy),this.windowResizeProxy=null)},e.prototype.hydrate=function(){var e=this;this.state=this.buildInitialState();var t=this.opt("eventSources")||[],n=this.opt("events"),r=[];n&&t.unshift(n);for(var i=0,o=t;i<o.length;i++){var a=Wn(o[i],this);a&&r.push(a)}this.batchRendering(function(){e.dispatch({type:"INIT"}),e.dispatch({type:"ADD_EVENT_SOURCES",sources:r}),e.dispatch({type:"SET_VIEW_TYPE",viewType:e.opt("defaultView")||e.pluginSystem.hooks.defaultView})})},e.prototype.buildInitialState=function(){return{viewType:null,loadingLevel:0,eventSourceLoadingLevel:0,currentDate:this.getInitialDate(),dateProfile:null,eventSources:{},eventStore:{defs:{},instances:{}},dateSelection:null,eventSelection:"",eventDrag:null,eventResize:null}},e.prototype.dispatch=function(e){if(this.actionQueue.push(e),!this.isReducing){this.isReducing=!0;for(var t=this.state;this.actionQueue.length;)this.state=this.reduce(this.state,this.actionQueue.shift(),this);var n=this.state;this.isReducing=!1,!t.loadingLevel&&n.loadingLevel?this.publiclyTrigger("loading",[!0]):t.loadingLevel&&!n.loadingLevel&&this.publiclyTrigger("loading",[!1]);var r=this.component&&this.component.view;(t.eventStore!==n.eventStore||this.needsFullRerender)&&t.eventStore&&(this.isEventsUpdated=!0),(t.dateProfile!==n.dateProfile||this.needsFullRerender)&&(t.dateProfile&&r&&this.publiclyTrigger("datesDestroy",[{view:r,el:r.el}]),this.isDatesUpdated=!0),(t.viewType!==n.viewType||this.needsFullRerender)&&(t.viewType&&r&&this.publiclyTrigger("viewSkeletonDestroy",[{view:r,el:r.el}]),this.isViewUpdated=!0),this.requestRerender()}},e.prototype.reduce=function(e,t,n){return Kn(e,t,n)},e.prototype.requestRerender=function(e){void 0===e&&(e=!1),this.needsRerender=!0,this.needsFullRerender=this.needsFullRerender||e,this.delayedRerender()},e.prototype.tryRerender=function(){this.component&&this.needsRerender&&!this.renderingPauseDepth&&!this.isRendering&&this.executeRender()},e.prototype.batchRendering=function(e){this.renderingPauseDepth++,e(),this.renderingPauseDepth--,this.needsRerender&&this.requestRerender()},e.prototype.executeRender=function(){var e=this.needsFullRerender;this.needsRerender=!1,this.needsFullRerender=!1,this.isRendering=!0,this.renderComponent(e),this.isRendering=!1,this.needsRerender&&this.delayedRerender()},e.prototype.renderComponent=function(e){var t=this.state,n=this.component,r=t.viewType,i=this.viewSpecs[r],o=e&&n?n.view.queryScroll():null;if(!i)throw new Error('View type "'+r+'" is not valid');var a=this.renderableEventStore=t.eventSourceLoadingLevel&&!this.opt("progressiveEventRendering")?this.renderableEventStore:t.eventStore,s=this.buildEventUiSingleBase(i.options),u=this.buildEventUiBySource(t.eventSources),l=this.eventUiBases=this.buildEventUiBases(a.defs,s,u);!e&&n||(n&&(n.freezeHeight(),n.destroy()),n=this.component=new hr({calendar:this,view:null,dateEnv:this.dateEnv,theme:this.theme,options:this.optionsManager.computed},this.el),this.isViewUpdated=!0,this.isDatesUpdated=!0,this.isEventsUpdated=!0),n.receiveProps(Se({},t,{viewSpec:i,dateProfile:t.dateProfile,dateProfileGenerator:this.dateProfileGenerators[r],eventStore:a,eventUiBases:l,dateSelection:t.dateSelection,eventSelection:t.eventSelection,eventDrag:t.eventDrag,eventResize:t.eventResize})),o&&n.view.applyScroll(o,!1),this.isViewUpdated&&(this.isViewUpdated=!1,this.publiclyTrigger("viewSkeletonRender",[{view:n.view,el:n.view.el}])),this.isDatesUpdated&&(this.isDatesUpdated=!1,this.publiclyTrigger("datesRender",[{view:n.view,el:n.view.el}])),this.isEventsUpdated&&(this.isEventsUpdated=!1),this.releaseAfterSizingTriggers()},e.prototype.setOption=function(e,t){var n;this.mutateOptions(((n={})[e]=t,n),[],!0)},e.prototype.getOption=function(e){return this.optionsManager.computed[e]},e.prototype.opt=function(e){return this.optionsManager.computed[e]},e.prototype.viewOpt=function(e){return this.viewOpts()[e]},e.prototype.viewOpts=function(){return this.viewSpecs[this.state.viewType].options},e.prototype.mutateOptions=function(e,t,n,r){var i=this,o=this.pluginSystem.hooks.optionChangeHandlers,a={},s={},u=this.dateEnv,l=!1,c=!1,d=Boolean(t.length);for(var f in e)o[f]?s[f]=e[f]:a[f]=e[f];for(var p in a)/^(height|contentHeight|aspectRatio)$/.test(p)?c=!0:/^(defaultDate|defaultView)$/.test(p)||(d=!0,"timeZone"===p&&(l=!0));this.optionsManager.mutate(a,t,n),d&&(this.handleOptions(this.optionsManager.computed),this.needsFullRerender=!0),this.batchRendering(function(){if(d?(l&&i.dispatch({type:"CHANGE_TIMEZONE",oldDateEnv:u}),i.dispatch({type:"SET_VIEW_TYPE",viewType:i.state.viewType})):c&&i.updateSize(),r)for(var e in s)o[e](s[e],i,r)})},e.prototype.handleOptions=function(e){var t=this,n=this.pluginSystem.hooks;this.defaultAllDayEventDuration=J(e.defaultAllDayEventDuration),this.defaultTimedEventDuration=J(e.defaultTimedEventDuration),this.delayedRerender=this.buildDelayedRerender(e.rerenderDelay),this.theme=this.buildTheme(e);var r=this.parseRawLocales(e.locales);this.availableRawLocales=r.map;var i=this.buildLocale(e.locale||r.defaultCode,r.map);this.dateEnv=this.buildDateEnv(i,e.timeZone,n.namedTimeZonedImpl,e.firstDay,e.weekNumberCalculation,e.weekLabel,n.cmdFormatter),this.selectionConfig=this.buildSelectionConfig(e),this.viewSpecs=fr(n.views,this.optionsManager),this.dateProfileGenerators=Re(this.viewSpecs,function(e){return new e.class.prototype.dateProfileGeneratorClass(e,t)})},e.prototype.getAvailableLocaleCodes=function(){return Object.keys(this.availableRawLocales)},e.prototype._buildSelectionConfig=function(e){return Nt("select",e,this)},e.prototype._buildEventUiSingleBase=function(e){return e.editable&&(e=Se({},e,{eventEditable:!0})),Nt("event",e,this)},e.prototype.hasPublicHandlers=function(e){return this.hasHandlers(e)||this.opt(e)},e.prototype.publiclyTrigger=function(e,t){var n=this.opt(e);if(this.triggerWith(e,this,t),n)return n.apply(this,t)},e.prototype.publiclyTriggerAfterSizing=function(e,t){var n=this.afterSizingTriggers;(n[e]||(n[e]=[])).push(t)},e.prototype.releaseAfterSizingTriggers=function(){var e=this.afterSizingTriggers;for(var t in e)for(var n=0,r=e[t];n<r.length;n++){var i=r[n];this.publiclyTrigger(t,i)}this.afterSizingTriggers={}},e.prototype.isValidViewType=function(e){return Boolean(this.viewSpecs[e])},e.prototype.changeView=function(e,t){var n=null;t&&(t.start&&t.end?(this.optionsManager.mutate({visibleRange:t},[]),this.handleOptions(this.optionsManager.computed)):n=this.dateEnv.createMarker(t)),this.unselect(),this.dispatch({type:"SET_VIEW_TYPE",viewType:e,dateMarker:n})},e.prototype.zoomTo=function(e,t){var n;t=t||"day",n=this.viewSpecs[t]||this.getUnitViewSpec(t),this.unselect(),n?this.dispatch({type:"SET_VIEW_TYPE",viewType:n.type,dateMarker:e}):this.dispatch({type:"SET_DATE",dateMarker:e})},e.prototype.getUnitViewSpec=function(e){var t,n,r=this.component,i=[];for(var o in r.header&&i.push.apply(i,r.header.viewsWithButtons),r.footer&&i.push.apply(i,r.footer.viewsWithButtons),this.viewSpecs)i.push(o);for(t=0;t<i.length;t++)if((n=this.viewSpecs[i[t]])&&n.singleUnit===e)return n},e.prototype.getInitialDate=function(){var e=this.opt("defaultDate");return null!=e?this.dateEnv.createMarker(e):this.getNow()},e.prototype.prev=function(){this.unselect(),this.dispatch({type:"PREV"})},e.prototype.next=function(){this.unselect(),this.dispatch({type:"NEXT"})},e.prototype.prevYear=function(){this.unselect(),this.dispatch({type:"SET_DATE",dateMarker:this.dateEnv.addYears(this.state.currentDate,-1)})},e.prototype.nextYear=function(){this.unselect(),this.dispatch({type:"SET_DATE",dateMarker:this.dateEnv.addYears(this.state.currentDate,1)})},e.prototype.today=function(){this.unselect(),this.dispatch({type:"SET_DATE",dateMarker:this.getNow()})},e.prototype.gotoDate=function(e){this.unselect(),this.dispatch({type:"SET_DATE",dateMarker:this.dateEnv.createMarker(e)})},e.prototype.incrementDate=function(e){var t=J(e);t&&(this.unselect(),this.dispatch({type:"SET_DATE",dateMarker:this.dateEnv.add(this.state.currentDate,t)}))},e.prototype.getDate=function(){return this.dateEnv.toDate(this.state.currentDate)},e.prototype.formatDate=function(e,t){var n=this.dateEnv;return n.format(n.createMarker(e),ot(t))},e.prototype.formatRange=function(e,t,n){var r=this.dateEnv;return r.formatRange(r.createMarker(e),r.createMarker(t),ot(n,this.opt("defaultRangeSeparator")),n)},e.prototype.formatIso=function(e,t){var n=this.dateEnv;return n.formatIso(n.createMarker(e),{omitTime:t})},e.prototype.windowResize=function(e){!this.isHandlingWindowResize&&this.component&&e.target===window&&(this.isHandlingWindowResize=!0,this.updateSize(),this.publiclyTrigger("windowResize",[this.view]),this.isHandlingWindowResize=!1)},e.prototype.updateSize=function(){this.component&&this.component.updateSize(!0)},e.prototype.registerInteractiveComponent=function(e,t){var n=function(e,t){return{component:e,el:t.el,useEventCenter:null==t.useEventCenter||t.useEventCenter}}(e,t),r=[Er,Sr].concat(this.pluginSystem.hooks.componentInteractions).map(function(e){return new e(n)});this.interactionsStore[e.uid]=r,mr[e.uid]=n},e.prototype.unregisterInteractiveComponent=function(e){for(var t=0,n=this.interactionsStore[e.uid];t<n.length;t++){n[t].destroy()}delete this.interactionsStore[e.uid],delete mr[e.uid]},e.prototype.select=function(e,t){var n=or(null==t?null!=e.start?e:{start:e,end:null}:{start:e,end:t},this.dateEnv,J({days:1}));n&&(this.dispatch({type:"SELECT_DATES",selection:n}),this.triggerDateSelect(n))},e.prototype.unselect=function(e){this.state.dateSelection&&(this.dispatch({type:"UNSELECT_DATES"}),this.triggerDateUnselect(e))},e.prototype.triggerDateSelect=function(e,t){var n=Se({},this.buildDateSpanApi(e),{jsEvent:t?t.origEvent:null,view:this.view});this.publiclyTrigger("select",[n])},e.prototype.triggerDateUnselect=function(e){this.publiclyTrigger("unselect",[{jsEvent:e?e.origEvent:null,view:this.view}])},e.prototype.triggerDateClick=function(e,t,n,r){var i=Se({},this.buildDatePointApi(e),{dayEl:t,jsEvent:r,view:n});this.publiclyTrigger("dateClick",[i])},e.prototype.buildDatePointApi=function(e){for(var t,n,r={},i=0,o=this.pluginSystem.hooks.datePointTransforms;i<o.length;i++){var a=o[i];Se(r,a(e,this))}return Se(r,(t=e,{date:(n=this.dateEnv).toDate(t.range.start),dateStr:n.formatIso(t.range.start,{omitTime:t.allDay}),allDay:t.allDay})),r},e.prototype.buildDateSpanApi=function(e){for(var t,n,r={},i=0,o=this.pluginSystem.hooks.dateSpanTransforms;i<o.length;i++){var a=o[i];Se(r,a(e,this))}return Se(r,(t=e,{start:(n=this.dateEnv).toDate(t.range.start),end:n.toDate(t.range.end),startStr:n.formatIso(t.range.start,{omitTime:t.allDay}),endStr:n.formatIso(t.range.end,{omitTime:t.allDay}),allDay:t.allDay})),r},e.prototype.getNow=function(){var e=this.opt("now");return"function"==typeof e&&(e=e()),null==e?this.dateEnv.createNowMarker():this.dateEnv.createMarker(e)},e.prototype.getDefaultEventEnd=function(e,t){var n=t;return e?(n=B(n),n=this.dateEnv.add(n,this.defaultAllDayEventDuration)):n=this.dateEnv.add(n,this.defaultTimedEventDuration),n},e.prototype.addEvent=function(e,t){if(e instanceof ct){var n=e._def,r=e._instance;return this.state.eventStore.defs[n.defId]||this.dispatch({type:"ADD_EVENTS",eventStore:Oe({def:n,instance:r})}),e}var i;if(t instanceof lt)i=t.internalEventSource.sourceId;else if(null!=t){var o=this.getEventSourceById(t);if(!o)return console.warn('Could not find an event source with ID "'+t+'"'),null;i=o.internalEventSource.sourceId}var a=Ft(e,i,this);return a?(this.dispatch({type:"ADD_EVENTS",eventStore:Oe(a)}),new ct(this,a.def,a.def.recurringDef?null:a.instance)):null},e.prototype.getEventById=function(e){var t=this.state.eventStore,n=t.defs,r=t.instances;for(var i in e=String(e),n){var o=n[i];if(o.publicId===e){if(o.recurringDef)return new ct(this,o,null);for(var a in r){var s=r[a];if(s.defId===o.defId)return new ct(this,o,s)}}}return null},e.prototype.getEvents=function(){var e=this.state.eventStore,t=e.defs,n=e.instances,r=[];for(var i in n){var o=n[i],a=t[o.defId];r.push(new ct(this,a,o))}return r},e.prototype.removeAllEvents=function(){this.dispatch({type:"REMOVE_ALL_EVENTS"})},e.prototype.rerenderEvents=function(){this.dispatch({type:"RESET_EVENTS"})},e.prototype.getEventSources=function(){var e=this.state.eventSources,t=[];for(var n in e)t.push(new lt(this,e[n]));return t},e.prototype.getEventSourceById=function(e){var t=this.state.eventSources;for(var n in e=String(e),t)if(t[n].publicId===e)return new lt(this,t[n]);return null},e.prototype.addEventSource=function(e){if(e instanceof lt)return this.state.eventSources[e.internalEventSource.sourceId]||this.dispatch({type:"ADD_EVENT_SOURCES",sources:[e.internalEventSource]}),e;var t=Wn(e,this);return t?(this.dispatch({type:"ADD_EVENT_SOURCES",sources:[t]}),new lt(this,t)):null},e.prototype.removeAllEventSources=function(){this.dispatch({type:"REMOVE_ALL_EVENT_SOURCES"})},e.prototype.refetchEvents=function(){this.dispatch({type:"FETCH_EVENT_SOURCES"})},e.prototype.scrollToTime=function(e){var t=J(e);t&&this.component.view.scrollToDuration(t)},e}();function Tr(e,t,n,r,i,o,a){return new Bn({calendarSystem:"gregory",timeZone:t,namedTimeZoneImpl:n,locale:e,weekNumberCalculation:i,firstDay:r,weekLabel:o,cmdFormatter:a})}function wr(e){return new(this.pluginSystem.hooks.themeClasses[e.themeSystem]||br)(e)}function Rr(e){var t=this.tryRerender.bind(this);return null!=e&&(t=pe(t,e)),t}function Ir(e){return Re(e,function(e){return e.ui})}function Cr(e,t,n){var r={"":t};for(var i in e){var o=e[i];o.sourceId&&n[o.sourceId]&&(r[i]=n[o.sourceId])}return r}tn.mixInto(Dr);var Mr=function(e){function t(t,n,i,o){var a=e.call(this,t,r("div",{className:"fc-view fc-"+n.type+"-view"}),!0)||this;return a.renderDatesMem=qt(a.renderDatesWrap,a.unrenderDatesWrap),a.renderBusinessHoursMem=qt(a.renderBusinessHours,a.unrenderBusinessHours,[a.renderDatesMem]),a.renderDateSelectionMem=qt(a.renderDateSelectionWrap,a.unrenderDateSelectionWrap,[a.renderDatesMem]),a.renderEventsMem=qt(a.renderEvents,a.unrenderEvents,[a.renderDatesMem]),a.renderEventSelectionMem=qt(a.renderEventSelectionWrap,a.unrenderEventSelectionWrap,[a.renderEventsMem]),a.renderEventDragMem=qt(a.renderEventDragWrap,a.unrenderEventDragWrap,[a.renderDatesMem]),a.renderEventResizeMem=qt(a.renderEventResizeWrap,a.unrenderEventResizeWrap,[a.renderDatesMem]),a.viewSpec=n,a.dateProfileGenerator=i,a.type=n.type,a.eventOrderSpecs=ie(a.opt("eventOrder")),a.nextDayThreshold=J(a.opt("nextDayThreshold")),o.appendChild(a.el),a.initialize(),a}return Ee(t,e),t.prototype.initialize=function(){},Object.defineProperty(t.prototype,"activeStart",{get:function(){return this.dateEnv.toDate(this.props.dateProfile.activeRange.start)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"activeEnd",{get:function(){return this.dateEnv.toDate(this.props.dateProfile.activeRange.end)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"currentStart",{get:function(){return this.dateEnv.toDate(this.props.dateProfile.currentRange.start)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"currentEnd",{get:function(){return this.dateEnv.toDate(this.props.dateProfile.currentRange.end)},enumerable:!0,configurable:!0}),t.prototype.render=function(e){this.renderDatesMem(e.dateProfile),this.renderBusinessHoursMem(e.businessHours),this.renderDateSelectionMem(e.dateSelection),this.renderEventsMem(e.eventStore),this.renderEventSelectionMem(e.eventSelection),this.renderEventDragMem(e.eventDrag),this.renderEventResizeMem(e.eventResize)},t.prototype.destroy=function(){e.prototype.destroy.call(this),this.renderDatesMem.unrender()},t.prototype.updateSize=function(e,t,n){var r=this.calendar;(e||r.isViewUpdated||r.isDatesUpdated||r.isEventsUpdated)&&this.updateBaseSize(e,t,n)},t.prototype.updateBaseSize=function(e,t,n){},t.prototype.renderDatesWrap=function(e){this.renderDates(e),this.addScroll({duration:J(this.opt("scrollTime"))}),this.startNowIndicator(e)},t.prototype.unrenderDatesWrap=function(){this.stopNowIndicator(),this.unrenderDates()},t.prototype.renderDates=function(e){},t.prototype.unrenderDates=function(){},t.prototype.renderBusinessHours=function(e){},t.prototype.unrenderBusinessHours=function(){},t.prototype.renderDateSelectionWrap=function(e){e&&this.renderDateSelection(e)},t.prototype.unrenderDateSelectionWrap=function(e){e&&this.unrenderDateSelection(e)},t.prototype.renderDateSelection=function(e){},t.prototype.unrenderDateSelection=function(e){},t.prototype.renderEvents=function(e){},t.prototype.unrenderEvents=function(){},t.prototype.sliceEvents=function(e,t){var n=this.props;return dt(e,n.eventUiBases,n.dateProfile.activeRange,t?this.nextDayThreshold:null).fg},t.prototype.computeEventDraggable=function(e,t){for(var n=this.calendar.pluginSystem.hooks.isDraggableTransformers,r=t.startEditable,i=0,o=n;i<o.length;i++){r=(0,o[i])(r,e,t,this)}return r},t.prototype.computeEventStartResizable=function(e,t){return t.durationEditable&&this.opt("eventResizableFromStart")},t.prototype.computeEventEndResizable=function(e,t){return t.durationEditable},t.prototype.renderEventSelectionWrap=function(e){e&&this.renderEventSelection(e)},t.prototype.unrenderEventSelectionWrap=function(e){e&&this.unrenderEventSelection(e)},t.prototype.renderEventSelection=function(e){},t.prototype.unrenderEventSelection=function(e){},t.prototype.renderEventDragWrap=function(e){e&&this.renderEventDrag(e)},t.prototype.unrenderEventDragWrap=function(e){e&&this.unrenderEventDrag(e)},t.prototype.renderEventDrag=function(e){},t.prototype.unrenderEventDrag=function(e){},t.prototype.renderEventResizeWrap=function(e){e&&this.renderEventResize(e)},t.prototype.unrenderEventResizeWrap=function(e){e&&this.unrenderEventResize(e)},t.prototype.renderEventResize=function(e){},t.prototype.unrenderEventResize=function(e){},t.prototype.startNowIndicator=function(e){var t,n,r,i=this,o=this.dateEnv;this.opt("nowIndicator")&&(t=this.getNowIndicatorUnit(e))&&(n=this.updateNowIndicator.bind(this),this.initialNowDate=this.calendar.getNow(),this.initialNowQueriedMs=(new Date).valueOf(),r=o.add(o.startOf(this.initialNowDate,t),J(1,t)).valueOf()-this.initialNowDate.valueOf(),this.nowIndicatorTimeoutID=setTimeout(function(){i.nowIndicatorTimeoutID=null,n(),r="second"===t?1e3:6e4,i.nowIndicatorIntervalID=setInterval(n,r)},r))},t.prototype.updateNowIndicator=function(){this.props.dateProfile&&this.initialNowDate&&(this.unrenderNowIndicator(),this.renderNowIndicator(H(this.initialNowDate,(new Date).valueOf()-this.initialNowQueriedMs)),this.isNowIndicatorRendered=!0)},t.prototype.stopNowIndicator=function(){this.isNowIndicatorRendered&&(this.nowIndicatorTimeoutID&&(clearTimeout(this.nowIndicatorTimeoutID),this.nowIndicatorTimeoutID=null),this.nowIndicatorIntervalID&&(clearInterval(this.nowIndicatorIntervalID),this.nowIndicatorIntervalID=null),this.unrenderNowIndicator(),this.isNowIndicatorRendered=!1)},t.prototype.getNowIndicatorUnit=function(e){},t.prototype.renderNowIndicator=function(e){},t.prototype.unrenderNowIndicator=function(){},t.prototype.addScroll=function(e){var t=this.queuedScroll||(this.queuedScroll={});Se(t,e)},t.prototype.popScroll=function(e){this.applyQueuedScroll(e),this.queuedScroll=null},t.prototype.applyQueuedScroll=function(e){this.applyScroll(this.queuedScroll||{},e)},t.prototype.queryScroll=function(){var e={};return this.props.dateProfile&&Se(e,this.queryDateScroll()),e},t.prototype.applyScroll=function(e,t){var n=e.duration;null!=n&&(delete e.duration,this.props.dateProfile&&Se(e,this.computeDateScroll(n))),this.props.dateProfile&&this.applyDateScroll(e)},t.prototype.computeDateScroll=function(e){return{}},t.prototype.queryDateScroll=function(){return{}},t.prototype.applyDateScroll=function(e){},t.prototype.scrollToDuration=function(e){this.applyScroll({duration:e},!1)},t}(pn);tn.mixInto(Mr),Mr.prototype.usesMinMaxTime=!1,Mr.prototype.dateProfileGeneratorClass=Jn;var kr=function(){function e(e){this.segs=[],this.isSizeDirty=!1,this.context=e}return e.prototype.renderSegs=function(e,t){this.rangeUpdated(),e=this.renderSegEls(e,t),this.segs=e,this.attachSegs(e,t),this.isSizeDirty=!0,this.context.view.triggerRenderedSegs(this.segs,Boolean(t))},e.prototype.unrender=function(e,t){this.context.view.triggerWillRemoveSegs(this.segs,Boolean(t)),this.detachSegs(this.segs),this.segs=[]},e.prototype.rangeUpdated=function(){var e,t,n=this.context.options;this.eventTimeFormat=ot(n.eventTimeFormat||this.computeEventTimeFormat(),n.defaultRangeSeparator),null==(e=n.displayEventTime)&&(e=this.computeDisplayEventTime()),null==(t=n.displayEventEnd)&&(t=this.computeDisplayEventEnd()),this.displayEventTime=e,this.displayEventEnd=t},e.prototype.renderSegEls=function(e,t){var n,r="";if(e.length){for(n=0;n<e.length;n++)r+=this.renderSegHtml(e[n],t);o(r).forEach(function(t,n){var r=e[n];t&&(r.el=t)}),e=ft(this.context.view,e,Boolean(t))}return e},e.prototype.getSegClasses=function(e,t,n,r){var i=["fc-event",e.isStart?"fc-start":"fc-not-start",e.isEnd?"fc-end":"fc-not-end"].concat(e.eventRange.ui.classNames);return t&&i.push("fc-draggable"),n&&i.push("fc-resizable"),r&&(i.push("fc-mirror"),r.isDragging&&i.push("fc-dragging"),r.isResizing&&i.push("fc-resizing")),i},e.prototype.getTimeText=function(e,t,n){var r=e.def,i=e.instance;return this._getTimeText(i.range.start,r.hasEnd?i.range.end:null,r.allDay,t,n,i.forcedStartTzo,i.forcedEndTzo)},e.prototype._getTimeText=function(e,t,n,r,i,o,a){var s=this.context.dateEnv;return null==r&&(r=this.eventTimeFormat),null==i&&(i=this.displayEventEnd),this.displayEventTime&&!n?i&&t?s.formatRange(e,t,r,{forcedStartTzo:o,forcedEndTzo:a}):s.format(e,r,{forcedTzo:o}):""},e.prototype.computeEventTimeFormat=function(){return{hour:"numeric",minute:"2-digit",omitZeroMinute:!0}},e.prototype.computeDisplayEventTime=function(){return!0},e.prototype.computeDisplayEventEnd=function(){return!0},e.prototype.getSkinCss=function(e){return{"background-color":e.backgroundColor,"border-color":e.borderColor,color:e.textColor}},e.prototype.sortEventSegs=function(e){var t=this.context.view.eventOrderSpecs,n=e.map(Or);return n.sort(function(e,n){return oe(e,n,t)}),n.map(function(e){return e._seg})},e.prototype.computeSizes=function(e){(e||this.isSizeDirty)&&this.computeSegSizes(this.segs)},e.prototype.assignSizes=function(e){(e||this.isSizeDirty)&&(this.assignSegSizes(this.segs),this.isSizeDirty=!1)},e.prototype.computeSegSizes=function(e){},e.prototype.assignSegSizes=function(e){},e.prototype.hideByHash=function(e){if(e)for(var t=0,n=this.segs;t<n.length;t++){var r=n[t];e[r.eventRange.instance.instanceId]&&(r.el.style.visibility="hidden")}},e.prototype.showByHash=function(e){if(e)for(var t=0,n=this.segs;t<n.length;t++){var r=n[t];e[r.eventRange.instance.instanceId]&&(r.el.style.visibility="")}},e.prototype.selectByInstanceId=function(e){if(e)for(var t=0,n=this.segs;t<n.length;t++){var r=n[t],i=r.eventRange.instance;i&&i.instanceId===e&&r.el&&r.el.classList.add("fc-selected")}},e.prototype.unselectByInstanceId=function(e){if(e)for(var t=0,n=this.segs;t<n.length;t++){var r=n[t];r.el&&r.el.classList.remove("fc-selected")}},e}();function Or(e){var t=e.eventRange.def,n=e.eventRange.instance.range,r=n.start?n.start.valueOf():0,i=n.end?n.end.valueOf():0;return Se({},t.extendedProps,t,{id:t.publicId,start:r,end:i,duration:i-r,allDay:Number(t.allDay),_seg:e})}var _r=function(){function e(e){this.fillSegTag="div",this.dirtySizeFlags={},this.context=e,this.containerElsByType={},this.segsByType={}}return e.prototype.getSegsByType=function(e){return this.segsByType[e]||[]},e.prototype.renderSegs=function(e,t){var n,r=this.renderSegEls(e,t),i=this.attachSegs(e,r);i&&(n=this.containerElsByType[e]||(this.containerElsByType[e]=[])).push.apply(n,i),this.segsByType[e]=r,"bgEvent"===e&&this.context.view.triggerRenderedSegs(r,!1),this.dirtySizeFlags[e]=!0},e.prototype.unrender=function(e){var t=this.segsByType[e];t&&("bgEvent"===e&&this.context.view.triggerWillRemoveSegs(t,!1),this.detachSegs(e,t))},e.prototype.renderSegEls=function(e,t){var n,r=this,i="";if(t.length){for(n=0;n<t.length;n++)i+=this.renderSegHtml(e,t[n]);o(i).forEach(function(e,n){var r=t[n];e&&(r.el=e)}),"bgEvent"===e&&(t=ft(this.context.view,t,!1)),t=t.filter(function(e){return h(e.el,r.fillSegTag)})}return t},e.prototype.renderSegHtml=function(e,t){var n=null,r=[];return"highlight"!==e&&"businessHours"!==e&&(n={"background-color":t.eventRange.ui.backgroundColor}),"highlight"!==e&&(r=r.concat(t.eventRange.ui.classNames)),"businessHours"===e?r.push("fc-bgevent"):r.push("fc-"+e.toLowerCase()),"<"+this.fillSegTag+(r.length?' class="'+r.join(" ")+'"':"")+(n?' style="'+_t(n)+'"':"")+"></"+this.fillSegTag+">"},e.prototype.detachSegs=function(e,t){var n=this.containerElsByType[e];n&&(n.forEach(c),delete this.containerElsByType[e])},e.prototype.computeSizes=function(e){for(var t in this.segsByType)(e||this.dirtySizeFlags[t])&&this.computeSegSizes(this.segsByType[t])},e.prototype.assignSizes=function(e){for(var t in this.segsByType)(e||this.dirtySizeFlags[t])&&this.assignSegSizes(this.segsByType[t]);this.dirtySizeFlags={}},e.prototype.computeSegSizes=function(e){},e.prototype.assignSegSizes=function(e){},e}(),Pr=function(e){this.timeZoneName=e},xr=function(){function e(e){this.emitter=new tn}return e.prototype.destroy=function(){},e.prototype.setMirrorIsVisible=function(e){},e.prototype.setMirrorNeedsRevert=function(e){},e.prototype.setAutoScrollEnabled=function(e){},e}();function Hr(e){var t=_n(e.locale||"en",On([]).map);return e=Se({timeZone:Rn.timeZone,calendarSystem:"gregory"},e,{locale:t}),new Bn(e)}var Nr={startTime:J,duration:J,create:Boolean,sourceId:String},zr={create:!0};function Ur(e,t){return!e||t>10?{weekday:"short"}:t>1?{weekday:"short",month:"numeric",day:"numeric",omitCommas:!0}:{weekday:"long"}}function Lr(e,t,n,r,i,o,a,s){var u,l=o.view,c=o.dateEnv,d=o.theme,f=o.options,p=Ze(t.activeRange,e),h=["fc-day-header",d.getClass("widgetHeader")];return u="function"==typeof f.columnHeaderHtml?f.columnHeaderHtml(c.toDate(e)):"function"==typeof f.columnHeaderText?Ot(f.columnHeaderText(c.toDate(e))):Ot(c.format(e,i)),n?h=h.concat(Qt(e,t,o,!0)):h.push("fc-"+P[e.getUTCDay()]),'<th class="'+h.join(" ")+'"'+(p&&n?' data-date="'+c.formatIso(e,{omitTime:!0})+'"':"")+(a>1?' colspan="'+a+'"':"")+(s?" "+s:"")+">"+(p?Kt(l,{date:e,forceOff:!n||1===r},u):u)+"</th>"}var Br=function(e){function t(t,n){var r=e.call(this,t)||this;return n.innerHTML="",n.appendChild(r.el=i('<div class="fc-row '+r.theme.getClass("headerRow")+'"><table class="'+r.theme.getClass("tableGrid")+'"><thead></thead></table></div>')),r.thead=r.el.querySelector("thead"),r}return Ee(t,e),t.prototype.destroy=function(){c(this.el)},t.prototype.render=function(e){var t=e.dates,n=e.datesRepDistinctDays,r=[];e.renderIntroHtml&&r.push(e.renderIntroHtml());for(var i=ot(this.opt("columnHeaderFormat")||Ur(n,t.length)),o=0,a=t;o<a.length;o++){var s=a[o];r.push(Lr(s,e.dateProfile,n,t.length,i,this.context))}this.isRtl&&r.reverse(),this.thead.innerHTML="<tr>"+r.join("")+"</tr>"},t}(fn),Vr=function(){function e(e,t){for(var n=e.start,r=e.end,i=[],o=[],a=-1;n<r;)t.isHiddenDay(n)?i.push(a+.5):(a++,i.push(a),o.push(n)),n=x(n,1);this.dates=o,this.indices=i,this.cnt=o.length}return e.prototype.sliceRange=function(e){var t=this.getDateDayIndex(e.start),n=this.getDateDayIndex(x(e.end,-1)),r=Math.max(0,t),i=Math.min(this.cnt-1,n);return(r=Math.ceil(r))<=(i=Math.floor(i))?{firstIndex:r,lastIndex:i,isStart:t===r,isEnd:n===i}:null},e.prototype.getDateDayIndex=function(e){var t=this.indices,n=Math.floor(N(this.dates[0],e));return n<0?t[0]-1:n>=t.length?t[t.length-1]+1:t[n]},e}(),Ar=function(){function e(e,t){var n,r,i,o=e.dates;if(t){for(r=o[0].getUTCDay(),n=1;n<o.length&&o[n].getUTCDay()!==r;n++);i=Math.ceil(o.length/n)}else i=1,n=o.length;this.rowCnt=i,this.colCnt=n,this.daySeries=e,this.cells=this.buildCells(),this.headerDates=this.buildHeaderDates()}return e.prototype.buildCells=function(){for(var e=[],t=0;t<this.rowCnt;t++){for(var n=[],r=0;r<this.colCnt;r++)n.push(this.buildCell(t,r));e.push(n)}return e},e.prototype.buildCell=function(e,t){return{date:this.daySeries.dates[e*this.colCnt+t]}},e.prototype.buildHeaderDates=function(){for(var e=[],t=0;t<this.colCnt;t++)e.push(this.cells[0][t].date);return e},e.prototype.sliceRange=function(e){var t=this.colCnt,n=this.daySeries.sliceRange(e),r=[];if(n)for(var i=n.firstIndex,o=n.lastIndex,a=i;a<=o;){var s=Math.floor(a/t),u=Math.min((s+1)*t,o+1);r.push({row:s,firstCol:a%t,lastCol:(u-1)%t,isStart:n.isStart&&a===i,isEnd:n.isEnd&&u-1===o}),a=u}return r},e}(),Fr=function(){function e(){this.sliceBusinessHours=Ye(this._sliceBusinessHours),this.sliceDateSelection=Ye(this._sliceDateSpan),this.sliceEventStore=Ye(this._sliceEventStore),this.sliceEventDrag=Ye(this._sliceInteraction),this.sliceEventResize=Ye(this._sliceInteraction)}return e.prototype.sliceProps=function(e,t,n,r){for(var i=[],o=4;o<arguments.length;o++)i[o-4]=arguments[o];var a=e.eventUiBases,s=this.sliceEventStore.apply(this,[e.eventStore,a,t,n,r].concat(i));return{dateSelectionSegs:this.sliceDateSelection.apply(this,[e.dateSelection,a,r].concat(i)),businessHourSegs:this.sliceBusinessHours.apply(this,[e.businessHours,t,n,r].concat(i)),fgEventSegs:s.fg,bgEventSegs:s.bg,eventDrag:this.sliceEventDrag.apply(this,[e.eventDrag,a,t,n,r].concat(i)),eventResize:this.sliceEventResize.apply(this,[e.eventResize,a,t,n,r].concat(i)),eventSelection:e.eventSelection}},e.prototype.sliceNowDate=function(e,t){for(var n=[],r=2;r<arguments.length;r++)n[r-2]=arguments[r];return this._sliceDateSpan.apply(this,[{range:{start:e,end:H(e,1)},allDay:!1},{},t].concat(n))},e.prototype._sliceBusinessHours=function(e,t,n,r){for(var i=[],o=4;o<arguments.length;o++)i[o-4]=arguments[o];return e?this._sliceEventStore.apply(this,[_e(e,Wr(t,Boolean(n)),r.calendar),{},t,n,r].concat(i)).bg:[]},e.prototype._sliceEventStore=function(e,t,n,r,i){for(var o=[],a=5;a<arguments.length;a++)o[a-5]=arguments[a];if(e){var s=dt(e,t,Wr(n,Boolean(r)),r);return{bg:this.sliceEventRanges(s.bg,i,o),fg:this.sliceEventRanges(s.fg,i,o)}}return{bg:[],fg:[]}},e.prototype._sliceInteraction=function(e,t,n,r,i){for(var o=[],a=5;a<arguments.length;a++)o[a-5]=arguments[a];if(!e)return null;var s=dt(e.mutatedEvents,t,Wr(n,Boolean(r)),r);return{segs:this.sliceEventRanges(s.fg,i,o),affectedInstances:e.affectedEvents.instances,isEvent:e.isEvent,sourceSeg:e.origSeg}},e.prototype._sliceDateSpan=function(e,t,n){for(var r=[],i=3;i<arguments.length;i++)r[i-3]=arguments[i];if(!e)return[];for(var o=ar(e,t,n.calendar),a=this.sliceRange.apply(this,[e.range].concat(r)),s=0,u=a;s<u.length;s++){var l=u[s];l.component=n,l.eventRange=o}return a},e.prototype.sliceEventRanges=function(e,t,n){for(var r=[],i=0,o=e;i<o.length;i++){var a=o[i];r.push.apply(r,this.sliceEventRange(a,t,n))}return r},e.prototype.sliceEventRange=function(e,t,n){for(var r=this.sliceRange.apply(this,[e.range].concat(n)),i=0,o=r;i<o.length;i++){var a=o[i];a.component=t,a.eventRange=e,a.isStart=e.isStart&&a.isStart,a.isEnd=e.isEnd&&a.isEnd}return r},e}();function Wr(e,t){var n=e.activeRange;return t?n:{start:H(n.start,e.minTime.milliseconds),end:H(n.end,e.maxTime.milliseconds-864e5)}}e.Calendar=Dr,e.Component=fn,e.DateComponent=pn,e.DateEnv=Bn,e.DateProfileGenerator=Jn,e.DayHeader=Br,e.DaySeries=Vr,e.DayTable=Ar,e.ElementDragging=xr,e.ElementScrollController=sn,e.EmitterMixin=tn,e.EventApi=ct,e.FgEventRenderer=kr,e.FillRenderer=_r,e.Interaction=yr,e.Mixin=en,e.NamedTimeZoneImpl=Pr,e.PositionCache=on,e.ScrollComponent=ln,e.ScrollController=an,e.Slicer=Fr,e.Splitter=Xt,e.Theme=cn,e.View=Mr,e.WindowScrollController=un,e.addDays=x,e.addDurations=function(e,t){return{years:e.years+t.years,months:e.months+t.months,days:e.days+t.days,milliseconds:e.milliseconds+t.milliseconds}},e.addMs=H,e.addWeeks=function(e,t){var n=Z(e);return n[2]+=7*t,j(n)},e.allowContextMenu=function(e){e.removeEventListener("contextmenu",k)},e.allowSelection=function(e){e.classList.remove("fc-unselectable"),e.removeEventListener("selectstart",k)},e.appendToElement=s,e.applyAll=de,e.applyMutationToEventStore=yt,e.applyStyle=y,e.applyStyleProp=m,e.asRoughMinutes=function(e){return te(e)/6e4},e.asRoughMs=te,e.asRoughSeconds=function(e){return te(e)/1e3},e.buildGotoAnchorHtml=Kt,e.buildSegCompareObj=Or,e.capitaliseFirstLetter=ue,e.combineEventUis=Ut,e.compareByFieldSpec=ae,e.compareByFieldSpecs=oe,e.compareNumbers=function(e,t){return e-t},e.compensateScroll=function(e,t){t.left&&y(e,{borderLeftWidth:1,marginLeft:t.left-1}),t.right&&y(e,{borderRightWidth:1,marginRight:t.right-1})},e.computeClippingRect=function(e){return M(e).map(function(e){return w(e)}).concat({left:window.pageXOffset,right:window.pageXOffset+document.documentElement.clientWidth,top:window.pageYOffset,bottom:window.pageYOffset+document.documentElement.clientHeight}).reduce(function(e,t){return E(e,t)||t})},e.computeEdges=T,e.computeFallbackHeaderFormat=Ur,e.computeHeightAndMargins=I,e.computeInnerRect=w,e.computeRect=R,e.computeVisibleDayRange=ge,e.config={},e.constrainPoint=function(e,t){return{left:Math.min(Math.max(e.left,t.left),t.right),top:Math.min(Math.max(e.top,t.top),t.bottom)}},e.createDuration=J,e.createElement=r,e.createEmptyEventStore=He,e.createEventInstance=Zt,e.createFormatter=ot,e.createPlugin=vn,e.cssToStr=_t,e.debounce=pe,e.diffDates=ye,e.diffDayAndTime=z,e.diffDays=N,e.diffPoints=function(e,t){return{left:e.left-t.left,top:e.top-t.top}},e.diffWeeks=function(e,t){return N(e,t)/7},e.diffWholeDays=L,e.diffWholeWeeks=U,e.disableCursor=function(){document.body.classList.add("fc-not-allowed")},e.distributeHeight=function(e,t,n){var r=Math.floor(t/e.length),i=Math.floor(t-r*(e.length-1)),o=[],a=[],s=[],u=0;re(e),e.forEach(function(t,n){var l=n===e.length-1?i:r,c=t.getBoundingClientRect().height,d=c+C(t);d<l?(o.push(t),a.push(d),s.push(c)):u+=d}),n&&(t-=u,r=Math.floor(t/o.length),i=Math.floor(t-r*(o.length-1))),o.forEach(function(e,t){var n=t===o.length-1?i:r,u=a[t],l=n-(u-s[t]);u<n&&(e.style.height=l+"px")})},e.elementClosest=p,e.elementMatches=h,e.enableCursor=function(){document.body.classList.remove("fc-not-allowed")},e.eventTupleToStore=Oe,e.filterEventStoreDefs=ze,e.filterHash=we,e.findChildren=function(e,t){for(var n=e instanceof HTMLElement?[e]:e,r=[],i=0;i<n.length;i++)for(var o=n[i].children,a=0;a<o.length;a++){var s=o[a];t&&!h(s,t)||r.push(s)}return r},e.findElements=v,e.flexibleCompare=se,e.forceClassName=function(e,t,n){n?e.classList.add(t):e.classList.remove(t)},e.formatDate=function(e,t){void 0===t&&(t={});var n=Hr(t),r=ot(t),i=n.createMarkerMeta(e);return i?n.format(i.marker,r,{forcedTzo:i.forcedTzo}):""},e.formatIsoTimeString=function(e){return le(e.getUTCHours(),2)+":"+le(e.getUTCMinutes(),2)+":"+le(e.getUTCSeconds(),2)},e.formatRange=function(e,t,n){var r=Hr("object"==typeof n&&n?n:{}),i=ot(n,Rn.defaultRangeSeparator),o=r.createMarkerMeta(e),a=r.createMarkerMeta(t);return o&&a?r.formatRange(o.marker,a.marker,i,{forcedStartTzo:o.forcedTzo,forcedEndTzo:a.forcedTzo,isEndExclusive:n.isEndExclusive}):""},e.getAllDayHtml=function(e){return e.opt("allDayHtml")||Ot(e.opt("allDayText"))},e.getClippingParents=M,e.getDayClasses=Qt,e.getElSeg=ht,e.getRectCenter=function(e){return{left:(e.left+e.right)/2,top:(e.top+e.bottom)/2}},e.getRelevantEvents=Pe,e.globalDefaults=Rn,e.greatestDurationDenominator=ne,e.hasBgRendering=function(e){return"background"===e.rendering||"inverse-background"===e.rendering},e.htmlEscape=Ot,e.htmlToElement=i,e.insertAfterElement=function(e,t){for(var n=l(t),r=e.nextSibling||null,i=0;i<n.length;i++)e.parentNode.insertBefore(n[i],r)},e.interactionSettingsStore=mr,e.interactionSettingsToStore=function(e){var t;return(t={})[e.component.uid]=e,t},e.intersectRanges=Ve,e.intersectRects=E,e.isArraysEqual=je,e.isDateSpansEqual=function(e,t){return Ae(e.range,t.range)&&e.allDay===t.allDay&&function(e,t){for(var n in t)if("range"!==n&&"allDay"!==n&&e[n]!==t[n])return!1;for(var n in e)if(!(n in t))return!1;return!0}(e,t)},e.isInt=ce,e.isInteractionValid=Tt,e.isMultiDayRange=function(e){var t=ge(e);return N(t.start,t.end)>1},e.isPropsEqual=Me,e.isPropsValid=Rt,e.isSingleDay=function(e){return 0===e.years&&0===e.months&&1===e.days&&0===e.milliseconds},e.isValidDate=Y,e.listenBySelector=O,e.mapHash=Re,e.matchCellWidths=function(e){var t=0;return e.forEach(function(e){var n=e.firstChild;if(n instanceof HTMLElement){var r=n.getBoundingClientRect().width;r>t&&(t=r)}}),t++,e.forEach(function(e){e.style.width=t+"px"}),t},e.memoize=Ye,e.memoizeOutput=qe,e.memoizeRendering=qt,e.mergeEventStores=Ne,e.multiplyDuration=function(e,t){return{years:e.years*t,months:e.months*t,days:e.days*t,milliseconds:e.milliseconds*t}},e.padStart=le,e.parseBusinessHours=Yt,e.parseDragMeta=function(e){var t={},n=he(e,Nr,zr,t);return n.leftoverProps=t,n},e.parseEventDef=Wt,e.parseFieldSpecs=ie,e.parseMarker=Ln,e.pointInsideRect=function(e,t){return e.left>=t.left&&e.left<t.right&&e.top>=t.top&&e.top<t.bottom},e.prependToElement=u,e.preventContextMenu=function(e){e.addEventListener("contextmenu",k)},e.preventDefault=k,e.preventSelection=function(e){e.classList.add("fc-unselectable"),e.addEventListener("selectstart",k)},e.processScopedUiProps=Nt,e.rangeContainsMarker=Ze,e.rangeContainsRange=We,e.rangesEqual=Ae,e.rangesIntersect=Fe,e.refineProps=he,e.removeElement=c,e.removeExact=function(e,t){for(var n=0,r=0;r<e.length;)e[r]===t?(e.splice(r,1),n++):r++;return n},e.renderDateCell=Lr,e.requestJson=En,e.sliceEventStore=dt,e.startOfDay=B,e.subtractInnerElHeight=function(e,t){var n={position:"relative",left:-1};y(e,n),y(t,n);var r=e.getBoundingClientRect().height-t.getBoundingClientRect().height,i={position:"",left:""};return y(e,i),y(t,i),r},e.translateRect=function(e,t,n){return{left:e.left+t,right:e.right+t,top:e.top+n,bottom:e.bottom+n}},e.uncompensateScroll=function(e){y(e,{marginLeft:"",marginRight:"",borderLeftWidth:"",borderRightWidth:""})},e.undistributeHeight=re,e.unpromisify=$t,e.version="4.3.1",e.whenTransitionDone=function(e,t){var n=function(r){t(r),_.forEach(function(t){e.removeEventListener(t,n)})};_.forEach(function(t){e.addEventListener(t,n)})},e.wholeDivideDurations=function(e,t){for(var n=null,r=0;r<G.length;r++){var i=G[r];if(t[i]){var o=e[i]/t[i];if(!ce(o)||null!==n&&n!==o)return null;n=o}else if(e[i])return null}return n},Object.defineProperty(e,"__esModule",{value:!0})}); \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/core/package.json b/AKPlan/static/AKPlan/fullcalendar/core/package.json new file mode 100644 index 00000000..67f976df --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/core/package.json @@ -0,0 +1,30 @@ +{ + "name": "@fullcalendar/core", + "version": "4.3.1", + "title": "FullCalendar Core Package", + "description": "Provides core functionality, including the Calendar class", + "keywords": [ + "calendar", + "event", + "full-sized" + ], + "homepage": "https://fullcalendar.io/", + "docs": "https://fullcalendar.io/docs/initialize-es6", + "bugs": "https://fullcalendar.io/reporting-bugs", + "repository": { + "type": "git", + "url": "https://github.com/fullcalendar/fullcalendar.git", + "homepage": "https://github.com/fullcalendar/fullcalendar" + }, + "license": "MIT", + "author": { + "name": "Adam Shaw", + "email": "arshaw@arshaw.com", + "url": "http://arshaw.com/" + }, + "copyright": "2019 Adam Shaw", + "main": "main.js", + "module": "main.esm.js", + "unpkg": "main.min.js", + "types": "main.d.ts" +} diff --git a/AKPlan/static/AKPlan/fullcalendar/daygrid/LICENSE.txt b/AKPlan/static/AKPlan/fullcalendar/daygrid/LICENSE.txt new file mode 100644 index 00000000..2149cfbe --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/daygrid/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2019 Adam Shaw + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/AKPlan/static/AKPlan/fullcalendar/daygrid/README.md b/AKPlan/static/AKPlan/fullcalendar/daygrid/README.md new file mode 100644 index 00000000..e0093654 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/daygrid/README.md @@ -0,0 +1,8 @@ + +# FullCalendar Day Grid Plugin + +Display events on Month view or DayGrid view + +[View the docs »](https://fullcalendar.io/docs/month-view) + +This package was created from the [FullCalendar monorepo »](https://github.com/fullcalendar/fullcalendar) diff --git a/AKPlan/static/AKPlan/fullcalendar/daygrid/main.css b/AKPlan/static/AKPlan/fullcalendar/daygrid/main.css new file mode 100644 index 00000000..81f58955 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/daygrid/main.css @@ -0,0 +1,78 @@ +/* DayGridView +--------------------------------------------------------------------------------------------------*/ +/* day row structure */ +.fc-dayGridWeek-view .fc-content-skeleton, +.fc-dayGridDay-view .fc-content-skeleton { + /* there may be week numbers in these views, so no padding-top */ + padding-bottom: 1em; + /* ensure a space at bottom of cell for user selecting/clicking */ +} + +.fc-dayGrid-view .fc-body .fc-row { + min-height: 4em; + /* ensure that all rows are at least this tall */ +} + +/* a "rigid" row will take up a constant amount of height because content-skeleton is absolute */ +.fc-row.fc-rigid { + overflow: hidden; +} + +.fc-row.fc-rigid .fc-content-skeleton { + position: absolute; + top: 0; + left: 0; + right: 0; +} + +/* week and day number styling */ +.fc-day-top.fc-other-month { + opacity: 0.3; +} + +.fc-dayGrid-view .fc-week-number, +.fc-dayGrid-view .fc-day-number { + padding: 2px; +} + +.fc-dayGrid-view th.fc-week-number, +.fc-dayGrid-view th.fc-day-number { + padding: 0 2px; + /* column headers can't have as much v space */ +} + +.fc-ltr .fc-dayGrid-view .fc-day-top .fc-day-number { + float: right; +} + +.fc-rtl .fc-dayGrid-view .fc-day-top .fc-day-number { + float: left; +} + +.fc-ltr .fc-dayGrid-view .fc-day-top .fc-week-number { + float: left; + border-radius: 0 0 3px 0; +} + +.fc-rtl .fc-dayGrid-view .fc-day-top .fc-week-number { + float: right; + border-radius: 0 0 0 3px; +} + +.fc-dayGrid-view .fc-day-top .fc-week-number { + min-width: 1.5em; + text-align: center; + background-color: #f2f2f2; + color: #808080; +} + +/* when week/day number have own column */ +.fc-dayGrid-view td.fc-week-number { + text-align: center; +} + +.fc-dayGrid-view td.fc-week-number > * { + /* work around the way we do column resizing and ensure a minimum width */ + display: inline-block; + min-width: 1.25em; +} diff --git a/AKPlan/static/AKPlan/fullcalendar/daygrid/main.d.ts b/AKPlan/static/AKPlan/fullcalendar/daygrid/main.d.ts new file mode 100644 index 00000000..ed214f2d --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/daygrid/main.d.ts @@ -0,0 +1,310 @@ +// Generated by dts-bundle v0.7.3-fork.1 +// Dependencies for this module: +// ../../../../../@fullcalendar/core + +declare module '@fullcalendar/daygrid' { + export { default as SimpleDayGrid, DayGridSlicer } from '@fullcalendar/daygrid/SimpleDayGrid'; + export { default as DayGrid, DayGridSeg } from '@fullcalendar/daygrid/DayGrid'; + export { default as AbstractDayGridView } from '@fullcalendar/daygrid/AbstractDayGridView'; + export { default as DayGridView, buildDayTable as buildBasicDayTable } from '@fullcalendar/daygrid/DayGridView'; + export { default as DayBgRow } from '@fullcalendar/daygrid/DayBgRow'; + const _default: import("@fullcalendar/core").PluginDef; + export default _default; +} + +declare module '@fullcalendar/daygrid/SimpleDayGrid' { + import { DateProfile, EventStore, EventUiHash, DateSpan, EventInteractionState, DayTable, Duration, DateComponent, DateRange, Slicer, Hit, ComponentContext } from '@fullcalendar/core'; + import { default as DayGrid, DayGridSeg } from '@fullcalendar/daygrid/DayGrid'; + export interface SimpleDayGridProps { + dateProfile: DateProfile | null; + dayTable: DayTable; + nextDayThreshold: Duration; + businessHours: EventStore; + eventStore: EventStore; + eventUiBases: EventUiHash; + dateSelection: DateSpan | null; + eventSelection: string; + eventDrag: EventInteractionState | null; + eventResize: EventInteractionState | null; + isRigid: boolean; + } + export { SimpleDayGrid as default, SimpleDayGrid }; + class SimpleDayGrid extends DateComponent<SimpleDayGridProps> { + dayGrid: DayGrid; + constructor(context: ComponentContext, dayGrid: DayGrid); + destroy(): void; + render(props: SimpleDayGridProps): void; + buildPositionCaches(): void; + queryHit(positionLeft: number, positionTop: number): Hit; + } + export class DayGridSlicer extends Slicer<DayGridSeg, [DayTable]> { + sliceRange(dateRange: DateRange, dayTable: DayTable): DayGridSeg[]; + } +} + +declare module '@fullcalendar/daygrid/DayGrid' { + import { PositionCache, DateMarker, DateComponent, EventSegUiInteractionState, Seg, DateProfile } from '@fullcalendar/core'; + import Popover from '@fullcalendar/daygrid/Popover'; + import DayGridEventRenderer from '@fullcalendar/daygrid/DayGridEventRenderer'; + import DayTile from '@fullcalendar/daygrid/DayTile'; + export interface RenderProps { + renderNumberIntroHtml: (row: number, dayGrid: DayGrid) => string; + renderBgIntroHtml: () => string; + renderIntroHtml: () => string; + colWeekNumbersVisible: boolean; + cellWeekNumbersVisible: boolean; + } + export interface DayGridSeg extends Seg { + row: number; + firstCol: number; + lastCol: number; + } + export interface DayGridCell { + date: DateMarker; + htmlAttrs?: string; + } + export interface DayGridProps { + dateProfile: DateProfile; + cells: DayGridCell[][]; + businessHourSegs: DayGridSeg[]; + bgEventSegs: DayGridSeg[]; + fgEventSegs: DayGridSeg[]; + dateSelectionSegs: DayGridSeg[]; + eventSelection: string; + eventDrag: EventSegUiInteractionState | null; + eventResize: EventSegUiInteractionState | null; + isRigid: boolean; + } + export { DayGrid as default, DayGrid }; + class DayGrid extends DateComponent<DayGridProps> { + eventRenderer: DayGridEventRenderer; + renderProps: RenderProps; + rowCnt: number; + colCnt: number; + bottomCoordPadding: number; + rowEls: HTMLElement[]; + cellEls: HTMLElement[]; + isCellSizesDirty: boolean; + rowPositions: PositionCache; + colPositions: PositionCache; + segPopover: Popover; + segPopoverTile: DayTile; + constructor(context: any, el: any, renderProps: RenderProps); + render(props: DayGridProps): void; + destroy(): void; + getCellRange(row: any, col: any): { + start: Date; + end: Date; + }; + updateSegPopoverTile(date?: any, segs?: any): void; + _renderCells(cells: DayGridCell[][], isRigid: boolean): void; + _unrenderCells(): void; + renderDayRowHtml(row: any, isRigid: any): string; + getIsNumbersVisible(): boolean; + getIsDayNumbersVisible(): boolean; + renderNumberTrHtml(row: number): string; + renderNumberCellsHtml(row: any): string; + renderNumberCellHtml(date: any): string; + updateSize(isResize: boolean): void; + buildPositionCaches(): void; + buildColPositions(): void; + buildRowPositions(): void; + positionToHit(leftPosition: any, topPosition: any): { + row: any; + col: any; + dateSpan: { + range: { + start: Date; + end: Date; + }; + allDay: boolean; + }; + dayEl: HTMLElement; + relativeRect: { + left: any; + right: any; + top: any; + bottom: any; + }; + }; + getCellEl(row: any, col: any): HTMLElement; + _renderEventDrag(state: EventSegUiInteractionState): void; + _unrenderEventDrag(state: EventSegUiInteractionState): void; + _renderEventResize(state: EventSegUiInteractionState): void; + _unrenderEventResize(state: EventSegUiInteractionState): void; + removeSegPopover(): void; + limitRows(levelLimit: any): void; + computeRowLevelLimit(row: any): (number | false); + limitRow(row: any, levelLimit: any): void; + unlimitRow(row: any): void; + renderMoreLink(row: any, col: any, hiddenSegs: any): HTMLElement; + showSegPopover(row: any, col: any, moreLink: HTMLElement, segs: any): void; + resliceDaySegs(segs: any, dayDate: any): any[]; + getMoreLinkText(num: any): any; + getCellSegs(row: any, col: any, startLevel?: any): any[]; + } +} + +declare module '@fullcalendar/daygrid/AbstractDayGridView' { + import { ScrollComponent, View, ComponentContext, ViewSpec, DateProfileGenerator, Duration } from '@fullcalendar/core'; + import DayGrid from '@fullcalendar/daygrid/DayGrid'; + export { DayGridView as default, DayGridView }; + abstract class DayGridView extends View { + scroller: ScrollComponent; + dayGrid: DayGrid; + colWeekNumbersVisible: boolean; + weekNumberWidth: number; + constructor(context: ComponentContext, viewSpec: ViewSpec, dateProfileGenerator: DateProfileGenerator, parentEl: HTMLElement); + destroy(): void; + renderSkeletonHtml(): string; + weekNumberStyleAttr(): string; + hasRigidRows(): boolean; + updateSize(isResize: boolean, viewHeight: number, isAuto: boolean): void; + updateBaseSize(isResize: boolean, viewHeight: number, isAuto: boolean): void; + computeScrollerHeight(viewHeight: any): number; + setGridHeight(height: any, isAuto: any): void; + computeDateScroll(duration: Duration): { + top: number; + }; + queryDateScroll(): { + top: number; + }; + applyDateScroll(scroll: any): void; + renderHeadIntroHtml: () => string; + renderDayGridNumberIntroHtml: (row: number, dayGrid: DayGrid) => string; + renderDayGridBgIntroHtml: () => string; + renderDayGridIntroHtml: () => string; + } +} + +declare module '@fullcalendar/daygrid/DayGridView' { + import { DayHeader, ComponentContext, ViewSpec, DateProfileGenerator, DateProfile, ViewProps, DayTable } from '@fullcalendar/core'; + import AbstractDayGridView from '@fullcalendar/daygrid/AbstractDayGridView'; + import SimpleDayGrid from '@fullcalendar/daygrid/SimpleDayGrid'; + export { DayGridView as default, DayGridView }; + class DayGridView extends AbstractDayGridView { + header: DayHeader; + simpleDayGrid: SimpleDayGrid; + dayTable: DayTable; + constructor(_context: ComponentContext, viewSpec: ViewSpec, dateProfileGenerator: DateProfileGenerator, parentEl: HTMLElement); + destroy(): void; + render(props: ViewProps): void; + } + export function buildDayTable(dateProfile: DateProfile, dateProfileGenerator: DateProfileGenerator): DayTable; +} + +declare module '@fullcalendar/daygrid/DayBgRow' { + import { ComponentContext, DateMarker, DateProfile } from '@fullcalendar/core'; + export interface DayBgCell { + date: DateMarker; + htmlAttrs?: string; + } + export interface DayBgRowProps { + cells: DayBgCell[]; + dateProfile: DateProfile; + renderIntroHtml?: () => string; + } + export { DayBgRow as default, DayBgRow }; + class DayBgRow { + context: ComponentContext; + constructor(context: ComponentContext); + renderHtml(props: DayBgRowProps): string; + } +} + +declare module '@fullcalendar/daygrid/Popover' { + export interface PopoverOptions { + className?: string; + content?: (el: HTMLElement) => void; + parentEl: HTMLElement; + autoHide?: boolean; + top?: number; + left?: number; + right?: number; + viewportConstrain?: boolean; + } + export { Popover as default, Popover }; + class Popover { + isHidden: boolean; + options: PopoverOptions; + el: HTMLElement; + margin: number; + constructor(options: PopoverOptions); + show(): void; + hide(): void; + render(): void; + documentMousedown: (ev: any) => void; + destroy(): void; + position(): void; + trigger(name: any): void; + } +} + +declare module '@fullcalendar/daygrid/DayGridEventRenderer' { + import { Seg } from '@fullcalendar/core'; + import DayGrid from '@fullcalendar/daygrid/DayGrid'; + import SimpleDayGridEventRenderer from '@fullcalendar/daygrid/SimpleDayGridEventRenderer'; + export { DayGridEventRenderer as default, DayGridEventRenderer }; + class DayGridEventRenderer extends SimpleDayGridEventRenderer { + dayGrid: DayGrid; + rowStructs: any; + constructor(dayGrid: DayGrid); + attachSegs(segs: Seg[], mirrorInfo: any): void; + detachSegs(): void; + renderSegRows(segs: Seg[]): any[]; + renderSegRow(row: any, rowSegs: any): { + row: any; + tbodyEl: HTMLTableSectionElement; + cellMatrix: any[]; + segMatrix: any[]; + segLevels: any[]; + segs: any; + }; + buildSegLevels(segs: Seg[]): any[]; + groupSegRows(segs: Seg[]): any[]; + computeDisplayEventEnd(): boolean; + } +} + +declare module '@fullcalendar/daygrid/DayTile' { + import { DateComponent, Seg, Hit, DateMarker, ComponentContext, EventInstanceHash } from '@fullcalendar/core'; + import SimpleDayGridEventRenderer from '@fullcalendar/daygrid/SimpleDayGridEventRenderer'; + export interface DayTileProps { + date: DateMarker; + fgSegs: Seg[]; + eventSelection: string; + eventDragInstances: EventInstanceHash; + eventResizeInstances: EventInstanceHash; + } + export { DayTile as default, DayTile }; + class DayTile extends DateComponent<DayTileProps> { + segContainerEl: HTMLElement; + constructor(context: ComponentContext, el: HTMLElement); + render(props: DayTileProps): void; + destroy(): void; + _renderFrame(date: DateMarker): void; + queryHit(positionLeft: number, positionTop: number, elWidth: number, elHeight: number): Hit | null; + } + export class DayTileEventRenderer extends SimpleDayGridEventRenderer { + dayTile: DayTile; + constructor(dayTile: any); + attachSegs(segs: Seg[]): void; + detachSegs(segs: Seg[]): void; + } +} + +declare module '@fullcalendar/daygrid/SimpleDayGridEventRenderer' { + import { FgEventRenderer, Seg } from '@fullcalendar/core'; + export { SimpleDayGridEventRenderer as default, SimpleDayGridEventRenderer }; + abstract class SimpleDayGridEventRenderer extends FgEventRenderer { + renderSegHtml(seg: Seg, mirrorInfo: any): string; + computeEventTimeFormat(): { + hour: string; + minute: string; + omitZeroMinute: boolean; + meridiem: string; + }; + computeDisplayEventEnd(): boolean; + } +} + diff --git a/AKPlan/static/AKPlan/fullcalendar/daygrid/main.esm.js b/AKPlan/static/AKPlan/fullcalendar/daygrid/main.esm.js new file mode 100644 index 00000000..28c2a24c --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/daygrid/main.esm.js @@ -0,0 +1,1627 @@ +/*! +FullCalendar Day Grid Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +import { addWeeks, diffWeeks, DateProfileGenerator, createElement, listenBySelector, removeElement, computeRect, computeClippingRect, applyStyle, cssToStr, htmlEscape, FgEventRenderer, appendToElement, prependToElement, htmlToElement, FillRenderer, memoizeRendering, createFormatter, addDays, DateComponent, rangeContainsMarker, getDayClasses, findElements, PositionCache, buildGotoAnchorHtml, findChildren, insertAfterElement, intersectRanges, ScrollComponent, matchCellWidths, uncompensateScroll, compensateScroll, subtractInnerElHeight, distributeHeight, undistributeHeight, View, Slicer, memoize, DayHeader, DaySeries, DayTable, createPlugin } from '@fullcalendar/core'; + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} + +var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; + +var DayGridDateProfileGenerator = /** @class */ (function (_super) { + __extends(DayGridDateProfileGenerator, _super); + function DayGridDateProfileGenerator() { + return _super !== null && _super.apply(this, arguments) || this; + } + // Computes the date range that will be rendered. + DayGridDateProfileGenerator.prototype.buildRenderRange = function (currentRange, currentRangeUnit, isRangeAllDay) { + var dateEnv = this.dateEnv; + var renderRange = _super.prototype.buildRenderRange.call(this, currentRange, currentRangeUnit, isRangeAllDay); + var start = renderRange.start; + var end = renderRange.end; + var endOfWeek; + // year and month views should be aligned with weeks. this is already done for week + if (/^(year|month)$/.test(currentRangeUnit)) { + start = dateEnv.startOfWeek(start); + // make end-of-week if not already + endOfWeek = dateEnv.startOfWeek(end); + if (endOfWeek.valueOf() !== end.valueOf()) { + end = addWeeks(endOfWeek, 1); + } + } + // ensure 6 weeks + if (this.options.monthMode && + this.options.fixedWeekCount) { + var rowCnt = Math.ceil(// could be partial weeks due to hiddenDays + diffWeeks(start, end)); + end = addWeeks(end, 6 - rowCnt); + } + return { start: start, end: end }; + }; + return DayGridDateProfileGenerator; +}(DateProfileGenerator)); + +/* A rectangular panel that is absolutely positioned over other content +------------------------------------------------------------------------------------------------------------------------ +Options: + - className (string) + - content (HTML string, element, or element array) + - parentEl + - top + - left + - right (the x coord of where the right edge should be. not a "CSS" right) + - autoHide (boolean) + - show (callback) + - hide (callback) +*/ +var Popover = /** @class */ (function () { + function Popover(options) { + var _this = this; + this.isHidden = true; + this.margin = 10; // the space required between the popover and the edges of the scroll container + // Triggered when the user clicks *anywhere* in the document, for the autoHide feature + this.documentMousedown = function (ev) { + // only hide the popover if the click happened outside the popover + if (_this.el && !_this.el.contains(ev.target)) { + _this.hide(); + } + }; + this.options = options; + } + // Shows the popover on the specified position. Renders it if not already + Popover.prototype.show = function () { + if (this.isHidden) { + if (!this.el) { + this.render(); + } + this.el.style.display = ''; + this.position(); + this.isHidden = false; + this.trigger('show'); + } + }; + // Hides the popover, through CSS, but does not remove it from the DOM + Popover.prototype.hide = function () { + if (!this.isHidden) { + this.el.style.display = 'none'; + this.isHidden = true; + this.trigger('hide'); + } + }; + // Creates `this.el` and renders content inside of it + Popover.prototype.render = function () { + var _this = this; + var options = this.options; + var el = this.el = createElement('div', { + className: 'fc-popover ' + (options.className || ''), + style: { + top: '0', + left: '0' + } + }); + if (typeof options.content === 'function') { + options.content(el); + } + options.parentEl.appendChild(el); + // when a click happens on anything inside with a 'fc-close' className, hide the popover + listenBySelector(el, 'click', '.fc-close', function (ev) { + _this.hide(); + }); + if (options.autoHide) { + document.addEventListener('mousedown', this.documentMousedown); + } + }; + // Hides and unregisters any handlers + Popover.prototype.destroy = function () { + this.hide(); + if (this.el) { + removeElement(this.el); + this.el = null; + } + document.removeEventListener('mousedown', this.documentMousedown); + }; + // Positions the popover optimally, using the top/left/right options + Popover.prototype.position = function () { + var options = this.options; + var el = this.el; + var elDims = el.getBoundingClientRect(); // only used for width,height + var origin = computeRect(el.offsetParent); + var clippingRect = computeClippingRect(options.parentEl); + var top; // the "position" (not "offset") values for the popover + var left; // + // compute top and left + top = options.top || 0; + if (options.left !== undefined) { + left = options.left; + } + else if (options.right !== undefined) { + left = options.right - elDims.width; // derive the left value from the right value + } + else { + left = 0; + } + // constrain to the view port. if constrained by two edges, give precedence to top/left + top = Math.min(top, clippingRect.bottom - elDims.height - this.margin); + top = Math.max(top, clippingRect.top + this.margin); + left = Math.min(left, clippingRect.right - elDims.width - this.margin); + left = Math.max(left, clippingRect.left + this.margin); + applyStyle(el, { + top: top - origin.top, + left: left - origin.left + }); + }; + // Triggers a callback. Calls a function in the option hash of the same name. + // Arguments beyond the first `name` are forwarded on. + // TODO: better code reuse for this. Repeat code + // can kill this??? + Popover.prototype.trigger = function (name) { + if (this.options[name]) { + this.options[name].apply(this, Array.prototype.slice.call(arguments, 1)); + } + }; + return Popover; +}()); + +/* Event-rendering methods for the DayGrid class +----------------------------------------------------------------------------------------------------------------------*/ +// "Simple" is bad a name. has nothing to do with SimpleDayGrid +var SimpleDayGridEventRenderer = /** @class */ (function (_super) { + __extends(SimpleDayGridEventRenderer, _super); + function SimpleDayGridEventRenderer() { + return _super !== null && _super.apply(this, arguments) || this; + } + // Builds the HTML to be used for the default element for an individual segment + SimpleDayGridEventRenderer.prototype.renderSegHtml = function (seg, mirrorInfo) { + var _a = this.context, view = _a.view, options = _a.options; + var eventRange = seg.eventRange; + var eventDef = eventRange.def; + var eventUi = eventRange.ui; + var allDay = eventDef.allDay; + var isDraggable = view.computeEventDraggable(eventDef, eventUi); + var isResizableFromStart = allDay && seg.isStart && view.computeEventStartResizable(eventDef, eventUi); + var isResizableFromEnd = allDay && seg.isEnd && view.computeEventEndResizable(eventDef, eventUi); + var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd, mirrorInfo); + var skinCss = cssToStr(this.getSkinCss(eventUi)); + var timeHtml = ''; + var timeText; + var titleHtml; + classes.unshift('fc-day-grid-event', 'fc-h-event'); + // Only display a timed events time if it is the starting segment + if (seg.isStart) { + timeText = this.getTimeText(eventRange); + if (timeText) { + timeHtml = '<span class="fc-time">' + htmlEscape(timeText) + '</span>'; + } + } + titleHtml = + '<span class="fc-title">' + + (htmlEscape(eventDef.title || '') || ' ') + // we always want one line of height + '</span>'; + return '<a class="' + classes.join(' ') + '"' + + (eventDef.url ? + ' href="' + htmlEscape(eventDef.url) + '"' : + '') + + (skinCss ? + ' style="' + skinCss + '"' : + '') + + '>' + + '<div class="fc-content">' + + (options.dir === 'rtl' ? + titleHtml + ' ' + timeHtml : // put a natural space in between + timeHtml + ' ' + titleHtml // + ) + + '</div>' + + (isResizableFromStart ? + '<div class="fc-resizer fc-start-resizer"></div>' : + '') + + (isResizableFromEnd ? + '<div class="fc-resizer fc-end-resizer"></div>' : + '') + + '</a>'; + }; + // Computes a default event time formatting string if `eventTimeFormat` is not explicitly defined + SimpleDayGridEventRenderer.prototype.computeEventTimeFormat = function () { + return { + hour: 'numeric', + minute: '2-digit', + omitZeroMinute: true, + meridiem: 'narrow' + }; + }; + SimpleDayGridEventRenderer.prototype.computeDisplayEventEnd = function () { + return false; // TODO: somehow consider the originating DayGrid's column count + }; + return SimpleDayGridEventRenderer; +}(FgEventRenderer)); + +/* Event-rendering methods for the DayGrid class +----------------------------------------------------------------------------------------------------------------------*/ +var DayGridEventRenderer = /** @class */ (function (_super) { + __extends(DayGridEventRenderer, _super); + function DayGridEventRenderer(dayGrid) { + var _this = _super.call(this, dayGrid.context) || this; + _this.dayGrid = dayGrid; + return _this; + } + // Renders the given foreground event segments onto the grid + DayGridEventRenderer.prototype.attachSegs = function (segs, mirrorInfo) { + var rowStructs = this.rowStructs = this.renderSegRows(segs); + // append to each row's content skeleton + this.dayGrid.rowEls.forEach(function (rowNode, i) { + rowNode.querySelector('.fc-content-skeleton > table').appendChild(rowStructs[i].tbodyEl); + }); + // removes the "more.." events popover + if (!mirrorInfo) { + this.dayGrid.removeSegPopover(); + } + }; + // Unrenders all currently rendered foreground event segments + DayGridEventRenderer.prototype.detachSegs = function () { + var rowStructs = this.rowStructs || []; + var rowStruct; + while ((rowStruct = rowStructs.pop())) { + removeElement(rowStruct.tbodyEl); + } + this.rowStructs = null; + }; + // Uses the given events array to generate <tbody> elements that should be appended to each row's content skeleton. + // Returns an array of rowStruct objects (see the bottom of `renderSegRow`). + // PRECONDITION: each segment shoud already have a rendered and assigned `.el` + DayGridEventRenderer.prototype.renderSegRows = function (segs) { + var rowStructs = []; + var segRows; + var row; + segRows = this.groupSegRows(segs); // group into nested arrays + // iterate each row of segment groupings + for (row = 0; row < segRows.length; row++) { + rowStructs.push(this.renderSegRow(row, segRows[row])); + } + return rowStructs; + }; + // Given a row # and an array of segments all in the same row, render a <tbody> element, a skeleton that contains + // the segments. Returns object with a bunch of internal data about how the render was calculated. + // NOTE: modifies rowSegs + DayGridEventRenderer.prototype.renderSegRow = function (row, rowSegs) { + var dayGrid = this.dayGrid; + var colCnt = dayGrid.colCnt, isRtl = dayGrid.isRtl; + var segLevels = this.buildSegLevels(rowSegs); // group into sub-arrays of levels + var levelCnt = Math.max(1, segLevels.length); // ensure at least one level + var tbody = document.createElement('tbody'); + var segMatrix = []; // lookup for which segments are rendered into which level+col cells + var cellMatrix = []; // lookup for all <td> elements of the level+col matrix + var loneCellMatrix = []; // lookup for <td> elements that only take up a single column + var i; + var levelSegs; + var col; + var tr; + var j; + var seg; + var td; + // populates empty cells from the current column (`col`) to `endCol` + function emptyCellsUntil(endCol) { + while (col < endCol) { + // try to grab a cell from the level above and extend its rowspan. otherwise, create a fresh cell + td = (loneCellMatrix[i - 1] || [])[col]; + if (td) { + td.rowSpan = (td.rowSpan || 1) + 1; + } + else { + td = document.createElement('td'); + tr.appendChild(td); + } + cellMatrix[i][col] = td; + loneCellMatrix[i][col] = td; + col++; + } + } + for (i = 0; i < levelCnt; i++) { // iterate through all levels + levelSegs = segLevels[i]; + col = 0; + tr = document.createElement('tr'); + segMatrix.push([]); + cellMatrix.push([]); + loneCellMatrix.push([]); + // levelCnt might be 1 even though there are no actual levels. protect against this. + // this single empty row is useful for styling. + if (levelSegs) { + for (j = 0; j < levelSegs.length; j++) { // iterate through segments in level + seg = levelSegs[j]; + var leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol; + var rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol; + emptyCellsUntil(leftCol); + // create a container that occupies or more columns. append the event element. + td = createElement('td', { className: 'fc-event-container' }, seg.el); + if (leftCol !== rightCol) { + td.colSpan = rightCol - leftCol + 1; + } + else { // a single-column segment + loneCellMatrix[i][col] = td; + } + while (col <= rightCol) { + cellMatrix[i][col] = td; + segMatrix[i][col] = seg; + col++; + } + tr.appendChild(td); + } + } + emptyCellsUntil(colCnt); // finish off the row + var introHtml = dayGrid.renderProps.renderIntroHtml(); + if (introHtml) { + if (dayGrid.isRtl) { + appendToElement(tr, introHtml); + } + else { + prependToElement(tr, introHtml); + } + } + tbody.appendChild(tr); + } + return { + row: row, + tbodyEl: tbody, + cellMatrix: cellMatrix, + segMatrix: segMatrix, + segLevels: segLevels, + segs: rowSegs + }; + }; + // Stacks a flat array of segments, which are all assumed to be in the same row, into subarrays of vertical levels. + // NOTE: modifies segs + DayGridEventRenderer.prototype.buildSegLevels = function (segs) { + var _a = this.dayGrid, isRtl = _a.isRtl, colCnt = _a.colCnt; + var levels = []; + var i; + var seg; + var j; + // Give preference to elements with certain criteria, so they have + // a chance to be closer to the top. + segs = this.sortEventSegs(segs); + for (i = 0; i < segs.length; i++) { + seg = segs[i]; + // loop through levels, starting with the topmost, until the segment doesn't collide with other segments + for (j = 0; j < levels.length; j++) { + if (!isDaySegCollision(seg, levels[j])) { + break; + } + } + // `j` now holds the desired subrow index + seg.level = j; + seg.leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol; // for sorting only + seg.rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol // for sorting only + ; + (levels[j] || (levels[j] = [])).push(seg); + } + // order segments left-to-right. very important if calendar is RTL + for (j = 0; j < levels.length; j++) { + levels[j].sort(compareDaySegCols); + } + return levels; + }; + // Given a flat array of segments, return an array of sub-arrays, grouped by each segment's row + DayGridEventRenderer.prototype.groupSegRows = function (segs) { + var segRows = []; + var i; + for (i = 0; i < this.dayGrid.rowCnt; i++) { + segRows.push([]); + } + for (i = 0; i < segs.length; i++) { + segRows[segs[i].row].push(segs[i]); + } + return segRows; + }; + // Computes a default `displayEventEnd` value if one is not expliclty defined + DayGridEventRenderer.prototype.computeDisplayEventEnd = function () { + return this.dayGrid.colCnt === 1; // we'll likely have space if there's only one day + }; + return DayGridEventRenderer; +}(SimpleDayGridEventRenderer)); +// Computes whether two segments' columns collide. They are assumed to be in the same row. +function isDaySegCollision(seg, otherSegs) { + var i; + var otherSeg; + for (i = 0; i < otherSegs.length; i++) { + otherSeg = otherSegs[i]; + if (otherSeg.firstCol <= seg.lastCol && + otherSeg.lastCol >= seg.firstCol) { + return true; + } + } + return false; +} +// A cmp function for determining the leftmost event +function compareDaySegCols(a, b) { + return a.leftCol - b.leftCol; +} + +var DayGridMirrorRenderer = /** @class */ (function (_super) { + __extends(DayGridMirrorRenderer, _super); + function DayGridMirrorRenderer() { + return _super !== null && _super.apply(this, arguments) || this; + } + DayGridMirrorRenderer.prototype.attachSegs = function (segs, mirrorInfo) { + var sourceSeg = mirrorInfo.sourceSeg; + var rowStructs = this.rowStructs = this.renderSegRows(segs); + // inject each new event skeleton into each associated row + this.dayGrid.rowEls.forEach(function (rowNode, row) { + var skeletonEl = htmlToElement('<div class="fc-mirror-skeleton"><table></table></div>'); // will be absolutely positioned + var skeletonTopEl; + var skeletonTop; + // If there is an original segment, match the top position. Otherwise, put it at the row's top level + if (sourceSeg && sourceSeg.row === row) { + skeletonTopEl = sourceSeg.el; + } + else { + skeletonTopEl = rowNode.querySelector('.fc-content-skeleton tbody'); + if (!skeletonTopEl) { // when no events + skeletonTopEl = rowNode.querySelector('.fc-content-skeleton table'); + } + } + skeletonTop = skeletonTopEl.getBoundingClientRect().top - + rowNode.getBoundingClientRect().top; // the offsetParent origin + skeletonEl.style.top = skeletonTop + 'px'; + skeletonEl.querySelector('table').appendChild(rowStructs[row].tbodyEl); + rowNode.appendChild(skeletonEl); + }); + }; + return DayGridMirrorRenderer; +}(DayGridEventRenderer)); + +var EMPTY_CELL_HTML = '<td style="pointer-events:none"></td>'; +var DayGridFillRenderer = /** @class */ (function (_super) { + __extends(DayGridFillRenderer, _super); + function DayGridFillRenderer(dayGrid) { + var _this = _super.call(this, dayGrid.context) || this; + _this.fillSegTag = 'td'; // override the default tag name + _this.dayGrid = dayGrid; + return _this; + } + DayGridFillRenderer.prototype.renderSegs = function (type, segs) { + // don't render timed background events + if (type === 'bgEvent') { + segs = segs.filter(function (seg) { + return seg.eventRange.def.allDay; + }); + } + _super.prototype.renderSegs.call(this, type, segs); + }; + DayGridFillRenderer.prototype.attachSegs = function (type, segs) { + var els = []; + var i; + var seg; + var skeletonEl; + for (i = 0; i < segs.length; i++) { + seg = segs[i]; + skeletonEl = this.renderFillRow(type, seg); + this.dayGrid.rowEls[seg.row].appendChild(skeletonEl); + els.push(skeletonEl); + } + return els; + }; + // Generates the HTML needed for one row of a fill. Requires the seg's el to be rendered. + DayGridFillRenderer.prototype.renderFillRow = function (type, seg) { + var dayGrid = this.dayGrid; + var colCnt = dayGrid.colCnt, isRtl = dayGrid.isRtl; + var leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol; + var rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol; + var startCol = leftCol; + var endCol = rightCol + 1; + var className; + var skeletonEl; + var trEl; + if (type === 'businessHours') { + className = 'bgevent'; + } + else { + className = type.toLowerCase(); + } + skeletonEl = htmlToElement('<div class="fc-' + className + '-skeleton">' + + '<table><tr></tr></table>' + + '</div>'); + trEl = skeletonEl.getElementsByTagName('tr')[0]; + if (startCol > 0) { + appendToElement(trEl, + // will create (startCol + 1) td's + new Array(startCol + 1).join(EMPTY_CELL_HTML)); + } + seg.el.colSpan = endCol - startCol; + trEl.appendChild(seg.el); + if (endCol < colCnt) { + appendToElement(trEl, + // will create (colCnt - endCol) td's + new Array(colCnt - endCol + 1).join(EMPTY_CELL_HTML)); + } + var introHtml = dayGrid.renderProps.renderIntroHtml(); + if (introHtml) { + if (dayGrid.isRtl) { + appendToElement(trEl, introHtml); + } + else { + prependToElement(trEl, introHtml); + } + } + return skeletonEl; + }; + return DayGridFillRenderer; +}(FillRenderer)); + +var DayTile = /** @class */ (function (_super) { + __extends(DayTile, _super); + function DayTile(context, el) { + var _this = _super.call(this, context, el) || this; + var eventRenderer = _this.eventRenderer = new DayTileEventRenderer(_this); + var renderFrame = _this.renderFrame = memoizeRendering(_this._renderFrame); + _this.renderFgEvents = memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer), [renderFrame]); + _this.renderEventSelection = memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]); + _this.renderEventDrag = memoizeRendering(eventRenderer.hideByHash.bind(eventRenderer), eventRenderer.showByHash.bind(eventRenderer), [renderFrame]); + _this.renderEventResize = memoizeRendering(eventRenderer.hideByHash.bind(eventRenderer), eventRenderer.showByHash.bind(eventRenderer), [renderFrame]); + context.calendar.registerInteractiveComponent(_this, { + el: _this.el, + useEventCenter: false + }); + return _this; + } + DayTile.prototype.render = function (props) { + this.renderFrame(props.date); + this.renderFgEvents(props.fgSegs); + this.renderEventSelection(props.eventSelection); + this.renderEventDrag(props.eventDragInstances); + this.renderEventResize(props.eventResizeInstances); + }; + DayTile.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.renderFrame.unrender(); // should unrender everything else + this.calendar.unregisterInteractiveComponent(this); + }; + DayTile.prototype._renderFrame = function (date) { + var _a = this, theme = _a.theme, dateEnv = _a.dateEnv; + var title = dateEnv.format(date, createFormatter(this.opt('dayPopoverFormat')) // TODO: cache + ); + this.el.innerHTML = + '<div class="fc-header ' + theme.getClass('popoverHeader') + '">' + + '<span class="fc-title">' + + htmlEscape(title) + + '</span>' + + '<span class="fc-close ' + theme.getIconClass('close') + '"></span>' + + '</div>' + + '<div class="fc-body ' + theme.getClass('popoverContent') + '">' + + '<div class="fc-event-container"></div>' + + '</div>'; + this.segContainerEl = this.el.querySelector('.fc-event-container'); + }; + DayTile.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) { + var date = this.props.date; // HACK + if (positionLeft < elWidth && positionTop < elHeight) { + return { + component: this, + dateSpan: { + allDay: true, + range: { start: date, end: addDays(date, 1) } + }, + dayEl: this.el, + rect: { + left: 0, + top: 0, + right: elWidth, + bottom: elHeight + }, + layer: 1 + }; + } + }; + return DayTile; +}(DateComponent)); +var DayTileEventRenderer = /** @class */ (function (_super) { + __extends(DayTileEventRenderer, _super); + function DayTileEventRenderer(dayTile) { + var _this = _super.call(this, dayTile.context) || this; + _this.dayTile = dayTile; + return _this; + } + DayTileEventRenderer.prototype.attachSegs = function (segs) { + for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { + var seg = segs_1[_i]; + this.dayTile.segContainerEl.appendChild(seg.el); + } + }; + DayTileEventRenderer.prototype.detachSegs = function (segs) { + for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { + var seg = segs_2[_i]; + removeElement(seg.el); + } + }; + return DayTileEventRenderer; +}(SimpleDayGridEventRenderer)); + +var DayBgRow = /** @class */ (function () { + function DayBgRow(context) { + this.context = context; + } + DayBgRow.prototype.renderHtml = function (props) { + var parts = []; + if (props.renderIntroHtml) { + parts.push(props.renderIntroHtml()); + } + for (var _i = 0, _a = props.cells; _i < _a.length; _i++) { + var cell = _a[_i]; + parts.push(renderCellHtml(cell.date, props.dateProfile, this.context, cell.htmlAttrs)); + } + if (!props.cells.length) { + parts.push('<td class="fc-day ' + this.context.theme.getClass('widgetContent') + '"></td>'); + } + if (this.context.options.dir === 'rtl') { + parts.reverse(); + } + return '<tr>' + parts.join('') + '</tr>'; + }; + return DayBgRow; +}()); +function renderCellHtml(date, dateProfile, context, otherAttrs) { + var dateEnv = context.dateEnv, theme = context.theme; + var isDateValid = rangeContainsMarker(dateProfile.activeRange, date); // TODO: called too frequently. cache somehow. + var classes = getDayClasses(date, dateProfile, context); + classes.unshift('fc-day', theme.getClass('widgetContent')); + return '<td class="' + classes.join(' ') + '"' + + (isDateValid ? + ' data-date="' + dateEnv.formatIso(date, { omitTime: true }) + '"' : + '') + + (otherAttrs ? + ' ' + otherAttrs : + '') + + '></td>'; +} + +var DAY_NUM_FORMAT = createFormatter({ day: 'numeric' }); +var WEEK_NUM_FORMAT = createFormatter({ week: 'numeric' }); +var DayGrid = /** @class */ (function (_super) { + __extends(DayGrid, _super); + function DayGrid(context, el, renderProps) { + var _this = _super.call(this, context, el) || this; + _this.bottomCoordPadding = 0; // hack for extending the hit area for the last row of the coordinate grid + _this.isCellSizesDirty = false; + var eventRenderer = _this.eventRenderer = new DayGridEventRenderer(_this); + var fillRenderer = _this.fillRenderer = new DayGridFillRenderer(_this); + _this.mirrorRenderer = new DayGridMirrorRenderer(_this); + var renderCells = _this.renderCells = memoizeRendering(_this._renderCells, _this._unrenderCells); + _this.renderBusinessHours = memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'businessHours'), fillRenderer.unrender.bind(fillRenderer, 'businessHours'), [renderCells]); + _this.renderDateSelection = memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'highlight'), fillRenderer.unrender.bind(fillRenderer, 'highlight'), [renderCells]); + _this.renderBgEvents = memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'bgEvent'), fillRenderer.unrender.bind(fillRenderer, 'bgEvent'), [renderCells]); + _this.renderFgEvents = memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer), [renderCells]); + _this.renderEventSelection = memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]); + _this.renderEventDrag = memoizeRendering(_this._renderEventDrag, _this._unrenderEventDrag, [renderCells]); + _this.renderEventResize = memoizeRendering(_this._renderEventResize, _this._unrenderEventResize, [renderCells]); + _this.renderProps = renderProps; + return _this; + } + DayGrid.prototype.render = function (props) { + var cells = props.cells; + this.rowCnt = cells.length; + this.colCnt = cells[0].length; + this.renderCells(cells, props.isRigid); + this.renderBusinessHours(props.businessHourSegs); + this.renderDateSelection(props.dateSelectionSegs); + this.renderBgEvents(props.bgEventSegs); + this.renderFgEvents(props.fgEventSegs); + this.renderEventSelection(props.eventSelection); + this.renderEventDrag(props.eventDrag); + this.renderEventResize(props.eventResize); + if (this.segPopoverTile) { + this.updateSegPopoverTile(); + } + }; + DayGrid.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.renderCells.unrender(); // will unrender everything else + }; + DayGrid.prototype.getCellRange = function (row, col) { + var start = this.props.cells[row][col].date; + var end = addDays(start, 1); + return { start: start, end: end }; + }; + DayGrid.prototype.updateSegPopoverTile = function (date, segs) { + var ownProps = this.props; + this.segPopoverTile.receiveProps({ + date: date || this.segPopoverTile.props.date, + fgSegs: segs || this.segPopoverTile.props.fgSegs, + eventSelection: ownProps.eventSelection, + eventDragInstances: ownProps.eventDrag ? ownProps.eventDrag.affectedInstances : null, + eventResizeInstances: ownProps.eventResize ? ownProps.eventResize.affectedInstances : null + }); + }; + /* Date Rendering + ------------------------------------------------------------------------------------------------------------------*/ + DayGrid.prototype._renderCells = function (cells, isRigid) { + var _a = this, view = _a.view, dateEnv = _a.dateEnv; + var _b = this, rowCnt = _b.rowCnt, colCnt = _b.colCnt; + var html = ''; + var row; + var col; + for (row = 0; row < rowCnt; row++) { + html += this.renderDayRowHtml(row, isRigid); + } + this.el.innerHTML = html; + this.rowEls = findElements(this.el, '.fc-row'); + this.cellEls = findElements(this.el, '.fc-day, .fc-disabled-day'); + if (this.isRtl) { + this.cellEls.reverse(); + } + this.rowPositions = new PositionCache(this.el, this.rowEls, false, true // vertical + ); + this.colPositions = new PositionCache(this.el, this.cellEls.slice(0, colCnt), // only the first row + true, false // horizontal + ); + // trigger dayRender with each cell's element + for (row = 0; row < rowCnt; row++) { + for (col = 0; col < colCnt; col++) { + this.publiclyTrigger('dayRender', [ + { + date: dateEnv.toDate(cells[row][col].date), + el: this.getCellEl(row, col), + view: view + } + ]); + } + } + this.isCellSizesDirty = true; + }; + DayGrid.prototype._unrenderCells = function () { + this.removeSegPopover(); + }; + // Generates the HTML for a single row, which is a div that wraps a table. + // `row` is the row number. + DayGrid.prototype.renderDayRowHtml = function (row, isRigid) { + var theme = this.theme; + var classes = ['fc-row', 'fc-week', theme.getClass('dayRow')]; + if (isRigid) { + classes.push('fc-rigid'); + } + var bgRow = new DayBgRow(this.context); + return '' + + '<div class="' + classes.join(' ') + '">' + + '<div class="fc-bg">' + + '<table class="' + theme.getClass('tableGrid') + '">' + + bgRow.renderHtml({ + cells: this.props.cells[row], + dateProfile: this.props.dateProfile, + renderIntroHtml: this.renderProps.renderBgIntroHtml + }) + + '</table>' + + '</div>' + + '<div class="fc-content-skeleton">' + + '<table>' + + (this.getIsNumbersVisible() ? + '<thead>' + + this.renderNumberTrHtml(row) + + '</thead>' : + '') + + '</table>' + + '</div>' + + '</div>'; + }; + DayGrid.prototype.getIsNumbersVisible = function () { + return this.getIsDayNumbersVisible() || + this.renderProps.cellWeekNumbersVisible || + this.renderProps.colWeekNumbersVisible; + }; + DayGrid.prototype.getIsDayNumbersVisible = function () { + return this.rowCnt > 1; + }; + /* Grid Number Rendering + ------------------------------------------------------------------------------------------------------------------*/ + DayGrid.prototype.renderNumberTrHtml = function (row) { + var intro = this.renderProps.renderNumberIntroHtml(row, this); + return '' + + '<tr>' + + (this.isRtl ? '' : intro) + + this.renderNumberCellsHtml(row) + + (this.isRtl ? intro : '') + + '</tr>'; + }; + DayGrid.prototype.renderNumberCellsHtml = function (row) { + var htmls = []; + var col; + var date; + for (col = 0; col < this.colCnt; col++) { + date = this.props.cells[row][col].date; + htmls.push(this.renderNumberCellHtml(date)); + } + if (this.isRtl) { + htmls.reverse(); + } + return htmls.join(''); + }; + // Generates the HTML for the <td>s of the "number" row in the DayGrid's content skeleton. + // The number row will only exist if either day numbers or week numbers are turned on. + DayGrid.prototype.renderNumberCellHtml = function (date) { + var _a = this, view = _a.view, dateEnv = _a.dateEnv; + var html = ''; + var isDateValid = rangeContainsMarker(this.props.dateProfile.activeRange, date); // TODO: called too frequently. cache somehow. + var isDayNumberVisible = this.getIsDayNumbersVisible() && isDateValid; + var classes; + var weekCalcFirstDow; + if (!isDayNumberVisible && !this.renderProps.cellWeekNumbersVisible) { + // no numbers in day cell (week number must be along the side) + return '<td></td>'; // will create an empty space above events :( + } + classes = getDayClasses(date, this.props.dateProfile, this.context); + classes.unshift('fc-day-top'); + if (this.renderProps.cellWeekNumbersVisible) { + weekCalcFirstDow = dateEnv.weekDow; + } + html += '<td class="' + classes.join(' ') + '"' + + (isDateValid ? + ' data-date="' + dateEnv.formatIso(date, { omitTime: true }) + '"' : + '') + + '>'; + if (this.renderProps.cellWeekNumbersVisible && (date.getUTCDay() === weekCalcFirstDow)) { + html += buildGotoAnchorHtml(view, { date: date, type: 'week' }, { 'class': 'fc-week-number' }, dateEnv.format(date, WEEK_NUM_FORMAT) // inner HTML + ); + } + if (isDayNumberVisible) { + html += buildGotoAnchorHtml(view, date, { 'class': 'fc-day-number' }, dateEnv.format(date, DAY_NUM_FORMAT) // inner HTML + ); + } + html += '</td>'; + return html; + }; + /* Sizing + ------------------------------------------------------------------------------------------------------------------*/ + DayGrid.prototype.updateSize = function (isResize) { + var _a = this, fillRenderer = _a.fillRenderer, eventRenderer = _a.eventRenderer, mirrorRenderer = _a.mirrorRenderer; + if (isResize || + this.isCellSizesDirty || + this.view.calendar.isEventsUpdated // hack + ) { + this.buildPositionCaches(); + this.isCellSizesDirty = false; + } + fillRenderer.computeSizes(isResize); + eventRenderer.computeSizes(isResize); + mirrorRenderer.computeSizes(isResize); + fillRenderer.assignSizes(isResize); + eventRenderer.assignSizes(isResize); + mirrorRenderer.assignSizes(isResize); + }; + DayGrid.prototype.buildPositionCaches = function () { + this.buildColPositions(); + this.buildRowPositions(); + }; + DayGrid.prototype.buildColPositions = function () { + this.colPositions.build(); + }; + DayGrid.prototype.buildRowPositions = function () { + this.rowPositions.build(); + this.rowPositions.bottoms[this.rowCnt - 1] += this.bottomCoordPadding; // hack + }; + /* Hit System + ------------------------------------------------------------------------------------------------------------------*/ + DayGrid.prototype.positionToHit = function (leftPosition, topPosition) { + var _a = this, colPositions = _a.colPositions, rowPositions = _a.rowPositions; + var col = colPositions.leftToIndex(leftPosition); + var row = rowPositions.topToIndex(topPosition); + if (row != null && col != null) { + return { + row: row, + col: col, + dateSpan: { + range: this.getCellRange(row, col), + allDay: true + }, + dayEl: this.getCellEl(row, col), + relativeRect: { + left: colPositions.lefts[col], + right: colPositions.rights[col], + top: rowPositions.tops[row], + bottom: rowPositions.bottoms[row] + } + }; + } + }; + /* Cell System + ------------------------------------------------------------------------------------------------------------------*/ + // FYI: the first column is the leftmost column, regardless of date + DayGrid.prototype.getCellEl = function (row, col) { + return this.cellEls[row * this.colCnt + col]; + }; + /* Event Drag Visualization + ------------------------------------------------------------------------------------------------------------------*/ + DayGrid.prototype._renderEventDrag = function (state) { + if (state) { + this.eventRenderer.hideByHash(state.affectedInstances); + this.fillRenderer.renderSegs('highlight', state.segs); + } + }; + DayGrid.prototype._unrenderEventDrag = function (state) { + if (state) { + this.eventRenderer.showByHash(state.affectedInstances); + this.fillRenderer.unrender('highlight'); + } + }; + /* Event Resize Visualization + ------------------------------------------------------------------------------------------------------------------*/ + DayGrid.prototype._renderEventResize = function (state) { + if (state) { + this.eventRenderer.hideByHash(state.affectedInstances); + this.fillRenderer.renderSegs('highlight', state.segs); + this.mirrorRenderer.renderSegs(state.segs, { isResizing: true, sourceSeg: state.sourceSeg }); + } + }; + DayGrid.prototype._unrenderEventResize = function (state) { + if (state) { + this.eventRenderer.showByHash(state.affectedInstances); + this.fillRenderer.unrender('highlight'); + this.mirrorRenderer.unrender(state.segs, { isResizing: true, sourceSeg: state.sourceSeg }); + } + }; + /* More+ Link Popover + ------------------------------------------------------------------------------------------------------------------*/ + DayGrid.prototype.removeSegPopover = function () { + if (this.segPopover) { + this.segPopover.hide(); // in handler, will call segPopover's removeElement + } + }; + // Limits the number of "levels" (vertically stacking layers of events) for each row of the grid. + // `levelLimit` can be false (don't limit), a number, or true (should be computed). + DayGrid.prototype.limitRows = function (levelLimit) { + var rowStructs = this.eventRenderer.rowStructs || []; + var row; // row # + var rowLevelLimit; + for (row = 0; row < rowStructs.length; row++) { + this.unlimitRow(row); + if (!levelLimit) { + rowLevelLimit = false; + } + else if (typeof levelLimit === 'number') { + rowLevelLimit = levelLimit; + } + else { + rowLevelLimit = this.computeRowLevelLimit(row); + } + if (rowLevelLimit !== false) { + this.limitRow(row, rowLevelLimit); + } + } + }; + // Computes the number of levels a row will accomodate without going outside its bounds. + // Assumes the row is "rigid" (maintains a constant height regardless of what is inside). + // `row` is the row number. + DayGrid.prototype.computeRowLevelLimit = function (row) { + var rowEl = this.rowEls[row]; // the containing "fake" row div + var rowBottom = rowEl.getBoundingClientRect().bottom; // relative to viewport! + var trEls = findChildren(this.eventRenderer.rowStructs[row].tbodyEl); + var i; + var trEl; + // Reveal one level <tr> at a time and stop when we find one out of bounds + for (i = 0; i < trEls.length; i++) { + trEl = trEls[i]; + trEl.classList.remove('fc-limited'); // reset to original state (reveal) + if (trEl.getBoundingClientRect().bottom > rowBottom) { + return i; + } + } + return false; // should not limit at all + }; + // Limits the given grid row to the maximum number of levels and injects "more" links if necessary. + // `row` is the row number. + // `levelLimit` is a number for the maximum (inclusive) number of levels allowed. + DayGrid.prototype.limitRow = function (row, levelLimit) { + var _this = this; + var _a = this, colCnt = _a.colCnt, isRtl = _a.isRtl; + var rowStruct = this.eventRenderer.rowStructs[row]; + var moreNodes = []; // array of "more" <a> links and <td> DOM nodes + var col = 0; // col #, left-to-right (not chronologically) + var levelSegs; // array of segment objects in the last allowable level, ordered left-to-right + var cellMatrix; // a matrix (by level, then column) of all <td> elements in the row + var limitedNodes; // array of temporarily hidden level <tr> and segment <td> DOM nodes + var i; + var seg; + var segsBelow; // array of segment objects below `seg` in the current `col` + var totalSegsBelow; // total number of segments below `seg` in any of the columns `seg` occupies + var colSegsBelow; // array of segment arrays, below seg, one for each column (offset from segs's first column) + var td; + var rowSpan; + var segMoreNodes; // array of "more" <td> cells that will stand-in for the current seg's cell + var j; + var moreTd; + var moreWrap; + var moreLink; + // Iterates through empty level cells and places "more" links inside if need be + var emptyCellsUntil = function (endCol) { + while (col < endCol) { + segsBelow = _this.getCellSegs(row, col, levelLimit); + if (segsBelow.length) { + td = cellMatrix[levelLimit - 1][col]; + moreLink = _this.renderMoreLink(row, col, segsBelow); + moreWrap = createElement('div', null, moreLink); + td.appendChild(moreWrap); + moreNodes.push(moreWrap); + } + col++; + } + }; + if (levelLimit && levelLimit < rowStruct.segLevels.length) { // is it actually over the limit? + levelSegs = rowStruct.segLevels[levelLimit - 1]; + cellMatrix = rowStruct.cellMatrix; + limitedNodes = findChildren(rowStruct.tbodyEl).slice(levelLimit); // get level <tr> elements past the limit + limitedNodes.forEach(function (node) { + node.classList.add('fc-limited'); // hide elements and get a simple DOM-nodes array + }); + // iterate though segments in the last allowable level + for (i = 0; i < levelSegs.length; i++) { + seg = levelSegs[i]; + var leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol; + var rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol; + emptyCellsUntil(leftCol); // process empty cells before the segment + // determine *all* segments below `seg` that occupy the same columns + colSegsBelow = []; + totalSegsBelow = 0; + while (col <= rightCol) { + segsBelow = this.getCellSegs(row, col, levelLimit); + colSegsBelow.push(segsBelow); + totalSegsBelow += segsBelow.length; + col++; + } + if (totalSegsBelow) { // do we need to replace this segment with one or many "more" links? + td = cellMatrix[levelLimit - 1][leftCol]; // the segment's parent cell + rowSpan = td.rowSpan || 1; + segMoreNodes = []; + // make a replacement <td> for each column the segment occupies. will be one for each colspan + for (j = 0; j < colSegsBelow.length; j++) { + moreTd = createElement('td', { className: 'fc-more-cell', rowSpan: rowSpan }); + segsBelow = colSegsBelow[j]; + moreLink = this.renderMoreLink(row, leftCol + j, [seg].concat(segsBelow) // count seg as hidden too + ); + moreWrap = createElement('div', null, moreLink); + moreTd.appendChild(moreWrap); + segMoreNodes.push(moreTd); + moreNodes.push(moreTd); + } + td.classList.add('fc-limited'); + insertAfterElement(td, segMoreNodes); + limitedNodes.push(td); + } + } + emptyCellsUntil(this.colCnt); // finish off the level + rowStruct.moreEls = moreNodes; // for easy undoing later + rowStruct.limitedEls = limitedNodes; // for easy undoing later + } + }; + // Reveals all levels and removes all "more"-related elements for a grid's row. + // `row` is a row number. + DayGrid.prototype.unlimitRow = function (row) { + var rowStruct = this.eventRenderer.rowStructs[row]; + if (rowStruct.moreEls) { + rowStruct.moreEls.forEach(removeElement); + rowStruct.moreEls = null; + } + if (rowStruct.limitedEls) { + rowStruct.limitedEls.forEach(function (limitedEl) { + limitedEl.classList.remove('fc-limited'); + }); + rowStruct.limitedEls = null; + } + }; + // Renders an <a> element that represents hidden event element for a cell. + // Responsible for attaching click handler as well. + DayGrid.prototype.renderMoreLink = function (row, col, hiddenSegs) { + var _this = this; + var _a = this, view = _a.view, dateEnv = _a.dateEnv; + var a = createElement('a', { className: 'fc-more' }); + a.innerText = this.getMoreLinkText(hiddenSegs.length); + a.addEventListener('click', function (ev) { + var clickOption = _this.opt('eventLimitClick'); + var _col = _this.isRtl ? _this.colCnt - col - 1 : col; // HACK: props.cells has different dir system? + var date = _this.props.cells[row][_col].date; + var moreEl = ev.currentTarget; + var dayEl = _this.getCellEl(row, col); + var allSegs = _this.getCellSegs(row, col); + // rescope the segments to be within the cell's date + var reslicedAllSegs = _this.resliceDaySegs(allSegs, date); + var reslicedHiddenSegs = _this.resliceDaySegs(hiddenSegs, date); + if (typeof clickOption === 'function') { + // the returned value can be an atomic option + clickOption = _this.publiclyTrigger('eventLimitClick', [ + { + date: dateEnv.toDate(date), + allDay: true, + dayEl: dayEl, + moreEl: moreEl, + segs: reslicedAllSegs, + hiddenSegs: reslicedHiddenSegs, + jsEvent: ev, + view: view + } + ]); + } + if (clickOption === 'popover') { + _this.showSegPopover(row, col, moreEl, reslicedAllSegs); + } + else if (typeof clickOption === 'string') { // a view name + view.calendar.zoomTo(date, clickOption); + } + }); + return a; + }; + // Reveals the popover that displays all events within a cell + DayGrid.prototype.showSegPopover = function (row, col, moreLink, segs) { + var _this = this; + var _a = this, calendar = _a.calendar, view = _a.view, theme = _a.theme; + var _col = this.isRtl ? this.colCnt - col - 1 : col; // HACK: props.cells has different dir system? + var moreWrap = moreLink.parentNode; // the <div> wrapper around the <a> + var topEl; // the element we want to match the top coordinate of + var options; + if (this.rowCnt === 1) { + topEl = view.el; // will cause the popover to cover any sort of header + } + else { + topEl = this.rowEls[row]; // will align with top of row + } + options = { + className: 'fc-more-popover ' + theme.getClass('popover'), + parentEl: view.el, + top: computeRect(topEl).top, + autoHide: true, + content: function (el) { + _this.segPopoverTile = new DayTile(_this.context, el); + _this.updateSegPopoverTile(_this.props.cells[row][_col].date, segs); + }, + hide: function () { + _this.segPopoverTile.destroy(); + _this.segPopoverTile = null; + _this.segPopover.destroy(); + _this.segPopover = null; + } + }; + // Determine horizontal coordinate. + // We use the moreWrap instead of the <td> to avoid border confusion. + if (this.isRtl) { + options.right = computeRect(moreWrap).right + 1; // +1 to be over cell border + } + else { + options.left = computeRect(moreWrap).left - 1; // -1 to be over cell border + } + this.segPopover = new Popover(options); + this.segPopover.show(); + calendar.releaseAfterSizingTriggers(); // hack for eventPositioned + }; + // Given the events within an array of segment objects, reslice them to be in a single day + DayGrid.prototype.resliceDaySegs = function (segs, dayDate) { + var dayStart = dayDate; + var dayEnd = addDays(dayStart, 1); + var dayRange = { start: dayStart, end: dayEnd }; + var newSegs = []; + for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { + var seg = segs_1[_i]; + var eventRange = seg.eventRange; + var origRange = eventRange.range; + var slicedRange = intersectRanges(origRange, dayRange); + if (slicedRange) { + newSegs.push(__assign({}, seg, { eventRange: { + def: eventRange.def, + ui: __assign({}, eventRange.ui, { durationEditable: false }), + instance: eventRange.instance, + range: slicedRange + }, isStart: seg.isStart && slicedRange.start.valueOf() === origRange.start.valueOf(), isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf() })); + } + } + return newSegs; + }; + // Generates the text that should be inside a "more" link, given the number of events it represents + DayGrid.prototype.getMoreLinkText = function (num) { + var opt = this.opt('eventLimitText'); + if (typeof opt === 'function') { + return opt(num); + } + else { + return '+' + num + ' ' + opt; + } + }; + // Returns segments within a given cell. + // If `startLevel` is specified, returns only events including and below that level. Otherwise returns all segs. + DayGrid.prototype.getCellSegs = function (row, col, startLevel) { + var segMatrix = this.eventRenderer.rowStructs[row].segMatrix; + var level = startLevel || 0; + var segs = []; + var seg; + while (level < segMatrix.length) { + seg = segMatrix[level][col]; + if (seg) { + segs.push(seg); + } + level++; + } + return segs; + }; + return DayGrid; +}(DateComponent)); + +var WEEK_NUM_FORMAT$1 = createFormatter({ week: 'numeric' }); +/* An abstract class for the daygrid views, as well as month view. Renders one or more rows of day cells. +----------------------------------------------------------------------------------------------------------------------*/ +// It is a manager for a DayGrid subcomponent, which does most of the heavy lifting. +// It is responsible for managing width/height. +var DayGridView = /** @class */ (function (_super) { + __extends(DayGridView, _super); + function DayGridView(context, viewSpec, dateProfileGenerator, parentEl) { + var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this; + /* Header Rendering + ------------------------------------------------------------------------------------------------------------------*/ + // Generates the HTML that will go before the day-of week header cells + _this.renderHeadIntroHtml = function () { + var theme = _this.theme; + if (_this.colWeekNumbersVisible) { + return '' + + '<th class="fc-week-number ' + theme.getClass('widgetHeader') + '" ' + _this.weekNumberStyleAttr() + '>' + + '<span>' + // needed for matchCellWidths + htmlEscape(_this.opt('weekLabel')) + + '</span>' + + '</th>'; + } + return ''; + }; + /* Day Grid Rendering + ------------------------------------------------------------------------------------------------------------------*/ + // Generates the HTML that will go before content-skeleton cells that display the day/week numbers + _this.renderDayGridNumberIntroHtml = function (row, dayGrid) { + var dateEnv = _this.dateEnv; + var weekStart = dayGrid.props.cells[row][0].date; + if (_this.colWeekNumbersVisible) { + return '' + + '<td class="fc-week-number" ' + _this.weekNumberStyleAttr() + '>' + + buildGotoAnchorHtml(// aside from link, important for matchCellWidths + _this, { date: weekStart, type: 'week', forceOff: dayGrid.colCnt === 1 }, dateEnv.format(weekStart, WEEK_NUM_FORMAT$1) // inner HTML + ) + + '</td>'; + } + return ''; + }; + // Generates the HTML that goes before the day bg cells for each day-row + _this.renderDayGridBgIntroHtml = function () { + var theme = _this.theme; + if (_this.colWeekNumbersVisible) { + return '<td class="fc-week-number ' + theme.getClass('widgetContent') + '" ' + _this.weekNumberStyleAttr() + '></td>'; + } + return ''; + }; + // Generates the HTML that goes before every other type of row generated by DayGrid. + // Affects mirror-skeleton and highlight-skeleton rows. + _this.renderDayGridIntroHtml = function () { + if (_this.colWeekNumbersVisible) { + return '<td class="fc-week-number" ' + _this.weekNumberStyleAttr() + '></td>'; + } + return ''; + }; + _this.el.classList.add('fc-dayGrid-view'); + _this.el.innerHTML = _this.renderSkeletonHtml(); + _this.scroller = new ScrollComponent('hidden', // overflow x + 'auto' // overflow y + ); + var dayGridContainerEl = _this.scroller.el; + _this.el.querySelector('.fc-body > tr > td').appendChild(dayGridContainerEl); + dayGridContainerEl.classList.add('fc-day-grid-container'); + var dayGridEl = createElement('div', { className: 'fc-day-grid' }); + dayGridContainerEl.appendChild(dayGridEl); + var cellWeekNumbersVisible; + if (_this.opt('weekNumbers')) { + if (_this.opt('weekNumbersWithinDays')) { + cellWeekNumbersVisible = true; + _this.colWeekNumbersVisible = false; + } + else { + cellWeekNumbersVisible = false; + _this.colWeekNumbersVisible = true; + } + } + else { + _this.colWeekNumbersVisible = false; + cellWeekNumbersVisible = false; + } + _this.dayGrid = new DayGrid(_this.context, dayGridEl, { + renderNumberIntroHtml: _this.renderDayGridNumberIntroHtml, + renderBgIntroHtml: _this.renderDayGridBgIntroHtml, + renderIntroHtml: _this.renderDayGridIntroHtml, + colWeekNumbersVisible: _this.colWeekNumbersVisible, + cellWeekNumbersVisible: cellWeekNumbersVisible + }); + return _this; + } + DayGridView.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.dayGrid.destroy(); + this.scroller.destroy(); + }; + // Builds the HTML skeleton for the view. + // The day-grid component will render inside of a container defined by this HTML. + DayGridView.prototype.renderSkeletonHtml = function () { + var theme = this.theme; + return '' + + '<table class="' + theme.getClass('tableGrid') + '">' + + (this.opt('columnHeader') ? + '<thead class="fc-head">' + + '<tr>' + + '<td class="fc-head-container ' + theme.getClass('widgetHeader') + '"> </td>' + + '</tr>' + + '</thead>' : + '') + + '<tbody class="fc-body">' + + '<tr>' + + '<td class="' + theme.getClass('widgetContent') + '"></td>' + + '</tr>' + + '</tbody>' + + '</table>'; + }; + // Generates an HTML attribute string for setting the width of the week number column, if it is known + DayGridView.prototype.weekNumberStyleAttr = function () { + if (this.weekNumberWidth != null) { + return 'style="width:' + this.weekNumberWidth + 'px"'; + } + return ''; + }; + // Determines whether each row should have a constant height + DayGridView.prototype.hasRigidRows = function () { + var eventLimit = this.opt('eventLimit'); + return eventLimit && typeof eventLimit !== 'number'; + }; + /* Dimensions + ------------------------------------------------------------------------------------------------------------------*/ + DayGridView.prototype.updateSize = function (isResize, viewHeight, isAuto) { + _super.prototype.updateSize.call(this, isResize, viewHeight, isAuto); // will call updateBaseSize. important that executes first + this.dayGrid.updateSize(isResize); + }; + // Refreshes the horizontal dimensions of the view + DayGridView.prototype.updateBaseSize = function (isResize, viewHeight, isAuto) { + var dayGrid = this.dayGrid; + var eventLimit = this.opt('eventLimit'); + var headRowEl = this.header ? this.header.el : null; // HACK + var scrollerHeight; + var scrollbarWidths; + // hack to give the view some height prior to dayGrid's columns being rendered + // TODO: separate setting height from scroller VS dayGrid. + if (!dayGrid.rowEls) { + if (!isAuto) { + scrollerHeight = this.computeScrollerHeight(viewHeight); + this.scroller.setHeight(scrollerHeight); + } + return; + } + if (this.colWeekNumbersVisible) { + // Make sure all week number cells running down the side have the same width. + this.weekNumberWidth = matchCellWidths(findElements(this.el, '.fc-week-number')); + } + // reset all heights to be natural + this.scroller.clear(); + if (headRowEl) { + uncompensateScroll(headRowEl); + } + dayGrid.removeSegPopover(); // kill the "more" popover if displayed + // is the event limit a constant level number? + if (eventLimit && typeof eventLimit === 'number') { + dayGrid.limitRows(eventLimit); // limit the levels first so the height can redistribute after + } + // distribute the height to the rows + // (viewHeight is a "recommended" value if isAuto) + scrollerHeight = this.computeScrollerHeight(viewHeight); + this.setGridHeight(scrollerHeight, isAuto); + // is the event limit dynamically calculated? + if (eventLimit && typeof eventLimit !== 'number') { + dayGrid.limitRows(eventLimit); // limit the levels after the grid's row heights have been set + } + if (!isAuto) { // should we force dimensions of the scroll container? + this.scroller.setHeight(scrollerHeight); + scrollbarWidths = this.scroller.getScrollbarWidths(); + if (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars? + if (headRowEl) { + compensateScroll(headRowEl, scrollbarWidths); + } + // doing the scrollbar compensation might have created text overflow which created more height. redo + scrollerHeight = this.computeScrollerHeight(viewHeight); + this.scroller.setHeight(scrollerHeight); + } + // guarantees the same scrollbar widths + this.scroller.lockOverflow(scrollbarWidths); + } + }; + // given a desired total height of the view, returns what the height of the scroller should be + DayGridView.prototype.computeScrollerHeight = function (viewHeight) { + return viewHeight - + subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller + }; + // Sets the height of just the DayGrid component in this view + DayGridView.prototype.setGridHeight = function (height, isAuto) { + if (this.opt('monthMode')) { + // if auto, make the height of each row the height that it would be if there were 6 weeks + if (isAuto) { + height *= this.dayGrid.rowCnt / 6; + } + distributeHeight(this.dayGrid.rowEls, height, !isAuto); // if auto, don't compensate for height-hogging rows + } + else { + if (isAuto) { + undistributeHeight(this.dayGrid.rowEls); // let the rows be their natural height with no expanding + } + else { + distributeHeight(this.dayGrid.rowEls, height, true); // true = compensate for height-hogging rows + } + } + }; + /* Scroll + ------------------------------------------------------------------------------------------------------------------*/ + DayGridView.prototype.computeDateScroll = function (duration) { + return { top: 0 }; + }; + DayGridView.prototype.queryDateScroll = function () { + return { top: this.scroller.getScrollTop() }; + }; + DayGridView.prototype.applyDateScroll = function (scroll) { + if (scroll.top !== undefined) { + this.scroller.setScrollTop(scroll.top); + } + }; + return DayGridView; +}(View)); +DayGridView.prototype.dateProfileGeneratorClass = DayGridDateProfileGenerator; + +var SimpleDayGrid = /** @class */ (function (_super) { + __extends(SimpleDayGrid, _super); + function SimpleDayGrid(context, dayGrid) { + var _this = _super.call(this, context, dayGrid.el) || this; + _this.slicer = new DayGridSlicer(); + _this.dayGrid = dayGrid; + context.calendar.registerInteractiveComponent(_this, { el: _this.dayGrid.el }); + return _this; + } + SimpleDayGrid.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.calendar.unregisterInteractiveComponent(this); + }; + SimpleDayGrid.prototype.render = function (props) { + var dayGrid = this.dayGrid; + var dateProfile = props.dateProfile, dayTable = props.dayTable; + dayGrid.receiveProps(__assign({}, this.slicer.sliceProps(props, dateProfile, props.nextDayThreshold, dayGrid, dayTable), { dateProfile: dateProfile, cells: dayTable.cells, isRigid: props.isRigid })); + }; + SimpleDayGrid.prototype.buildPositionCaches = function () { + this.dayGrid.buildPositionCaches(); + }; + SimpleDayGrid.prototype.queryHit = function (positionLeft, positionTop) { + var rawHit = this.dayGrid.positionToHit(positionLeft, positionTop); + if (rawHit) { + return { + component: this.dayGrid, + dateSpan: rawHit.dateSpan, + dayEl: rawHit.dayEl, + rect: { + left: rawHit.relativeRect.left, + right: rawHit.relativeRect.right, + top: rawHit.relativeRect.top, + bottom: rawHit.relativeRect.bottom + }, + layer: 0 + }; + } + }; + return SimpleDayGrid; +}(DateComponent)); +var DayGridSlicer = /** @class */ (function (_super) { + __extends(DayGridSlicer, _super); + function DayGridSlicer() { + return _super !== null && _super.apply(this, arguments) || this; + } + DayGridSlicer.prototype.sliceRange = function (dateRange, dayTable) { + return dayTable.sliceRange(dateRange); + }; + return DayGridSlicer; +}(Slicer)); + +var DayGridView$1 = /** @class */ (function (_super) { + __extends(DayGridView, _super); + function DayGridView(_context, viewSpec, dateProfileGenerator, parentEl) { + var _this = _super.call(this, _context, viewSpec, dateProfileGenerator, parentEl) || this; + _this.buildDayTable = memoize(buildDayTable); + if (_this.opt('columnHeader')) { + _this.header = new DayHeader(_this.context, _this.el.querySelector('.fc-head-container')); + } + _this.simpleDayGrid = new SimpleDayGrid(_this.context, _this.dayGrid); + return _this; + } + DayGridView.prototype.destroy = function () { + _super.prototype.destroy.call(this); + if (this.header) { + this.header.destroy(); + } + this.simpleDayGrid.destroy(); + }; + DayGridView.prototype.render = function (props) { + _super.prototype.render.call(this, props); + var dateProfile = this.props.dateProfile; + var dayTable = this.dayTable = + this.buildDayTable(dateProfile, this.dateProfileGenerator); + if (this.header) { + this.header.receiveProps({ + dateProfile: dateProfile, + dates: dayTable.headerDates, + datesRepDistinctDays: dayTable.rowCnt === 1, + renderIntroHtml: this.renderHeadIntroHtml + }); + } + this.simpleDayGrid.receiveProps({ + dateProfile: dateProfile, + dayTable: dayTable, + businessHours: props.businessHours, + dateSelection: props.dateSelection, + eventStore: props.eventStore, + eventUiBases: props.eventUiBases, + eventSelection: props.eventSelection, + eventDrag: props.eventDrag, + eventResize: props.eventResize, + isRigid: this.hasRigidRows(), + nextDayThreshold: this.nextDayThreshold + }); + }; + return DayGridView; +}(DayGridView)); +function buildDayTable(dateProfile, dateProfileGenerator) { + var daySeries = new DaySeries(dateProfile.renderRange, dateProfileGenerator); + return new DayTable(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit)); +} + +var main = createPlugin({ + defaultView: 'dayGridMonth', + views: { + dayGrid: DayGridView$1, + dayGridDay: { + type: 'dayGrid', + duration: { days: 1 } + }, + dayGridWeek: { + type: 'dayGrid', + duration: { weeks: 1 } + }, + dayGridMonth: { + type: 'dayGrid', + duration: { months: 1 }, + monthMode: true, + fixedWeekCount: true + } + } +}); + +export default main; +export { DayGridView as AbstractDayGridView, DayBgRow, DayGrid, DayGridSlicer, DayGridView$1 as DayGridView, SimpleDayGrid, buildDayTable as buildBasicDayTable }; diff --git a/AKPlan/static/AKPlan/fullcalendar/daygrid/main.js b/AKPlan/static/AKPlan/fullcalendar/daygrid/main.js new file mode 100644 index 00000000..d1cc407f --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/daygrid/main.js @@ -0,0 +1,1641 @@ +/*! +FullCalendar Day Grid Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) : + typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) : + (global = global || self, factory(global.FullCalendarDayGrid = {}, global.FullCalendar)); +}(this, function (exports, core) { 'use strict'; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + var DayGridDateProfileGenerator = /** @class */ (function (_super) { + __extends(DayGridDateProfileGenerator, _super); + function DayGridDateProfileGenerator() { + return _super !== null && _super.apply(this, arguments) || this; + } + // Computes the date range that will be rendered. + DayGridDateProfileGenerator.prototype.buildRenderRange = function (currentRange, currentRangeUnit, isRangeAllDay) { + var dateEnv = this.dateEnv; + var renderRange = _super.prototype.buildRenderRange.call(this, currentRange, currentRangeUnit, isRangeAllDay); + var start = renderRange.start; + var end = renderRange.end; + var endOfWeek; + // year and month views should be aligned with weeks. this is already done for week + if (/^(year|month)$/.test(currentRangeUnit)) { + start = dateEnv.startOfWeek(start); + // make end-of-week if not already + endOfWeek = dateEnv.startOfWeek(end); + if (endOfWeek.valueOf() !== end.valueOf()) { + end = core.addWeeks(endOfWeek, 1); + } + } + // ensure 6 weeks + if (this.options.monthMode && + this.options.fixedWeekCount) { + var rowCnt = Math.ceil(// could be partial weeks due to hiddenDays + core.diffWeeks(start, end)); + end = core.addWeeks(end, 6 - rowCnt); + } + return { start: start, end: end }; + }; + return DayGridDateProfileGenerator; + }(core.DateProfileGenerator)); + + /* A rectangular panel that is absolutely positioned over other content + ------------------------------------------------------------------------------------------------------------------------ + Options: + - className (string) + - content (HTML string, element, or element array) + - parentEl + - top + - left + - right (the x coord of where the right edge should be. not a "CSS" right) + - autoHide (boolean) + - show (callback) + - hide (callback) + */ + var Popover = /** @class */ (function () { + function Popover(options) { + var _this = this; + this.isHidden = true; + this.margin = 10; // the space required between the popover and the edges of the scroll container + // Triggered when the user clicks *anywhere* in the document, for the autoHide feature + this.documentMousedown = function (ev) { + // only hide the popover if the click happened outside the popover + if (_this.el && !_this.el.contains(ev.target)) { + _this.hide(); + } + }; + this.options = options; + } + // Shows the popover on the specified position. Renders it if not already + Popover.prototype.show = function () { + if (this.isHidden) { + if (!this.el) { + this.render(); + } + this.el.style.display = ''; + this.position(); + this.isHidden = false; + this.trigger('show'); + } + }; + // Hides the popover, through CSS, but does not remove it from the DOM + Popover.prototype.hide = function () { + if (!this.isHidden) { + this.el.style.display = 'none'; + this.isHidden = true; + this.trigger('hide'); + } + }; + // Creates `this.el` and renders content inside of it + Popover.prototype.render = function () { + var _this = this; + var options = this.options; + var el = this.el = core.createElement('div', { + className: 'fc-popover ' + (options.className || ''), + style: { + top: '0', + left: '0' + } + }); + if (typeof options.content === 'function') { + options.content(el); + } + options.parentEl.appendChild(el); + // when a click happens on anything inside with a 'fc-close' className, hide the popover + core.listenBySelector(el, 'click', '.fc-close', function (ev) { + _this.hide(); + }); + if (options.autoHide) { + document.addEventListener('mousedown', this.documentMousedown); + } + }; + // Hides and unregisters any handlers + Popover.prototype.destroy = function () { + this.hide(); + if (this.el) { + core.removeElement(this.el); + this.el = null; + } + document.removeEventListener('mousedown', this.documentMousedown); + }; + // Positions the popover optimally, using the top/left/right options + Popover.prototype.position = function () { + var options = this.options; + var el = this.el; + var elDims = el.getBoundingClientRect(); // only used for width,height + var origin = core.computeRect(el.offsetParent); + var clippingRect = core.computeClippingRect(options.parentEl); + var top; // the "position" (not "offset") values for the popover + var left; // + // compute top and left + top = options.top || 0; + if (options.left !== undefined) { + left = options.left; + } + else if (options.right !== undefined) { + left = options.right - elDims.width; // derive the left value from the right value + } + else { + left = 0; + } + // constrain to the view port. if constrained by two edges, give precedence to top/left + top = Math.min(top, clippingRect.bottom - elDims.height - this.margin); + top = Math.max(top, clippingRect.top + this.margin); + left = Math.min(left, clippingRect.right - elDims.width - this.margin); + left = Math.max(left, clippingRect.left + this.margin); + core.applyStyle(el, { + top: top - origin.top, + left: left - origin.left + }); + }; + // Triggers a callback. Calls a function in the option hash of the same name. + // Arguments beyond the first `name` are forwarded on. + // TODO: better code reuse for this. Repeat code + // can kill this??? + Popover.prototype.trigger = function (name) { + if (this.options[name]) { + this.options[name].apply(this, Array.prototype.slice.call(arguments, 1)); + } + }; + return Popover; + }()); + + /* Event-rendering methods for the DayGrid class + ----------------------------------------------------------------------------------------------------------------------*/ + // "Simple" is bad a name. has nothing to do with SimpleDayGrid + var SimpleDayGridEventRenderer = /** @class */ (function (_super) { + __extends(SimpleDayGridEventRenderer, _super); + function SimpleDayGridEventRenderer() { + return _super !== null && _super.apply(this, arguments) || this; + } + // Builds the HTML to be used for the default element for an individual segment + SimpleDayGridEventRenderer.prototype.renderSegHtml = function (seg, mirrorInfo) { + var _a = this.context, view = _a.view, options = _a.options; + var eventRange = seg.eventRange; + var eventDef = eventRange.def; + var eventUi = eventRange.ui; + var allDay = eventDef.allDay; + var isDraggable = view.computeEventDraggable(eventDef, eventUi); + var isResizableFromStart = allDay && seg.isStart && view.computeEventStartResizable(eventDef, eventUi); + var isResizableFromEnd = allDay && seg.isEnd && view.computeEventEndResizable(eventDef, eventUi); + var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd, mirrorInfo); + var skinCss = core.cssToStr(this.getSkinCss(eventUi)); + var timeHtml = ''; + var timeText; + var titleHtml; + classes.unshift('fc-day-grid-event', 'fc-h-event'); + // Only display a timed events time if it is the starting segment + if (seg.isStart) { + timeText = this.getTimeText(eventRange); + if (timeText) { + timeHtml = '<span class="fc-time">' + core.htmlEscape(timeText) + '</span>'; + } + } + titleHtml = + '<span class="fc-title">' + + (core.htmlEscape(eventDef.title || '') || ' ') + // we always want one line of height + '</span>'; + return '<a class="' + classes.join(' ') + '"' + + (eventDef.url ? + ' href="' + core.htmlEscape(eventDef.url) + '"' : + '') + + (skinCss ? + ' style="' + skinCss + '"' : + '') + + '>' + + '<div class="fc-content">' + + (options.dir === 'rtl' ? + titleHtml + ' ' + timeHtml : // put a natural space in between + timeHtml + ' ' + titleHtml // + ) + + '</div>' + + (isResizableFromStart ? + '<div class="fc-resizer fc-start-resizer"></div>' : + '') + + (isResizableFromEnd ? + '<div class="fc-resizer fc-end-resizer"></div>' : + '') + + '</a>'; + }; + // Computes a default event time formatting string if `eventTimeFormat` is not explicitly defined + SimpleDayGridEventRenderer.prototype.computeEventTimeFormat = function () { + return { + hour: 'numeric', + minute: '2-digit', + omitZeroMinute: true, + meridiem: 'narrow' + }; + }; + SimpleDayGridEventRenderer.prototype.computeDisplayEventEnd = function () { + return false; // TODO: somehow consider the originating DayGrid's column count + }; + return SimpleDayGridEventRenderer; + }(core.FgEventRenderer)); + + /* Event-rendering methods for the DayGrid class + ----------------------------------------------------------------------------------------------------------------------*/ + var DayGridEventRenderer = /** @class */ (function (_super) { + __extends(DayGridEventRenderer, _super); + function DayGridEventRenderer(dayGrid) { + var _this = _super.call(this, dayGrid.context) || this; + _this.dayGrid = dayGrid; + return _this; + } + // Renders the given foreground event segments onto the grid + DayGridEventRenderer.prototype.attachSegs = function (segs, mirrorInfo) { + var rowStructs = this.rowStructs = this.renderSegRows(segs); + // append to each row's content skeleton + this.dayGrid.rowEls.forEach(function (rowNode, i) { + rowNode.querySelector('.fc-content-skeleton > table').appendChild(rowStructs[i].tbodyEl); + }); + // removes the "more.." events popover + if (!mirrorInfo) { + this.dayGrid.removeSegPopover(); + } + }; + // Unrenders all currently rendered foreground event segments + DayGridEventRenderer.prototype.detachSegs = function () { + var rowStructs = this.rowStructs || []; + var rowStruct; + while ((rowStruct = rowStructs.pop())) { + core.removeElement(rowStruct.tbodyEl); + } + this.rowStructs = null; + }; + // Uses the given events array to generate <tbody> elements that should be appended to each row's content skeleton. + // Returns an array of rowStruct objects (see the bottom of `renderSegRow`). + // PRECONDITION: each segment shoud already have a rendered and assigned `.el` + DayGridEventRenderer.prototype.renderSegRows = function (segs) { + var rowStructs = []; + var segRows; + var row; + segRows = this.groupSegRows(segs); // group into nested arrays + // iterate each row of segment groupings + for (row = 0; row < segRows.length; row++) { + rowStructs.push(this.renderSegRow(row, segRows[row])); + } + return rowStructs; + }; + // Given a row # and an array of segments all in the same row, render a <tbody> element, a skeleton that contains + // the segments. Returns object with a bunch of internal data about how the render was calculated. + // NOTE: modifies rowSegs + DayGridEventRenderer.prototype.renderSegRow = function (row, rowSegs) { + var dayGrid = this.dayGrid; + var colCnt = dayGrid.colCnt, isRtl = dayGrid.isRtl; + var segLevels = this.buildSegLevels(rowSegs); // group into sub-arrays of levels + var levelCnt = Math.max(1, segLevels.length); // ensure at least one level + var tbody = document.createElement('tbody'); + var segMatrix = []; // lookup for which segments are rendered into which level+col cells + var cellMatrix = []; // lookup for all <td> elements of the level+col matrix + var loneCellMatrix = []; // lookup for <td> elements that only take up a single column + var i; + var levelSegs; + var col; + var tr; + var j; + var seg; + var td; + // populates empty cells from the current column (`col`) to `endCol` + function emptyCellsUntil(endCol) { + while (col < endCol) { + // try to grab a cell from the level above and extend its rowspan. otherwise, create a fresh cell + td = (loneCellMatrix[i - 1] || [])[col]; + if (td) { + td.rowSpan = (td.rowSpan || 1) + 1; + } + else { + td = document.createElement('td'); + tr.appendChild(td); + } + cellMatrix[i][col] = td; + loneCellMatrix[i][col] = td; + col++; + } + } + for (i = 0; i < levelCnt; i++) { // iterate through all levels + levelSegs = segLevels[i]; + col = 0; + tr = document.createElement('tr'); + segMatrix.push([]); + cellMatrix.push([]); + loneCellMatrix.push([]); + // levelCnt might be 1 even though there are no actual levels. protect against this. + // this single empty row is useful for styling. + if (levelSegs) { + for (j = 0; j < levelSegs.length; j++) { // iterate through segments in level + seg = levelSegs[j]; + var leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol; + var rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol; + emptyCellsUntil(leftCol); + // create a container that occupies or more columns. append the event element. + td = core.createElement('td', { className: 'fc-event-container' }, seg.el); + if (leftCol !== rightCol) { + td.colSpan = rightCol - leftCol + 1; + } + else { // a single-column segment + loneCellMatrix[i][col] = td; + } + while (col <= rightCol) { + cellMatrix[i][col] = td; + segMatrix[i][col] = seg; + col++; + } + tr.appendChild(td); + } + } + emptyCellsUntil(colCnt); // finish off the row + var introHtml = dayGrid.renderProps.renderIntroHtml(); + if (introHtml) { + if (dayGrid.isRtl) { + core.appendToElement(tr, introHtml); + } + else { + core.prependToElement(tr, introHtml); + } + } + tbody.appendChild(tr); + } + return { + row: row, + tbodyEl: tbody, + cellMatrix: cellMatrix, + segMatrix: segMatrix, + segLevels: segLevels, + segs: rowSegs + }; + }; + // Stacks a flat array of segments, which are all assumed to be in the same row, into subarrays of vertical levels. + // NOTE: modifies segs + DayGridEventRenderer.prototype.buildSegLevels = function (segs) { + var _a = this.dayGrid, isRtl = _a.isRtl, colCnt = _a.colCnt; + var levels = []; + var i; + var seg; + var j; + // Give preference to elements with certain criteria, so they have + // a chance to be closer to the top. + segs = this.sortEventSegs(segs); + for (i = 0; i < segs.length; i++) { + seg = segs[i]; + // loop through levels, starting with the topmost, until the segment doesn't collide with other segments + for (j = 0; j < levels.length; j++) { + if (!isDaySegCollision(seg, levels[j])) { + break; + } + } + // `j` now holds the desired subrow index + seg.level = j; + seg.leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol; // for sorting only + seg.rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol // for sorting only + ; + (levels[j] || (levels[j] = [])).push(seg); + } + // order segments left-to-right. very important if calendar is RTL + for (j = 0; j < levels.length; j++) { + levels[j].sort(compareDaySegCols); + } + return levels; + }; + // Given a flat array of segments, return an array of sub-arrays, grouped by each segment's row + DayGridEventRenderer.prototype.groupSegRows = function (segs) { + var segRows = []; + var i; + for (i = 0; i < this.dayGrid.rowCnt; i++) { + segRows.push([]); + } + for (i = 0; i < segs.length; i++) { + segRows[segs[i].row].push(segs[i]); + } + return segRows; + }; + // Computes a default `displayEventEnd` value if one is not expliclty defined + DayGridEventRenderer.prototype.computeDisplayEventEnd = function () { + return this.dayGrid.colCnt === 1; // we'll likely have space if there's only one day + }; + return DayGridEventRenderer; + }(SimpleDayGridEventRenderer)); + // Computes whether two segments' columns collide. They are assumed to be in the same row. + function isDaySegCollision(seg, otherSegs) { + var i; + var otherSeg; + for (i = 0; i < otherSegs.length; i++) { + otherSeg = otherSegs[i]; + if (otherSeg.firstCol <= seg.lastCol && + otherSeg.lastCol >= seg.firstCol) { + return true; + } + } + return false; + } + // A cmp function for determining the leftmost event + function compareDaySegCols(a, b) { + return a.leftCol - b.leftCol; + } + + var DayGridMirrorRenderer = /** @class */ (function (_super) { + __extends(DayGridMirrorRenderer, _super); + function DayGridMirrorRenderer() { + return _super !== null && _super.apply(this, arguments) || this; + } + DayGridMirrorRenderer.prototype.attachSegs = function (segs, mirrorInfo) { + var sourceSeg = mirrorInfo.sourceSeg; + var rowStructs = this.rowStructs = this.renderSegRows(segs); + // inject each new event skeleton into each associated row + this.dayGrid.rowEls.forEach(function (rowNode, row) { + var skeletonEl = core.htmlToElement('<div class="fc-mirror-skeleton"><table></table></div>'); // will be absolutely positioned + var skeletonTopEl; + var skeletonTop; + // If there is an original segment, match the top position. Otherwise, put it at the row's top level + if (sourceSeg && sourceSeg.row === row) { + skeletonTopEl = sourceSeg.el; + } + else { + skeletonTopEl = rowNode.querySelector('.fc-content-skeleton tbody'); + if (!skeletonTopEl) { // when no events + skeletonTopEl = rowNode.querySelector('.fc-content-skeleton table'); + } + } + skeletonTop = skeletonTopEl.getBoundingClientRect().top - + rowNode.getBoundingClientRect().top; // the offsetParent origin + skeletonEl.style.top = skeletonTop + 'px'; + skeletonEl.querySelector('table').appendChild(rowStructs[row].tbodyEl); + rowNode.appendChild(skeletonEl); + }); + }; + return DayGridMirrorRenderer; + }(DayGridEventRenderer)); + + var EMPTY_CELL_HTML = '<td style="pointer-events:none"></td>'; + var DayGridFillRenderer = /** @class */ (function (_super) { + __extends(DayGridFillRenderer, _super); + function DayGridFillRenderer(dayGrid) { + var _this = _super.call(this, dayGrid.context) || this; + _this.fillSegTag = 'td'; // override the default tag name + _this.dayGrid = dayGrid; + return _this; + } + DayGridFillRenderer.prototype.renderSegs = function (type, segs) { + // don't render timed background events + if (type === 'bgEvent') { + segs = segs.filter(function (seg) { + return seg.eventRange.def.allDay; + }); + } + _super.prototype.renderSegs.call(this, type, segs); + }; + DayGridFillRenderer.prototype.attachSegs = function (type, segs) { + var els = []; + var i; + var seg; + var skeletonEl; + for (i = 0; i < segs.length; i++) { + seg = segs[i]; + skeletonEl = this.renderFillRow(type, seg); + this.dayGrid.rowEls[seg.row].appendChild(skeletonEl); + els.push(skeletonEl); + } + return els; + }; + // Generates the HTML needed for one row of a fill. Requires the seg's el to be rendered. + DayGridFillRenderer.prototype.renderFillRow = function (type, seg) { + var dayGrid = this.dayGrid; + var colCnt = dayGrid.colCnt, isRtl = dayGrid.isRtl; + var leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol; + var rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol; + var startCol = leftCol; + var endCol = rightCol + 1; + var className; + var skeletonEl; + var trEl; + if (type === 'businessHours') { + className = 'bgevent'; + } + else { + className = type.toLowerCase(); + } + skeletonEl = core.htmlToElement('<div class="fc-' + className + '-skeleton">' + + '<table><tr></tr></table>' + + '</div>'); + trEl = skeletonEl.getElementsByTagName('tr')[0]; + if (startCol > 0) { + core.appendToElement(trEl, + // will create (startCol + 1) td's + new Array(startCol + 1).join(EMPTY_CELL_HTML)); + } + seg.el.colSpan = endCol - startCol; + trEl.appendChild(seg.el); + if (endCol < colCnt) { + core.appendToElement(trEl, + // will create (colCnt - endCol) td's + new Array(colCnt - endCol + 1).join(EMPTY_CELL_HTML)); + } + var introHtml = dayGrid.renderProps.renderIntroHtml(); + if (introHtml) { + if (dayGrid.isRtl) { + core.appendToElement(trEl, introHtml); + } + else { + core.prependToElement(trEl, introHtml); + } + } + return skeletonEl; + }; + return DayGridFillRenderer; + }(core.FillRenderer)); + + var DayTile = /** @class */ (function (_super) { + __extends(DayTile, _super); + function DayTile(context, el) { + var _this = _super.call(this, context, el) || this; + var eventRenderer = _this.eventRenderer = new DayTileEventRenderer(_this); + var renderFrame = _this.renderFrame = core.memoizeRendering(_this._renderFrame); + _this.renderFgEvents = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer), [renderFrame]); + _this.renderEventSelection = core.memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]); + _this.renderEventDrag = core.memoizeRendering(eventRenderer.hideByHash.bind(eventRenderer), eventRenderer.showByHash.bind(eventRenderer), [renderFrame]); + _this.renderEventResize = core.memoizeRendering(eventRenderer.hideByHash.bind(eventRenderer), eventRenderer.showByHash.bind(eventRenderer), [renderFrame]); + context.calendar.registerInteractiveComponent(_this, { + el: _this.el, + useEventCenter: false + }); + return _this; + } + DayTile.prototype.render = function (props) { + this.renderFrame(props.date); + this.renderFgEvents(props.fgSegs); + this.renderEventSelection(props.eventSelection); + this.renderEventDrag(props.eventDragInstances); + this.renderEventResize(props.eventResizeInstances); + }; + DayTile.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.renderFrame.unrender(); // should unrender everything else + this.calendar.unregisterInteractiveComponent(this); + }; + DayTile.prototype._renderFrame = function (date) { + var _a = this, theme = _a.theme, dateEnv = _a.dateEnv; + var title = dateEnv.format(date, core.createFormatter(this.opt('dayPopoverFormat')) // TODO: cache + ); + this.el.innerHTML = + '<div class="fc-header ' + theme.getClass('popoverHeader') + '">' + + '<span class="fc-title">' + + core.htmlEscape(title) + + '</span>' + + '<span class="fc-close ' + theme.getIconClass('close') + '"></span>' + + '</div>' + + '<div class="fc-body ' + theme.getClass('popoverContent') + '">' + + '<div class="fc-event-container"></div>' + + '</div>'; + this.segContainerEl = this.el.querySelector('.fc-event-container'); + }; + DayTile.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) { + var date = this.props.date; // HACK + if (positionLeft < elWidth && positionTop < elHeight) { + return { + component: this, + dateSpan: { + allDay: true, + range: { start: date, end: core.addDays(date, 1) } + }, + dayEl: this.el, + rect: { + left: 0, + top: 0, + right: elWidth, + bottom: elHeight + }, + layer: 1 + }; + } + }; + return DayTile; + }(core.DateComponent)); + var DayTileEventRenderer = /** @class */ (function (_super) { + __extends(DayTileEventRenderer, _super); + function DayTileEventRenderer(dayTile) { + var _this = _super.call(this, dayTile.context) || this; + _this.dayTile = dayTile; + return _this; + } + DayTileEventRenderer.prototype.attachSegs = function (segs) { + for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { + var seg = segs_1[_i]; + this.dayTile.segContainerEl.appendChild(seg.el); + } + }; + DayTileEventRenderer.prototype.detachSegs = function (segs) { + for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { + var seg = segs_2[_i]; + core.removeElement(seg.el); + } + }; + return DayTileEventRenderer; + }(SimpleDayGridEventRenderer)); + + var DayBgRow = /** @class */ (function () { + function DayBgRow(context) { + this.context = context; + } + DayBgRow.prototype.renderHtml = function (props) { + var parts = []; + if (props.renderIntroHtml) { + parts.push(props.renderIntroHtml()); + } + for (var _i = 0, _a = props.cells; _i < _a.length; _i++) { + var cell = _a[_i]; + parts.push(renderCellHtml(cell.date, props.dateProfile, this.context, cell.htmlAttrs)); + } + if (!props.cells.length) { + parts.push('<td class="fc-day ' + this.context.theme.getClass('widgetContent') + '"></td>'); + } + if (this.context.options.dir === 'rtl') { + parts.reverse(); + } + return '<tr>' + parts.join('') + '</tr>'; + }; + return DayBgRow; + }()); + function renderCellHtml(date, dateProfile, context, otherAttrs) { + var dateEnv = context.dateEnv, theme = context.theme; + var isDateValid = core.rangeContainsMarker(dateProfile.activeRange, date); // TODO: called too frequently. cache somehow. + var classes = core.getDayClasses(date, dateProfile, context); + classes.unshift('fc-day', theme.getClass('widgetContent')); + return '<td class="' + classes.join(' ') + '"' + + (isDateValid ? + ' data-date="' + dateEnv.formatIso(date, { omitTime: true }) + '"' : + '') + + (otherAttrs ? + ' ' + otherAttrs : + '') + + '></td>'; + } + + var DAY_NUM_FORMAT = core.createFormatter({ day: 'numeric' }); + var WEEK_NUM_FORMAT = core.createFormatter({ week: 'numeric' }); + var DayGrid = /** @class */ (function (_super) { + __extends(DayGrid, _super); + function DayGrid(context, el, renderProps) { + var _this = _super.call(this, context, el) || this; + _this.bottomCoordPadding = 0; // hack for extending the hit area for the last row of the coordinate grid + _this.isCellSizesDirty = false; + var eventRenderer = _this.eventRenderer = new DayGridEventRenderer(_this); + var fillRenderer = _this.fillRenderer = new DayGridFillRenderer(_this); + _this.mirrorRenderer = new DayGridMirrorRenderer(_this); + var renderCells = _this.renderCells = core.memoizeRendering(_this._renderCells, _this._unrenderCells); + _this.renderBusinessHours = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'businessHours'), fillRenderer.unrender.bind(fillRenderer, 'businessHours'), [renderCells]); + _this.renderDateSelection = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'highlight'), fillRenderer.unrender.bind(fillRenderer, 'highlight'), [renderCells]); + _this.renderBgEvents = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'bgEvent'), fillRenderer.unrender.bind(fillRenderer, 'bgEvent'), [renderCells]); + _this.renderFgEvents = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer), [renderCells]); + _this.renderEventSelection = core.memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]); + _this.renderEventDrag = core.memoizeRendering(_this._renderEventDrag, _this._unrenderEventDrag, [renderCells]); + _this.renderEventResize = core.memoizeRendering(_this._renderEventResize, _this._unrenderEventResize, [renderCells]); + _this.renderProps = renderProps; + return _this; + } + DayGrid.prototype.render = function (props) { + var cells = props.cells; + this.rowCnt = cells.length; + this.colCnt = cells[0].length; + this.renderCells(cells, props.isRigid); + this.renderBusinessHours(props.businessHourSegs); + this.renderDateSelection(props.dateSelectionSegs); + this.renderBgEvents(props.bgEventSegs); + this.renderFgEvents(props.fgEventSegs); + this.renderEventSelection(props.eventSelection); + this.renderEventDrag(props.eventDrag); + this.renderEventResize(props.eventResize); + if (this.segPopoverTile) { + this.updateSegPopoverTile(); + } + }; + DayGrid.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.renderCells.unrender(); // will unrender everything else + }; + DayGrid.prototype.getCellRange = function (row, col) { + var start = this.props.cells[row][col].date; + var end = core.addDays(start, 1); + return { start: start, end: end }; + }; + DayGrid.prototype.updateSegPopoverTile = function (date, segs) { + var ownProps = this.props; + this.segPopoverTile.receiveProps({ + date: date || this.segPopoverTile.props.date, + fgSegs: segs || this.segPopoverTile.props.fgSegs, + eventSelection: ownProps.eventSelection, + eventDragInstances: ownProps.eventDrag ? ownProps.eventDrag.affectedInstances : null, + eventResizeInstances: ownProps.eventResize ? ownProps.eventResize.affectedInstances : null + }); + }; + /* Date Rendering + ------------------------------------------------------------------------------------------------------------------*/ + DayGrid.prototype._renderCells = function (cells, isRigid) { + var _a = this, view = _a.view, dateEnv = _a.dateEnv; + var _b = this, rowCnt = _b.rowCnt, colCnt = _b.colCnt; + var html = ''; + var row; + var col; + for (row = 0; row < rowCnt; row++) { + html += this.renderDayRowHtml(row, isRigid); + } + this.el.innerHTML = html; + this.rowEls = core.findElements(this.el, '.fc-row'); + this.cellEls = core.findElements(this.el, '.fc-day, .fc-disabled-day'); + if (this.isRtl) { + this.cellEls.reverse(); + } + this.rowPositions = new core.PositionCache(this.el, this.rowEls, false, true // vertical + ); + this.colPositions = new core.PositionCache(this.el, this.cellEls.slice(0, colCnt), // only the first row + true, false // horizontal + ); + // trigger dayRender with each cell's element + for (row = 0; row < rowCnt; row++) { + for (col = 0; col < colCnt; col++) { + this.publiclyTrigger('dayRender', [ + { + date: dateEnv.toDate(cells[row][col].date), + el: this.getCellEl(row, col), + view: view + } + ]); + } + } + this.isCellSizesDirty = true; + }; + DayGrid.prototype._unrenderCells = function () { + this.removeSegPopover(); + }; + // Generates the HTML for a single row, which is a div that wraps a table. + // `row` is the row number. + DayGrid.prototype.renderDayRowHtml = function (row, isRigid) { + var theme = this.theme; + var classes = ['fc-row', 'fc-week', theme.getClass('dayRow')]; + if (isRigid) { + classes.push('fc-rigid'); + } + var bgRow = new DayBgRow(this.context); + return '' + + '<div class="' + classes.join(' ') + '">' + + '<div class="fc-bg">' + + '<table class="' + theme.getClass('tableGrid') + '">' + + bgRow.renderHtml({ + cells: this.props.cells[row], + dateProfile: this.props.dateProfile, + renderIntroHtml: this.renderProps.renderBgIntroHtml + }) + + '</table>' + + '</div>' + + '<div class="fc-content-skeleton">' + + '<table>' + + (this.getIsNumbersVisible() ? + '<thead>' + + this.renderNumberTrHtml(row) + + '</thead>' : + '') + + '</table>' + + '</div>' + + '</div>'; + }; + DayGrid.prototype.getIsNumbersVisible = function () { + return this.getIsDayNumbersVisible() || + this.renderProps.cellWeekNumbersVisible || + this.renderProps.colWeekNumbersVisible; + }; + DayGrid.prototype.getIsDayNumbersVisible = function () { + return this.rowCnt > 1; + }; + /* Grid Number Rendering + ------------------------------------------------------------------------------------------------------------------*/ + DayGrid.prototype.renderNumberTrHtml = function (row) { + var intro = this.renderProps.renderNumberIntroHtml(row, this); + return '' + + '<tr>' + + (this.isRtl ? '' : intro) + + this.renderNumberCellsHtml(row) + + (this.isRtl ? intro : '') + + '</tr>'; + }; + DayGrid.prototype.renderNumberCellsHtml = function (row) { + var htmls = []; + var col; + var date; + for (col = 0; col < this.colCnt; col++) { + date = this.props.cells[row][col].date; + htmls.push(this.renderNumberCellHtml(date)); + } + if (this.isRtl) { + htmls.reverse(); + } + return htmls.join(''); + }; + // Generates the HTML for the <td>s of the "number" row in the DayGrid's content skeleton. + // The number row will only exist if either day numbers or week numbers are turned on. + DayGrid.prototype.renderNumberCellHtml = function (date) { + var _a = this, view = _a.view, dateEnv = _a.dateEnv; + var html = ''; + var isDateValid = core.rangeContainsMarker(this.props.dateProfile.activeRange, date); // TODO: called too frequently. cache somehow. + var isDayNumberVisible = this.getIsDayNumbersVisible() && isDateValid; + var classes; + var weekCalcFirstDow; + if (!isDayNumberVisible && !this.renderProps.cellWeekNumbersVisible) { + // no numbers in day cell (week number must be along the side) + return '<td></td>'; // will create an empty space above events :( + } + classes = core.getDayClasses(date, this.props.dateProfile, this.context); + classes.unshift('fc-day-top'); + if (this.renderProps.cellWeekNumbersVisible) { + weekCalcFirstDow = dateEnv.weekDow; + } + html += '<td class="' + classes.join(' ') + '"' + + (isDateValid ? + ' data-date="' + dateEnv.formatIso(date, { omitTime: true }) + '"' : + '') + + '>'; + if (this.renderProps.cellWeekNumbersVisible && (date.getUTCDay() === weekCalcFirstDow)) { + html += core.buildGotoAnchorHtml(view, { date: date, type: 'week' }, { 'class': 'fc-week-number' }, dateEnv.format(date, WEEK_NUM_FORMAT) // inner HTML + ); + } + if (isDayNumberVisible) { + html += core.buildGotoAnchorHtml(view, date, { 'class': 'fc-day-number' }, dateEnv.format(date, DAY_NUM_FORMAT) // inner HTML + ); + } + html += '</td>'; + return html; + }; + /* Sizing + ------------------------------------------------------------------------------------------------------------------*/ + DayGrid.prototype.updateSize = function (isResize) { + var _a = this, fillRenderer = _a.fillRenderer, eventRenderer = _a.eventRenderer, mirrorRenderer = _a.mirrorRenderer; + if (isResize || + this.isCellSizesDirty || + this.view.calendar.isEventsUpdated // hack + ) { + this.buildPositionCaches(); + this.isCellSizesDirty = false; + } + fillRenderer.computeSizes(isResize); + eventRenderer.computeSizes(isResize); + mirrorRenderer.computeSizes(isResize); + fillRenderer.assignSizes(isResize); + eventRenderer.assignSizes(isResize); + mirrorRenderer.assignSizes(isResize); + }; + DayGrid.prototype.buildPositionCaches = function () { + this.buildColPositions(); + this.buildRowPositions(); + }; + DayGrid.prototype.buildColPositions = function () { + this.colPositions.build(); + }; + DayGrid.prototype.buildRowPositions = function () { + this.rowPositions.build(); + this.rowPositions.bottoms[this.rowCnt - 1] += this.bottomCoordPadding; // hack + }; + /* Hit System + ------------------------------------------------------------------------------------------------------------------*/ + DayGrid.prototype.positionToHit = function (leftPosition, topPosition) { + var _a = this, colPositions = _a.colPositions, rowPositions = _a.rowPositions; + var col = colPositions.leftToIndex(leftPosition); + var row = rowPositions.topToIndex(topPosition); + if (row != null && col != null) { + return { + row: row, + col: col, + dateSpan: { + range: this.getCellRange(row, col), + allDay: true + }, + dayEl: this.getCellEl(row, col), + relativeRect: { + left: colPositions.lefts[col], + right: colPositions.rights[col], + top: rowPositions.tops[row], + bottom: rowPositions.bottoms[row] + } + }; + } + }; + /* Cell System + ------------------------------------------------------------------------------------------------------------------*/ + // FYI: the first column is the leftmost column, regardless of date + DayGrid.prototype.getCellEl = function (row, col) { + return this.cellEls[row * this.colCnt + col]; + }; + /* Event Drag Visualization + ------------------------------------------------------------------------------------------------------------------*/ + DayGrid.prototype._renderEventDrag = function (state) { + if (state) { + this.eventRenderer.hideByHash(state.affectedInstances); + this.fillRenderer.renderSegs('highlight', state.segs); + } + }; + DayGrid.prototype._unrenderEventDrag = function (state) { + if (state) { + this.eventRenderer.showByHash(state.affectedInstances); + this.fillRenderer.unrender('highlight'); + } + }; + /* Event Resize Visualization + ------------------------------------------------------------------------------------------------------------------*/ + DayGrid.prototype._renderEventResize = function (state) { + if (state) { + this.eventRenderer.hideByHash(state.affectedInstances); + this.fillRenderer.renderSegs('highlight', state.segs); + this.mirrorRenderer.renderSegs(state.segs, { isResizing: true, sourceSeg: state.sourceSeg }); + } + }; + DayGrid.prototype._unrenderEventResize = function (state) { + if (state) { + this.eventRenderer.showByHash(state.affectedInstances); + this.fillRenderer.unrender('highlight'); + this.mirrorRenderer.unrender(state.segs, { isResizing: true, sourceSeg: state.sourceSeg }); + } + }; + /* More+ Link Popover + ------------------------------------------------------------------------------------------------------------------*/ + DayGrid.prototype.removeSegPopover = function () { + if (this.segPopover) { + this.segPopover.hide(); // in handler, will call segPopover's removeElement + } + }; + // Limits the number of "levels" (vertically stacking layers of events) for each row of the grid. + // `levelLimit` can be false (don't limit), a number, or true (should be computed). + DayGrid.prototype.limitRows = function (levelLimit) { + var rowStructs = this.eventRenderer.rowStructs || []; + var row; // row # + var rowLevelLimit; + for (row = 0; row < rowStructs.length; row++) { + this.unlimitRow(row); + if (!levelLimit) { + rowLevelLimit = false; + } + else if (typeof levelLimit === 'number') { + rowLevelLimit = levelLimit; + } + else { + rowLevelLimit = this.computeRowLevelLimit(row); + } + if (rowLevelLimit !== false) { + this.limitRow(row, rowLevelLimit); + } + } + }; + // Computes the number of levels a row will accomodate without going outside its bounds. + // Assumes the row is "rigid" (maintains a constant height regardless of what is inside). + // `row` is the row number. + DayGrid.prototype.computeRowLevelLimit = function (row) { + var rowEl = this.rowEls[row]; // the containing "fake" row div + var rowBottom = rowEl.getBoundingClientRect().bottom; // relative to viewport! + var trEls = core.findChildren(this.eventRenderer.rowStructs[row].tbodyEl); + var i; + var trEl; + // Reveal one level <tr> at a time and stop when we find one out of bounds + for (i = 0; i < trEls.length; i++) { + trEl = trEls[i]; + trEl.classList.remove('fc-limited'); // reset to original state (reveal) + if (trEl.getBoundingClientRect().bottom > rowBottom) { + return i; + } + } + return false; // should not limit at all + }; + // Limits the given grid row to the maximum number of levels and injects "more" links if necessary. + // `row` is the row number. + // `levelLimit` is a number for the maximum (inclusive) number of levels allowed. + DayGrid.prototype.limitRow = function (row, levelLimit) { + var _this = this; + var _a = this, colCnt = _a.colCnt, isRtl = _a.isRtl; + var rowStruct = this.eventRenderer.rowStructs[row]; + var moreNodes = []; // array of "more" <a> links and <td> DOM nodes + var col = 0; // col #, left-to-right (not chronologically) + var levelSegs; // array of segment objects in the last allowable level, ordered left-to-right + var cellMatrix; // a matrix (by level, then column) of all <td> elements in the row + var limitedNodes; // array of temporarily hidden level <tr> and segment <td> DOM nodes + var i; + var seg; + var segsBelow; // array of segment objects below `seg` in the current `col` + var totalSegsBelow; // total number of segments below `seg` in any of the columns `seg` occupies + var colSegsBelow; // array of segment arrays, below seg, one for each column (offset from segs's first column) + var td; + var rowSpan; + var segMoreNodes; // array of "more" <td> cells that will stand-in for the current seg's cell + var j; + var moreTd; + var moreWrap; + var moreLink; + // Iterates through empty level cells and places "more" links inside if need be + var emptyCellsUntil = function (endCol) { + while (col < endCol) { + segsBelow = _this.getCellSegs(row, col, levelLimit); + if (segsBelow.length) { + td = cellMatrix[levelLimit - 1][col]; + moreLink = _this.renderMoreLink(row, col, segsBelow); + moreWrap = core.createElement('div', null, moreLink); + td.appendChild(moreWrap); + moreNodes.push(moreWrap); + } + col++; + } + }; + if (levelLimit && levelLimit < rowStruct.segLevels.length) { // is it actually over the limit? + levelSegs = rowStruct.segLevels[levelLimit - 1]; + cellMatrix = rowStruct.cellMatrix; + limitedNodes = core.findChildren(rowStruct.tbodyEl).slice(levelLimit); // get level <tr> elements past the limit + limitedNodes.forEach(function (node) { + node.classList.add('fc-limited'); // hide elements and get a simple DOM-nodes array + }); + // iterate though segments in the last allowable level + for (i = 0; i < levelSegs.length; i++) { + seg = levelSegs[i]; + var leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol; + var rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol; + emptyCellsUntil(leftCol); // process empty cells before the segment + // determine *all* segments below `seg` that occupy the same columns + colSegsBelow = []; + totalSegsBelow = 0; + while (col <= rightCol) { + segsBelow = this.getCellSegs(row, col, levelLimit); + colSegsBelow.push(segsBelow); + totalSegsBelow += segsBelow.length; + col++; + } + if (totalSegsBelow) { // do we need to replace this segment with one or many "more" links? + td = cellMatrix[levelLimit - 1][leftCol]; // the segment's parent cell + rowSpan = td.rowSpan || 1; + segMoreNodes = []; + // make a replacement <td> for each column the segment occupies. will be one for each colspan + for (j = 0; j < colSegsBelow.length; j++) { + moreTd = core.createElement('td', { className: 'fc-more-cell', rowSpan: rowSpan }); + segsBelow = colSegsBelow[j]; + moreLink = this.renderMoreLink(row, leftCol + j, [seg].concat(segsBelow) // count seg as hidden too + ); + moreWrap = core.createElement('div', null, moreLink); + moreTd.appendChild(moreWrap); + segMoreNodes.push(moreTd); + moreNodes.push(moreTd); + } + td.classList.add('fc-limited'); + core.insertAfterElement(td, segMoreNodes); + limitedNodes.push(td); + } + } + emptyCellsUntil(this.colCnt); // finish off the level + rowStruct.moreEls = moreNodes; // for easy undoing later + rowStruct.limitedEls = limitedNodes; // for easy undoing later + } + }; + // Reveals all levels and removes all "more"-related elements for a grid's row. + // `row` is a row number. + DayGrid.prototype.unlimitRow = function (row) { + var rowStruct = this.eventRenderer.rowStructs[row]; + if (rowStruct.moreEls) { + rowStruct.moreEls.forEach(core.removeElement); + rowStruct.moreEls = null; + } + if (rowStruct.limitedEls) { + rowStruct.limitedEls.forEach(function (limitedEl) { + limitedEl.classList.remove('fc-limited'); + }); + rowStruct.limitedEls = null; + } + }; + // Renders an <a> element that represents hidden event element for a cell. + // Responsible for attaching click handler as well. + DayGrid.prototype.renderMoreLink = function (row, col, hiddenSegs) { + var _this = this; + var _a = this, view = _a.view, dateEnv = _a.dateEnv; + var a = core.createElement('a', { className: 'fc-more' }); + a.innerText = this.getMoreLinkText(hiddenSegs.length); + a.addEventListener('click', function (ev) { + var clickOption = _this.opt('eventLimitClick'); + var _col = _this.isRtl ? _this.colCnt - col - 1 : col; // HACK: props.cells has different dir system? + var date = _this.props.cells[row][_col].date; + var moreEl = ev.currentTarget; + var dayEl = _this.getCellEl(row, col); + var allSegs = _this.getCellSegs(row, col); + // rescope the segments to be within the cell's date + var reslicedAllSegs = _this.resliceDaySegs(allSegs, date); + var reslicedHiddenSegs = _this.resliceDaySegs(hiddenSegs, date); + if (typeof clickOption === 'function') { + // the returned value can be an atomic option + clickOption = _this.publiclyTrigger('eventLimitClick', [ + { + date: dateEnv.toDate(date), + allDay: true, + dayEl: dayEl, + moreEl: moreEl, + segs: reslicedAllSegs, + hiddenSegs: reslicedHiddenSegs, + jsEvent: ev, + view: view + } + ]); + } + if (clickOption === 'popover') { + _this.showSegPopover(row, col, moreEl, reslicedAllSegs); + } + else if (typeof clickOption === 'string') { // a view name + view.calendar.zoomTo(date, clickOption); + } + }); + return a; + }; + // Reveals the popover that displays all events within a cell + DayGrid.prototype.showSegPopover = function (row, col, moreLink, segs) { + var _this = this; + var _a = this, calendar = _a.calendar, view = _a.view, theme = _a.theme; + var _col = this.isRtl ? this.colCnt - col - 1 : col; // HACK: props.cells has different dir system? + var moreWrap = moreLink.parentNode; // the <div> wrapper around the <a> + var topEl; // the element we want to match the top coordinate of + var options; + if (this.rowCnt === 1) { + topEl = view.el; // will cause the popover to cover any sort of header + } + else { + topEl = this.rowEls[row]; // will align with top of row + } + options = { + className: 'fc-more-popover ' + theme.getClass('popover'), + parentEl: view.el, + top: core.computeRect(topEl).top, + autoHide: true, + content: function (el) { + _this.segPopoverTile = new DayTile(_this.context, el); + _this.updateSegPopoverTile(_this.props.cells[row][_col].date, segs); + }, + hide: function () { + _this.segPopoverTile.destroy(); + _this.segPopoverTile = null; + _this.segPopover.destroy(); + _this.segPopover = null; + } + }; + // Determine horizontal coordinate. + // We use the moreWrap instead of the <td> to avoid border confusion. + if (this.isRtl) { + options.right = core.computeRect(moreWrap).right + 1; // +1 to be over cell border + } + else { + options.left = core.computeRect(moreWrap).left - 1; // -1 to be over cell border + } + this.segPopover = new Popover(options); + this.segPopover.show(); + calendar.releaseAfterSizingTriggers(); // hack for eventPositioned + }; + // Given the events within an array of segment objects, reslice them to be in a single day + DayGrid.prototype.resliceDaySegs = function (segs, dayDate) { + var dayStart = dayDate; + var dayEnd = core.addDays(dayStart, 1); + var dayRange = { start: dayStart, end: dayEnd }; + var newSegs = []; + for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { + var seg = segs_1[_i]; + var eventRange = seg.eventRange; + var origRange = eventRange.range; + var slicedRange = core.intersectRanges(origRange, dayRange); + if (slicedRange) { + newSegs.push(__assign({}, seg, { eventRange: { + def: eventRange.def, + ui: __assign({}, eventRange.ui, { durationEditable: false }), + instance: eventRange.instance, + range: slicedRange + }, isStart: seg.isStart && slicedRange.start.valueOf() === origRange.start.valueOf(), isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf() })); + } + } + return newSegs; + }; + // Generates the text that should be inside a "more" link, given the number of events it represents + DayGrid.prototype.getMoreLinkText = function (num) { + var opt = this.opt('eventLimitText'); + if (typeof opt === 'function') { + return opt(num); + } + else { + return '+' + num + ' ' + opt; + } + }; + // Returns segments within a given cell. + // If `startLevel` is specified, returns only events including and below that level. Otherwise returns all segs. + DayGrid.prototype.getCellSegs = function (row, col, startLevel) { + var segMatrix = this.eventRenderer.rowStructs[row].segMatrix; + var level = startLevel || 0; + var segs = []; + var seg; + while (level < segMatrix.length) { + seg = segMatrix[level][col]; + if (seg) { + segs.push(seg); + } + level++; + } + return segs; + }; + return DayGrid; + }(core.DateComponent)); + + var WEEK_NUM_FORMAT$1 = core.createFormatter({ week: 'numeric' }); + /* An abstract class for the daygrid views, as well as month view. Renders one or more rows of day cells. + ----------------------------------------------------------------------------------------------------------------------*/ + // It is a manager for a DayGrid subcomponent, which does most of the heavy lifting. + // It is responsible for managing width/height. + var DayGridView = /** @class */ (function (_super) { + __extends(DayGridView, _super); + function DayGridView(context, viewSpec, dateProfileGenerator, parentEl) { + var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this; + /* Header Rendering + ------------------------------------------------------------------------------------------------------------------*/ + // Generates the HTML that will go before the day-of week header cells + _this.renderHeadIntroHtml = function () { + var theme = _this.theme; + if (_this.colWeekNumbersVisible) { + return '' + + '<th class="fc-week-number ' + theme.getClass('widgetHeader') + '" ' + _this.weekNumberStyleAttr() + '>' + + '<span>' + // needed for matchCellWidths + core.htmlEscape(_this.opt('weekLabel')) + + '</span>' + + '</th>'; + } + return ''; + }; + /* Day Grid Rendering + ------------------------------------------------------------------------------------------------------------------*/ + // Generates the HTML that will go before content-skeleton cells that display the day/week numbers + _this.renderDayGridNumberIntroHtml = function (row, dayGrid) { + var dateEnv = _this.dateEnv; + var weekStart = dayGrid.props.cells[row][0].date; + if (_this.colWeekNumbersVisible) { + return '' + + '<td class="fc-week-number" ' + _this.weekNumberStyleAttr() + '>' + + core.buildGotoAnchorHtml(// aside from link, important for matchCellWidths + _this, { date: weekStart, type: 'week', forceOff: dayGrid.colCnt === 1 }, dateEnv.format(weekStart, WEEK_NUM_FORMAT$1) // inner HTML + ) + + '</td>'; + } + return ''; + }; + // Generates the HTML that goes before the day bg cells for each day-row + _this.renderDayGridBgIntroHtml = function () { + var theme = _this.theme; + if (_this.colWeekNumbersVisible) { + return '<td class="fc-week-number ' + theme.getClass('widgetContent') + '" ' + _this.weekNumberStyleAttr() + '></td>'; + } + return ''; + }; + // Generates the HTML that goes before every other type of row generated by DayGrid. + // Affects mirror-skeleton and highlight-skeleton rows. + _this.renderDayGridIntroHtml = function () { + if (_this.colWeekNumbersVisible) { + return '<td class="fc-week-number" ' + _this.weekNumberStyleAttr() + '></td>'; + } + return ''; + }; + _this.el.classList.add('fc-dayGrid-view'); + _this.el.innerHTML = _this.renderSkeletonHtml(); + _this.scroller = new core.ScrollComponent('hidden', // overflow x + 'auto' // overflow y + ); + var dayGridContainerEl = _this.scroller.el; + _this.el.querySelector('.fc-body > tr > td').appendChild(dayGridContainerEl); + dayGridContainerEl.classList.add('fc-day-grid-container'); + var dayGridEl = core.createElement('div', { className: 'fc-day-grid' }); + dayGridContainerEl.appendChild(dayGridEl); + var cellWeekNumbersVisible; + if (_this.opt('weekNumbers')) { + if (_this.opt('weekNumbersWithinDays')) { + cellWeekNumbersVisible = true; + _this.colWeekNumbersVisible = false; + } + else { + cellWeekNumbersVisible = false; + _this.colWeekNumbersVisible = true; + } + } + else { + _this.colWeekNumbersVisible = false; + cellWeekNumbersVisible = false; + } + _this.dayGrid = new DayGrid(_this.context, dayGridEl, { + renderNumberIntroHtml: _this.renderDayGridNumberIntroHtml, + renderBgIntroHtml: _this.renderDayGridBgIntroHtml, + renderIntroHtml: _this.renderDayGridIntroHtml, + colWeekNumbersVisible: _this.colWeekNumbersVisible, + cellWeekNumbersVisible: cellWeekNumbersVisible + }); + return _this; + } + DayGridView.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.dayGrid.destroy(); + this.scroller.destroy(); + }; + // Builds the HTML skeleton for the view. + // The day-grid component will render inside of a container defined by this HTML. + DayGridView.prototype.renderSkeletonHtml = function () { + var theme = this.theme; + return '' + + '<table class="' + theme.getClass('tableGrid') + '">' + + (this.opt('columnHeader') ? + '<thead class="fc-head">' + + '<tr>' + + '<td class="fc-head-container ' + theme.getClass('widgetHeader') + '"> </td>' + + '</tr>' + + '</thead>' : + '') + + '<tbody class="fc-body">' + + '<tr>' + + '<td class="' + theme.getClass('widgetContent') + '"></td>' + + '</tr>' + + '</tbody>' + + '</table>'; + }; + // Generates an HTML attribute string for setting the width of the week number column, if it is known + DayGridView.prototype.weekNumberStyleAttr = function () { + if (this.weekNumberWidth != null) { + return 'style="width:' + this.weekNumberWidth + 'px"'; + } + return ''; + }; + // Determines whether each row should have a constant height + DayGridView.prototype.hasRigidRows = function () { + var eventLimit = this.opt('eventLimit'); + return eventLimit && typeof eventLimit !== 'number'; + }; + /* Dimensions + ------------------------------------------------------------------------------------------------------------------*/ + DayGridView.prototype.updateSize = function (isResize, viewHeight, isAuto) { + _super.prototype.updateSize.call(this, isResize, viewHeight, isAuto); // will call updateBaseSize. important that executes first + this.dayGrid.updateSize(isResize); + }; + // Refreshes the horizontal dimensions of the view + DayGridView.prototype.updateBaseSize = function (isResize, viewHeight, isAuto) { + var dayGrid = this.dayGrid; + var eventLimit = this.opt('eventLimit'); + var headRowEl = this.header ? this.header.el : null; // HACK + var scrollerHeight; + var scrollbarWidths; + // hack to give the view some height prior to dayGrid's columns being rendered + // TODO: separate setting height from scroller VS dayGrid. + if (!dayGrid.rowEls) { + if (!isAuto) { + scrollerHeight = this.computeScrollerHeight(viewHeight); + this.scroller.setHeight(scrollerHeight); + } + return; + } + if (this.colWeekNumbersVisible) { + // Make sure all week number cells running down the side have the same width. + this.weekNumberWidth = core.matchCellWidths(core.findElements(this.el, '.fc-week-number')); + } + // reset all heights to be natural + this.scroller.clear(); + if (headRowEl) { + core.uncompensateScroll(headRowEl); + } + dayGrid.removeSegPopover(); // kill the "more" popover if displayed + // is the event limit a constant level number? + if (eventLimit && typeof eventLimit === 'number') { + dayGrid.limitRows(eventLimit); // limit the levels first so the height can redistribute after + } + // distribute the height to the rows + // (viewHeight is a "recommended" value if isAuto) + scrollerHeight = this.computeScrollerHeight(viewHeight); + this.setGridHeight(scrollerHeight, isAuto); + // is the event limit dynamically calculated? + if (eventLimit && typeof eventLimit !== 'number') { + dayGrid.limitRows(eventLimit); // limit the levels after the grid's row heights have been set + } + if (!isAuto) { // should we force dimensions of the scroll container? + this.scroller.setHeight(scrollerHeight); + scrollbarWidths = this.scroller.getScrollbarWidths(); + if (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars? + if (headRowEl) { + core.compensateScroll(headRowEl, scrollbarWidths); + } + // doing the scrollbar compensation might have created text overflow which created more height. redo + scrollerHeight = this.computeScrollerHeight(viewHeight); + this.scroller.setHeight(scrollerHeight); + } + // guarantees the same scrollbar widths + this.scroller.lockOverflow(scrollbarWidths); + } + }; + // given a desired total height of the view, returns what the height of the scroller should be + DayGridView.prototype.computeScrollerHeight = function (viewHeight) { + return viewHeight - + core.subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller + }; + // Sets the height of just the DayGrid component in this view + DayGridView.prototype.setGridHeight = function (height, isAuto) { + if (this.opt('monthMode')) { + // if auto, make the height of each row the height that it would be if there were 6 weeks + if (isAuto) { + height *= this.dayGrid.rowCnt / 6; + } + core.distributeHeight(this.dayGrid.rowEls, height, !isAuto); // if auto, don't compensate for height-hogging rows + } + else { + if (isAuto) { + core.undistributeHeight(this.dayGrid.rowEls); // let the rows be their natural height with no expanding + } + else { + core.distributeHeight(this.dayGrid.rowEls, height, true); // true = compensate for height-hogging rows + } + } + }; + /* Scroll + ------------------------------------------------------------------------------------------------------------------*/ + DayGridView.prototype.computeDateScroll = function (duration) { + return { top: 0 }; + }; + DayGridView.prototype.queryDateScroll = function () { + return { top: this.scroller.getScrollTop() }; + }; + DayGridView.prototype.applyDateScroll = function (scroll) { + if (scroll.top !== undefined) { + this.scroller.setScrollTop(scroll.top); + } + }; + return DayGridView; + }(core.View)); + DayGridView.prototype.dateProfileGeneratorClass = DayGridDateProfileGenerator; + + var SimpleDayGrid = /** @class */ (function (_super) { + __extends(SimpleDayGrid, _super); + function SimpleDayGrid(context, dayGrid) { + var _this = _super.call(this, context, dayGrid.el) || this; + _this.slicer = new DayGridSlicer(); + _this.dayGrid = dayGrid; + context.calendar.registerInteractiveComponent(_this, { el: _this.dayGrid.el }); + return _this; + } + SimpleDayGrid.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.calendar.unregisterInteractiveComponent(this); + }; + SimpleDayGrid.prototype.render = function (props) { + var dayGrid = this.dayGrid; + var dateProfile = props.dateProfile, dayTable = props.dayTable; + dayGrid.receiveProps(__assign({}, this.slicer.sliceProps(props, dateProfile, props.nextDayThreshold, dayGrid, dayTable), { dateProfile: dateProfile, cells: dayTable.cells, isRigid: props.isRigid })); + }; + SimpleDayGrid.prototype.buildPositionCaches = function () { + this.dayGrid.buildPositionCaches(); + }; + SimpleDayGrid.prototype.queryHit = function (positionLeft, positionTop) { + var rawHit = this.dayGrid.positionToHit(positionLeft, positionTop); + if (rawHit) { + return { + component: this.dayGrid, + dateSpan: rawHit.dateSpan, + dayEl: rawHit.dayEl, + rect: { + left: rawHit.relativeRect.left, + right: rawHit.relativeRect.right, + top: rawHit.relativeRect.top, + bottom: rawHit.relativeRect.bottom + }, + layer: 0 + }; + } + }; + return SimpleDayGrid; + }(core.DateComponent)); + var DayGridSlicer = /** @class */ (function (_super) { + __extends(DayGridSlicer, _super); + function DayGridSlicer() { + return _super !== null && _super.apply(this, arguments) || this; + } + DayGridSlicer.prototype.sliceRange = function (dateRange, dayTable) { + return dayTable.sliceRange(dateRange); + }; + return DayGridSlicer; + }(core.Slicer)); + + var DayGridView$1 = /** @class */ (function (_super) { + __extends(DayGridView, _super); + function DayGridView(_context, viewSpec, dateProfileGenerator, parentEl) { + var _this = _super.call(this, _context, viewSpec, dateProfileGenerator, parentEl) || this; + _this.buildDayTable = core.memoize(buildDayTable); + if (_this.opt('columnHeader')) { + _this.header = new core.DayHeader(_this.context, _this.el.querySelector('.fc-head-container')); + } + _this.simpleDayGrid = new SimpleDayGrid(_this.context, _this.dayGrid); + return _this; + } + DayGridView.prototype.destroy = function () { + _super.prototype.destroy.call(this); + if (this.header) { + this.header.destroy(); + } + this.simpleDayGrid.destroy(); + }; + DayGridView.prototype.render = function (props) { + _super.prototype.render.call(this, props); + var dateProfile = this.props.dateProfile; + var dayTable = this.dayTable = + this.buildDayTable(dateProfile, this.dateProfileGenerator); + if (this.header) { + this.header.receiveProps({ + dateProfile: dateProfile, + dates: dayTable.headerDates, + datesRepDistinctDays: dayTable.rowCnt === 1, + renderIntroHtml: this.renderHeadIntroHtml + }); + } + this.simpleDayGrid.receiveProps({ + dateProfile: dateProfile, + dayTable: dayTable, + businessHours: props.businessHours, + dateSelection: props.dateSelection, + eventStore: props.eventStore, + eventUiBases: props.eventUiBases, + eventSelection: props.eventSelection, + eventDrag: props.eventDrag, + eventResize: props.eventResize, + isRigid: this.hasRigidRows(), + nextDayThreshold: this.nextDayThreshold + }); + }; + return DayGridView; + }(DayGridView)); + function buildDayTable(dateProfile, dateProfileGenerator) { + var daySeries = new core.DaySeries(dateProfile.renderRange, dateProfileGenerator); + return new core.DayTable(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit)); + } + + var main = core.createPlugin({ + defaultView: 'dayGridMonth', + views: { + dayGrid: DayGridView$1, + dayGridDay: { + type: 'dayGrid', + duration: { days: 1 } + }, + dayGridWeek: { + type: 'dayGrid', + duration: { weeks: 1 } + }, + dayGridMonth: { + type: 'dayGrid', + duration: { months: 1 }, + monthMode: true, + fixedWeekCount: true + } + } + }); + + exports.AbstractDayGridView = DayGridView; + exports.DayBgRow = DayBgRow; + exports.DayGrid = DayGrid; + exports.DayGridSlicer = DayGridSlicer; + exports.DayGridView = DayGridView$1; + exports.SimpleDayGrid = SimpleDayGrid; + exports.buildBasicDayTable = buildDayTable; + exports.default = main; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/daygrid/main.min.css b/AKPlan/static/AKPlan/fullcalendar/daygrid/main.min.css new file mode 100644 index 00000000..55a57241 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/daygrid/main.min.css @@ -0,0 +1 @@ +.fc-dayGridDay-view .fc-content-skeleton,.fc-dayGridWeek-view .fc-content-skeleton{padding-bottom:1em}.fc-dayGrid-view .fc-body .fc-row{min-height:4em}.fc-row.fc-rigid{overflow:hidden}.fc-row.fc-rigid .fc-content-skeleton{position:absolute;top:0;left:0;right:0}.fc-day-top.fc-other-month{opacity:.3}.fc-dayGrid-view .fc-day-number,.fc-dayGrid-view .fc-week-number{padding:2px}.fc-dayGrid-view th.fc-day-number,.fc-dayGrid-view th.fc-week-number{padding:0 2px}.fc-ltr .fc-dayGrid-view .fc-day-top .fc-day-number{float:right}.fc-rtl .fc-dayGrid-view .fc-day-top .fc-day-number{float:left}.fc-ltr .fc-dayGrid-view .fc-day-top .fc-week-number{float:left;border-radius:0 0 3px}.fc-rtl .fc-dayGrid-view .fc-day-top .fc-week-number{float:right;border-radius:0 0 0 3px}.fc-dayGrid-view .fc-day-top .fc-week-number{min-width:1.5em;text-align:center;background-color:#f2f2f2;color:grey}.fc-dayGrid-view td.fc-week-number{text-align:center}.fc-dayGrid-view td.fc-week-number>*{display:inline-block;min-width:1.25em} \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/daygrid/main.min.js b/AKPlan/static/AKPlan/fullcalendar/daygrid/main.min.js new file mode 100644 index 00000000..2f4c0d45 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/daygrid/main.min.js @@ -0,0 +1,6 @@ +/*! +FullCalendar Day Grid Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@fullcalendar/core")):"function"==typeof define&&define.amd?define(["exports","@fullcalendar/core"],t):t((e=e||self).FullCalendarDayGrid={},e.FullCalendar)}(this,function(e,t){"use strict";var r=function(e,t){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)};function n(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var i=function(){return(i=Object.assign||function(e){for(var t,r=1,n=arguments.length;r<n;r++)for(var i in t=arguments[r])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},o=function(e){function r(){return null!==e&&e.apply(this,arguments)||this}return n(r,e),r.prototype.buildRenderRange=function(r,n,i){var o,s=this.dateEnv,l=e.prototype.buildRenderRange.call(this,r,n,i),a=l.start,d=l.end;if(/^(year|month)$/.test(n)&&(a=s.startOfWeek(a),(o=s.startOfWeek(d)).valueOf()!==d.valueOf()&&(d=t.addWeeks(o,1))),this.options.monthMode&&this.options.fixedWeekCount){var c=Math.ceil(t.diffWeeks(a,d));d=t.addWeeks(d,6-c)}return{start:a,end:d}},r}(t.DateProfileGenerator),s=function(){function e(e){var t=this;this.isHidden=!0,this.margin=10,this.documentMousedown=function(e){t.el&&!t.el.contains(e.target)&&t.hide()},this.options=e}return e.prototype.show=function(){this.isHidden&&(this.el||this.render(),this.el.style.display="",this.position(),this.isHidden=!1,this.trigger("show"))},e.prototype.hide=function(){this.isHidden||(this.el.style.display="none",this.isHidden=!0,this.trigger("hide"))},e.prototype.render=function(){var e=this,r=this.options,n=this.el=t.createElement("div",{className:"fc-popover "+(r.className||""),style:{top:"0",left:"0"}});"function"==typeof r.content&&r.content(n),r.parentEl.appendChild(n),t.listenBySelector(n,"click",".fc-close",function(t){e.hide()}),r.autoHide&&document.addEventListener("mousedown",this.documentMousedown)},e.prototype.destroy=function(){this.hide(),this.el&&(t.removeElement(this.el),this.el=null),document.removeEventListener("mousedown",this.documentMousedown)},e.prototype.position=function(){var e,r,n=this.options,i=this.el,o=i.getBoundingClientRect(),s=t.computeRect(i.offsetParent),l=t.computeClippingRect(n.parentEl);e=n.top||0,r=void 0!==n.left?n.left:void 0!==n.right?n.right-o.width:0,e=Math.min(e,l.bottom-o.height-this.margin),e=Math.max(e,l.top+this.margin),r=Math.min(r,l.right-o.width-this.margin),r=Math.max(r,l.left+this.margin),t.applyStyle(i,{top:e-s.top,left:r-s.left})},e.prototype.trigger=function(e){this.options[e]&&this.options[e].apply(this,Array.prototype.slice.call(arguments,1))},e}(),l=function(e){function r(){return null!==e&&e.apply(this,arguments)||this}return n(r,e),r.prototype.renderSegHtml=function(e,r){var n,i,o=this.context,s=o.view,l=o.options,a=e.eventRange,d=a.def,c=a.ui,h=d.allDay,p=s.computeEventDraggable(d,c),u=h&&e.isStart&&s.computeEventStartResizable(d,c),f=h&&e.isEnd&&s.computeEventEndResizable(d,c),g=this.getSegClasses(e,p,u||f,r),m=t.cssToStr(this.getSkinCss(c)),y="";return g.unshift("fc-day-grid-event","fc-h-event"),e.isStart&&(n=this.getTimeText(a))&&(y='<span class="fc-time">'+t.htmlEscape(n)+"</span>"),i='<span class="fc-title">'+(t.htmlEscape(d.title||"")||" ")+"</span>",'<a class="'+g.join(" ")+'"'+(d.url?' href="'+t.htmlEscape(d.url)+'"':"")+(m?' style="'+m+'"':"")+'><div class="fc-content">'+("rtl"===l.dir?i+" "+y:y+" "+i)+"</div>"+(u?'<div class="fc-resizer fc-start-resizer"></div>':"")+(f?'<div class="fc-resizer fc-end-resizer"></div>':"")+"</a>"},r.prototype.computeEventTimeFormat=function(){return{hour:"numeric",minute:"2-digit",omitZeroMinute:!0,meridiem:"narrow"}},r.prototype.computeDisplayEventEnd=function(){return!1},r}(t.FgEventRenderer),a=function(e){function r(t){var r=e.call(this,t.context)||this;return r.dayGrid=t,r}return n(r,e),r.prototype.attachSegs=function(e,t){var r=this.rowStructs=this.renderSegRows(e);this.dayGrid.rowEls.forEach(function(e,t){e.querySelector(".fc-content-skeleton > table").appendChild(r[t].tbodyEl)}),t||this.dayGrid.removeSegPopover()},r.prototype.detachSegs=function(){for(var e,r=this.rowStructs||[];e=r.pop();)t.removeElement(e.tbodyEl);this.rowStructs=null},r.prototype.renderSegRows=function(e){var t,r,n=[];for(t=this.groupSegRows(e),r=0;r<t.length;r++)n.push(this.renderSegRow(r,t[r]));return n},r.prototype.renderSegRow=function(e,r){var n,i,o,s,l,a,d,c=this.dayGrid,h=c.colCnt,p=c.isRtl,u=this.buildSegLevels(r),f=Math.max(1,u.length),g=document.createElement("tbody"),m=[],y=[],v=[];function b(e){for(;o<e;)(d=(v[n-1]||[])[o])?d.rowSpan=(d.rowSpan||1)+1:(d=document.createElement("td"),s.appendChild(d)),y[n][o]=d,v[n][o]=d,o++}for(n=0;n<f;n++){if(i=u[n],o=0,s=document.createElement("tr"),m.push([]),y.push([]),v.push([]),i)for(l=0;l<i.length;l++){a=i[l];var w=p?h-1-a.lastCol:a.firstCol,S=p?h-1-a.firstCol:a.lastCol;for(b(w),d=t.createElement("td",{className:"fc-event-container"},a.el),w!==S?d.colSpan=S-w+1:v[n][o]=d;o<=S;)y[n][o]=d,m[n][o]=a,o++;s.appendChild(d)}b(h);var C=c.renderProps.renderIntroHtml();C&&(c.isRtl?t.appendToElement(s,C):t.prependToElement(s,C)),g.appendChild(s)}return{row:e,tbodyEl:g,cellMatrix:y,segMatrix:m,segLevels:u,segs:r}},r.prototype.buildSegLevels=function(e){var t,r,n,i=this.dayGrid,o=i.isRtl,s=i.colCnt,l=[];for(e=this.sortEventSegs(e),t=0;t<e.length;t++){for(r=e[t],n=0;n<l.length&&d(r,l[n]);n++);r.level=n,r.leftCol=o?s-1-r.lastCol:r.firstCol,r.rightCol=o?s-1-r.firstCol:r.lastCol,(l[n]||(l[n]=[])).push(r)}for(n=0;n<l.length;n++)l[n].sort(c);return l},r.prototype.groupSegRows=function(e){var t,r=[];for(t=0;t<this.dayGrid.rowCnt;t++)r.push([]);for(t=0;t<e.length;t++)r[e[t].row].push(e[t]);return r},r.prototype.computeDisplayEventEnd=function(){return 1===this.dayGrid.colCnt},r}(l);function d(e,t){var r,n;for(r=0;r<t.length;r++)if((n=t[r]).firstCol<=e.lastCol&&n.lastCol>=e.firstCol)return!0;return!1}function c(e,t){return e.leftCol-t.leftCol}var h=function(e){function r(){return null!==e&&e.apply(this,arguments)||this}return n(r,e),r.prototype.attachSegs=function(e,r){var n=r.sourceSeg,i=this.rowStructs=this.renderSegRows(e);this.dayGrid.rowEls.forEach(function(e,r){var o,s,l=t.htmlToElement('<div class="fc-mirror-skeleton"><table></table></div>');n&&n.row===r?o=n.el:(o=e.querySelector(".fc-content-skeleton tbody"))||(o=e.querySelector(".fc-content-skeleton table")),s=o.getBoundingClientRect().top-e.getBoundingClientRect().top,l.style.top=s+"px",l.querySelector("table").appendChild(i[r].tbodyEl),e.appendChild(l)})},r}(a),p=function(e){function r(t){var r=e.call(this,t.context)||this;return r.fillSegTag="td",r.dayGrid=t,r}return n(r,e),r.prototype.renderSegs=function(t,r){"bgEvent"===t&&(r=r.filter(function(e){return e.eventRange.def.allDay})),e.prototype.renderSegs.call(this,t,r)},r.prototype.attachSegs=function(e,t){var r,n,i,o=[];for(r=0;r<t.length;r++)n=t[r],i=this.renderFillRow(e,n),this.dayGrid.rowEls[n.row].appendChild(i),o.push(i);return o},r.prototype.renderFillRow=function(e,r){var n,i,o,s=this.dayGrid,l=s.colCnt,a=s.isRtl,d=a?l-1-r.lastCol:r.firstCol,c=(a?l-1-r.firstCol:r.lastCol)+1;n="businessHours"===e?"bgevent":e.toLowerCase(),o=(i=t.htmlToElement('<div class="fc-'+n+'-skeleton"><table><tr></tr></table></div>')).getElementsByTagName("tr")[0],d>0&&t.appendToElement(o,new Array(d+1).join('<td style="pointer-events:none"></td>')),r.el.colSpan=c-d,o.appendChild(r.el),c<l&&t.appendToElement(o,new Array(l-c+1).join('<td style="pointer-events:none"></td>'));var h=s.renderProps.renderIntroHtml();return h&&(s.isRtl?t.appendToElement(o,h):t.prependToElement(o,h)),i},r}(t.FillRenderer),u=function(e){function r(r,n){var i=e.call(this,r,n)||this,o=i.eventRenderer=new f(i),s=i.renderFrame=t.memoizeRendering(i._renderFrame);return i.renderFgEvents=t.memoizeRendering(o.renderSegs.bind(o),o.unrender.bind(o),[s]),i.renderEventSelection=t.memoizeRendering(o.selectByInstanceId.bind(o),o.unselectByInstanceId.bind(o),[i.renderFgEvents]),i.renderEventDrag=t.memoizeRendering(o.hideByHash.bind(o),o.showByHash.bind(o),[s]),i.renderEventResize=t.memoizeRendering(o.hideByHash.bind(o),o.showByHash.bind(o),[s]),r.calendar.registerInteractiveComponent(i,{el:i.el,useEventCenter:!1}),i}return n(r,e),r.prototype.render=function(e){this.renderFrame(e.date),this.renderFgEvents(e.fgSegs),this.renderEventSelection(e.eventSelection),this.renderEventDrag(e.eventDragInstances),this.renderEventResize(e.eventResizeInstances)},r.prototype.destroy=function(){e.prototype.destroy.call(this),this.renderFrame.unrender(),this.calendar.unregisterInteractiveComponent(this)},r.prototype._renderFrame=function(e){var r=this.theme,n=this.dateEnv.format(e,t.createFormatter(this.opt("dayPopoverFormat")));this.el.innerHTML='<div class="fc-header '+r.getClass("popoverHeader")+'"><span class="fc-title">'+t.htmlEscape(n)+'</span><span class="fc-close '+r.getIconClass("close")+'"></span></div><div class="fc-body '+r.getClass("popoverContent")+'"><div class="fc-event-container"></div></div>',this.segContainerEl=this.el.querySelector(".fc-event-container")},r.prototype.queryHit=function(e,r,n,i){var o=this.props.date;if(e<n&&r<i)return{component:this,dateSpan:{allDay:!0,range:{start:o,end:t.addDays(o,1)}},dayEl:this.el,rect:{left:0,top:0,right:n,bottom:i},layer:1}},r}(t.DateComponent),f=function(e){function r(t){var r=e.call(this,t.context)||this;return r.dayTile=t,r}return n(r,e),r.prototype.attachSegs=function(e){for(var t=0,r=e;t<r.length;t++){var n=r[t];this.dayTile.segContainerEl.appendChild(n.el)}},r.prototype.detachSegs=function(e){for(var r=0,n=e;r<n.length;r++){var i=n[r];t.removeElement(i.el)}},r}(l),g=function(){function e(e){this.context=e}return e.prototype.renderHtml=function(e){var t=[];e.renderIntroHtml&&t.push(e.renderIntroHtml());for(var r=0,n=e.cells;r<n.length;r++){var i=n[r];t.push(m(i.date,e.dateProfile,this.context,i.htmlAttrs))}return e.cells.length||t.push('<td class="fc-day '+this.context.theme.getClass("widgetContent")+'"></td>'),"rtl"===this.context.options.dir&&t.reverse(),"<tr>"+t.join("")+"</tr>"},e}();function m(e,r,n,i){var o=n.dateEnv,s=n.theme,l=t.rangeContainsMarker(r.activeRange,e),a=t.getDayClasses(e,r,n);return a.unshift("fc-day",s.getClass("widgetContent")),'<td class="'+a.join(" ")+'"'+(l?' data-date="'+o.formatIso(e,{omitTime:!0})+'"':"")+(i?" "+i:"")+"></td>"}var y=t.createFormatter({day:"numeric"}),v=t.createFormatter({week:"numeric"}),b=function(e){function r(r,n,i){var o=e.call(this,r,n)||this;o.bottomCoordPadding=0,o.isCellSizesDirty=!1;var s=o.eventRenderer=new a(o),l=o.fillRenderer=new p(o);o.mirrorRenderer=new h(o);var d=o.renderCells=t.memoizeRendering(o._renderCells,o._unrenderCells);return o.renderBusinessHours=t.memoizeRendering(l.renderSegs.bind(l,"businessHours"),l.unrender.bind(l,"businessHours"),[d]),o.renderDateSelection=t.memoizeRendering(l.renderSegs.bind(l,"highlight"),l.unrender.bind(l,"highlight"),[d]),o.renderBgEvents=t.memoizeRendering(l.renderSegs.bind(l,"bgEvent"),l.unrender.bind(l,"bgEvent"),[d]),o.renderFgEvents=t.memoizeRendering(s.renderSegs.bind(s),s.unrender.bind(s),[d]),o.renderEventSelection=t.memoizeRendering(s.selectByInstanceId.bind(s),s.unselectByInstanceId.bind(s),[o.renderFgEvents]),o.renderEventDrag=t.memoizeRendering(o._renderEventDrag,o._unrenderEventDrag,[d]),o.renderEventResize=t.memoizeRendering(o._renderEventResize,o._unrenderEventResize,[d]),o.renderProps=i,o}return n(r,e),r.prototype.render=function(e){var t=e.cells;this.rowCnt=t.length,this.colCnt=t[0].length,this.renderCells(t,e.isRigid),this.renderBusinessHours(e.businessHourSegs),this.renderDateSelection(e.dateSelectionSegs),this.renderBgEvents(e.bgEventSegs),this.renderFgEvents(e.fgEventSegs),this.renderEventSelection(e.eventSelection),this.renderEventDrag(e.eventDrag),this.renderEventResize(e.eventResize),this.segPopoverTile&&this.updateSegPopoverTile()},r.prototype.destroy=function(){e.prototype.destroy.call(this),this.renderCells.unrender()},r.prototype.getCellRange=function(e,r){var n=this.props.cells[e][r].date;return{start:n,end:t.addDays(n,1)}},r.prototype.updateSegPopoverTile=function(e,t){var r=this.props;this.segPopoverTile.receiveProps({date:e||this.segPopoverTile.props.date,fgSegs:t||this.segPopoverTile.props.fgSegs,eventSelection:r.eventSelection,eventDragInstances:r.eventDrag?r.eventDrag.affectedInstances:null,eventResizeInstances:r.eventResize?r.eventResize.affectedInstances:null})},r.prototype._renderCells=function(e,r){var n,i,o=this.view,s=this.dateEnv,l=this.rowCnt,a=this.colCnt,d="";for(n=0;n<l;n++)d+=this.renderDayRowHtml(n,r);for(this.el.innerHTML=d,this.rowEls=t.findElements(this.el,".fc-row"),this.cellEls=t.findElements(this.el,".fc-day, .fc-disabled-day"),this.isRtl&&this.cellEls.reverse(),this.rowPositions=new t.PositionCache(this.el,this.rowEls,!1,!0),this.colPositions=new t.PositionCache(this.el,this.cellEls.slice(0,a),!0,!1),n=0;n<l;n++)for(i=0;i<a;i++)this.publiclyTrigger("dayRender",[{date:s.toDate(e[n][i].date),el:this.getCellEl(n,i),view:o}]);this.isCellSizesDirty=!0},r.prototype._unrenderCells=function(){this.removeSegPopover()},r.prototype.renderDayRowHtml=function(e,t){var r=this.theme,n=["fc-row","fc-week",r.getClass("dayRow")];t&&n.push("fc-rigid");var i=new g(this.context);return'<div class="'+n.join(" ")+'"><div class="fc-bg"><table class="'+r.getClass("tableGrid")+'">'+i.renderHtml({cells:this.props.cells[e],dateProfile:this.props.dateProfile,renderIntroHtml:this.renderProps.renderBgIntroHtml})+'</table></div><div class="fc-content-skeleton"><table>'+(this.getIsNumbersVisible()?"<thead>"+this.renderNumberTrHtml(e)+"</thead>":"")+"</table></div></div>"},r.prototype.getIsNumbersVisible=function(){return this.getIsDayNumbersVisible()||this.renderProps.cellWeekNumbersVisible||this.renderProps.colWeekNumbersVisible},r.prototype.getIsDayNumbersVisible=function(){return this.rowCnt>1},r.prototype.renderNumberTrHtml=function(e){var t=this.renderProps.renderNumberIntroHtml(e,this);return"<tr>"+(this.isRtl?"":t)+this.renderNumberCellsHtml(e)+(this.isRtl?t:"")+"</tr>"},r.prototype.renderNumberCellsHtml=function(e){var t,r,n=[];for(t=0;t<this.colCnt;t++)r=this.props.cells[e][t].date,n.push(this.renderNumberCellHtml(r));return this.isRtl&&n.reverse(),n.join("")},r.prototype.renderNumberCellHtml=function(e){var r,n,i=this.view,o=this.dateEnv,s="",l=t.rangeContainsMarker(this.props.dateProfile.activeRange,e),a=this.getIsDayNumbersVisible()&&l;return a||this.renderProps.cellWeekNumbersVisible?((r=t.getDayClasses(e,this.props.dateProfile,this.context)).unshift("fc-day-top"),this.renderProps.cellWeekNumbersVisible&&(n=o.weekDow),s+='<td class="'+r.join(" ")+'"'+(l?' data-date="'+o.formatIso(e,{omitTime:!0})+'"':"")+">",this.renderProps.cellWeekNumbersVisible&&e.getUTCDay()===n&&(s+=t.buildGotoAnchorHtml(i,{date:e,type:"week"},{class:"fc-week-number"},o.format(e,v))),a&&(s+=t.buildGotoAnchorHtml(i,e,{class:"fc-day-number"},o.format(e,y))),s+="</td>"):"<td></td>"},r.prototype.updateSize=function(e){var t=this.fillRenderer,r=this.eventRenderer,n=this.mirrorRenderer;(e||this.isCellSizesDirty||this.view.calendar.isEventsUpdated)&&(this.buildPositionCaches(),this.isCellSizesDirty=!1),t.computeSizes(e),r.computeSizes(e),n.computeSizes(e),t.assignSizes(e),r.assignSizes(e),n.assignSizes(e)},r.prototype.buildPositionCaches=function(){this.buildColPositions(),this.buildRowPositions()},r.prototype.buildColPositions=function(){this.colPositions.build()},r.prototype.buildRowPositions=function(){this.rowPositions.build(),this.rowPositions.bottoms[this.rowCnt-1]+=this.bottomCoordPadding},r.prototype.positionToHit=function(e,t){var r=this.colPositions,n=this.rowPositions,i=r.leftToIndex(e),o=n.topToIndex(t);if(null!=o&&null!=i)return{row:o,col:i,dateSpan:{range:this.getCellRange(o,i),allDay:!0},dayEl:this.getCellEl(o,i),relativeRect:{left:r.lefts[i],right:r.rights[i],top:n.tops[o],bottom:n.bottoms[o]}}},r.prototype.getCellEl=function(e,t){return this.cellEls[e*this.colCnt+t]},r.prototype._renderEventDrag=function(e){e&&(this.eventRenderer.hideByHash(e.affectedInstances),this.fillRenderer.renderSegs("highlight",e.segs))},r.prototype._unrenderEventDrag=function(e){e&&(this.eventRenderer.showByHash(e.affectedInstances),this.fillRenderer.unrender("highlight"))},r.prototype._renderEventResize=function(e){e&&(this.eventRenderer.hideByHash(e.affectedInstances),this.fillRenderer.renderSegs("highlight",e.segs),this.mirrorRenderer.renderSegs(e.segs,{isResizing:!0,sourceSeg:e.sourceSeg}))},r.prototype._unrenderEventResize=function(e){e&&(this.eventRenderer.showByHash(e.affectedInstances),this.fillRenderer.unrender("highlight"),this.mirrorRenderer.unrender(e.segs,{isResizing:!0,sourceSeg:e.sourceSeg}))},r.prototype.removeSegPopover=function(){this.segPopover&&this.segPopover.hide()},r.prototype.limitRows=function(e){var t,r,n=this.eventRenderer.rowStructs||[];for(t=0;t<n.length;t++)this.unlimitRow(t),!1!==(r=!!e&&("number"==typeof e?e:this.computeRowLevelLimit(t)))&&this.limitRow(t,r)},r.prototype.computeRowLevelLimit=function(e){var r,n,i=this.rowEls[e].getBoundingClientRect().bottom,o=t.findChildren(this.eventRenderer.rowStructs[e].tbodyEl);for(r=0;r<o.length;r++)if((n=o[r]).classList.remove("fc-limited"),n.getBoundingClientRect().bottom>i)return r;return!1},r.prototype.limitRow=function(e,r){var n,i,o,s,l,a,d,c,h,p,u,f,g,m,y,v=this,b=this.colCnt,w=this.isRtl,S=this.eventRenderer.rowStructs[e],C=[],E=0,R=function(n){for(;E<n;)(a=v.getCellSegs(e,E,r)).length&&(h=i[r-1][E],y=v.renderMoreLink(e,E,a),m=t.createElement("div",null,y),h.appendChild(m),C.push(m)),E++};if(r&&r<S.segLevels.length){for(n=S.segLevels[r-1],i=S.cellMatrix,(o=t.findChildren(S.tbodyEl).slice(r)).forEach(function(e){e.classList.add("fc-limited")}),s=0;s<n.length;s++){l=n[s];var H=w?b-1-l.lastCol:l.firstCol,D=w?b-1-l.firstCol:l.lastCol;for(R(H),c=[],d=0;E<=D;)a=this.getCellSegs(e,E,r),c.push(a),d+=a.length,E++;if(d){for(p=(h=i[r-1][H]).rowSpan||1,u=[],f=0;f<c.length;f++)g=t.createElement("td",{className:"fc-more-cell",rowSpan:p}),a=c[f],y=this.renderMoreLink(e,H+f,[l].concat(a)),m=t.createElement("div",null,y),g.appendChild(m),u.push(g),C.push(g);h.classList.add("fc-limited"),t.insertAfterElement(h,u),o.push(h)}}R(this.colCnt),S.moreEls=C,S.limitedEls=o}},r.prototype.unlimitRow=function(e){var r=this.eventRenderer.rowStructs[e];r.moreEls&&(r.moreEls.forEach(t.removeElement),r.moreEls=null),r.limitedEls&&(r.limitedEls.forEach(function(e){e.classList.remove("fc-limited")}),r.limitedEls=null)},r.prototype.renderMoreLink=function(e,r,n){var i=this,o=this.view,s=this.dateEnv,l=t.createElement("a",{className:"fc-more"});return l.innerText=this.getMoreLinkText(n.length),l.addEventListener("click",function(t){var l=i.opt("eventLimitClick"),a=i.isRtl?i.colCnt-r-1:r,d=i.props.cells[e][a].date,c=t.currentTarget,h=i.getCellEl(e,r),p=i.getCellSegs(e,r),u=i.resliceDaySegs(p,d),f=i.resliceDaySegs(n,d);"function"==typeof l&&(l=i.publiclyTrigger("eventLimitClick",[{date:s.toDate(d),allDay:!0,dayEl:h,moreEl:c,segs:u,hiddenSegs:f,jsEvent:t,view:o}])),"popover"===l?i.showSegPopover(e,r,c,u):"string"==typeof l&&o.calendar.zoomTo(d,l)}),l},r.prototype.showSegPopover=function(e,r,n,i){var o,l,a=this,d=this.calendar,c=this.view,h=this.theme,p=this.isRtl?this.colCnt-r-1:r,f=n.parentNode;o=1===this.rowCnt?c.el:this.rowEls[e],l={className:"fc-more-popover "+h.getClass("popover"),parentEl:c.el,top:t.computeRect(o).top,autoHide:!0,content:function(t){a.segPopoverTile=new u(a.context,t),a.updateSegPopoverTile(a.props.cells[e][p].date,i)},hide:function(){a.segPopoverTile.destroy(),a.segPopoverTile=null,a.segPopover.destroy(),a.segPopover=null}},this.isRtl?l.right=t.computeRect(f).right+1:l.left=t.computeRect(f).left-1,this.segPopover=new s(l),this.segPopover.show(),d.releaseAfterSizingTriggers()},r.prototype.resliceDaySegs=function(e,r){for(var n=r,o={start:n,end:t.addDays(n,1)},s=[],l=0,a=e;l<a.length;l++){var d=a[l],c=d.eventRange,h=c.range,p=t.intersectRanges(h,o);p&&s.push(i({},d,{eventRange:{def:c.def,ui:i({},c.ui,{durationEditable:!1}),instance:c.instance,range:p},isStart:d.isStart&&p.start.valueOf()===h.start.valueOf(),isEnd:d.isEnd&&p.end.valueOf()===h.end.valueOf()}))}return s},r.prototype.getMoreLinkText=function(e){var t=this.opt("eventLimitText");return"function"==typeof t?t(e):"+"+e+" "+t},r.prototype.getCellSegs=function(e,t,r){for(var n,i=this.eventRenderer.rowStructs[e].segMatrix,o=r||0,s=[];o<i.length;)(n=i[o][t])&&s.push(n),o++;return s},r}(t.DateComponent),w=t.createFormatter({week:"numeric"}),S=function(e){function r(r,n,i,o){var s=e.call(this,r,n,i,o)||this;s.renderHeadIntroHtml=function(){var e=s.theme;return s.colWeekNumbersVisible?'<th class="fc-week-number '+e.getClass("widgetHeader")+'" '+s.weekNumberStyleAttr()+"><span>"+t.htmlEscape(s.opt("weekLabel"))+"</span></th>":""},s.renderDayGridNumberIntroHtml=function(e,r){var n=s.dateEnv,i=r.props.cells[e][0].date;return s.colWeekNumbersVisible?'<td class="fc-week-number" '+s.weekNumberStyleAttr()+">"+t.buildGotoAnchorHtml(s,{date:i,type:"week",forceOff:1===r.colCnt},n.format(i,w))+"</td>":""},s.renderDayGridBgIntroHtml=function(){var e=s.theme;return s.colWeekNumbersVisible?'<td class="fc-week-number '+e.getClass("widgetContent")+'" '+s.weekNumberStyleAttr()+"></td>":""},s.renderDayGridIntroHtml=function(){return s.colWeekNumbersVisible?'<td class="fc-week-number" '+s.weekNumberStyleAttr()+"></td>":""},s.el.classList.add("fc-dayGrid-view"),s.el.innerHTML=s.renderSkeletonHtml(),s.scroller=new t.ScrollComponent("hidden","auto");var l=s.scroller.el;s.el.querySelector(".fc-body > tr > td").appendChild(l),l.classList.add("fc-day-grid-container");var a,d=t.createElement("div",{className:"fc-day-grid"});return l.appendChild(d),s.opt("weekNumbers")?s.opt("weekNumbersWithinDays")?(a=!0,s.colWeekNumbersVisible=!1):(a=!1,s.colWeekNumbersVisible=!0):(s.colWeekNumbersVisible=!1,a=!1),s.dayGrid=new b(s.context,d,{renderNumberIntroHtml:s.renderDayGridNumberIntroHtml,renderBgIntroHtml:s.renderDayGridBgIntroHtml,renderIntroHtml:s.renderDayGridIntroHtml,colWeekNumbersVisible:s.colWeekNumbersVisible,cellWeekNumbersVisible:a}),s}return n(r,e),r.prototype.destroy=function(){e.prototype.destroy.call(this),this.dayGrid.destroy(),this.scroller.destroy()},r.prototype.renderSkeletonHtml=function(){var e=this.theme;return'<table class="'+e.getClass("tableGrid")+'">'+(this.opt("columnHeader")?'<thead class="fc-head"><tr><td class="fc-head-container '+e.getClass("widgetHeader")+'"> </td></tr></thead>':"")+'<tbody class="fc-body"><tr><td class="'+e.getClass("widgetContent")+'"></td></tr></tbody></table>'},r.prototype.weekNumberStyleAttr=function(){return null!=this.weekNumberWidth?'style="width:'+this.weekNumberWidth+'px"':""},r.prototype.hasRigidRows=function(){var e=this.opt("eventLimit");return e&&"number"!=typeof e},r.prototype.updateSize=function(t,r,n){e.prototype.updateSize.call(this,t,r,n),this.dayGrid.updateSize(t)},r.prototype.updateBaseSize=function(e,r,n){var i,o,s=this.dayGrid,l=this.opt("eventLimit"),a=this.header?this.header.el:null;s.rowEls?(this.colWeekNumbersVisible&&(this.weekNumberWidth=t.matchCellWidths(t.findElements(this.el,".fc-week-number"))),this.scroller.clear(),a&&t.uncompensateScroll(a),s.removeSegPopover(),l&&"number"==typeof l&&s.limitRows(l),i=this.computeScrollerHeight(r),this.setGridHeight(i,n),l&&"number"!=typeof l&&s.limitRows(l),n||(this.scroller.setHeight(i),((o=this.scroller.getScrollbarWidths()).left||o.right)&&(a&&t.compensateScroll(a,o),i=this.computeScrollerHeight(r),this.scroller.setHeight(i)),this.scroller.lockOverflow(o))):n||(i=this.computeScrollerHeight(r),this.scroller.setHeight(i))},r.prototype.computeScrollerHeight=function(e){return e-t.subtractInnerElHeight(this.el,this.scroller.el)},r.prototype.setGridHeight=function(e,r){this.opt("monthMode")?(r&&(e*=this.dayGrid.rowCnt/6),t.distributeHeight(this.dayGrid.rowEls,e,!r)):r?t.undistributeHeight(this.dayGrid.rowEls):t.distributeHeight(this.dayGrid.rowEls,e,!0)},r.prototype.computeDateScroll=function(e){return{top:0}},r.prototype.queryDateScroll=function(){return{top:this.scroller.getScrollTop()}},r.prototype.applyDateScroll=function(e){void 0!==e.top&&this.scroller.setScrollTop(e.top)},r}(t.View);S.prototype.dateProfileGeneratorClass=o;var C=function(e){function t(t,r){var n=e.call(this,t,r.el)||this;return n.slicer=new E,n.dayGrid=r,t.calendar.registerInteractiveComponent(n,{el:n.dayGrid.el}),n}return n(t,e),t.prototype.destroy=function(){e.prototype.destroy.call(this),this.calendar.unregisterInteractiveComponent(this)},t.prototype.render=function(e){var t=this.dayGrid,r=e.dateProfile,n=e.dayTable;t.receiveProps(i({},this.slicer.sliceProps(e,r,e.nextDayThreshold,t,n),{dateProfile:r,cells:n.cells,isRigid:e.isRigid}))},t.prototype.buildPositionCaches=function(){this.dayGrid.buildPositionCaches()},t.prototype.queryHit=function(e,t){var r=this.dayGrid.positionToHit(e,t);if(r)return{component:this.dayGrid,dateSpan:r.dateSpan,dayEl:r.dayEl,rect:{left:r.relativeRect.left,right:r.relativeRect.right,top:r.relativeRect.top,bottom:r.relativeRect.bottom},layer:0}},t}(t.DateComponent),E=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return n(t,e),t.prototype.sliceRange=function(e,t){return t.sliceRange(e)},t}(t.Slicer),R=function(e){function r(r,n,i,o){var s=e.call(this,r,n,i,o)||this;return s.buildDayTable=t.memoize(H),s.opt("columnHeader")&&(s.header=new t.DayHeader(s.context,s.el.querySelector(".fc-head-container"))),s.simpleDayGrid=new C(s.context,s.dayGrid),s}return n(r,e),r.prototype.destroy=function(){e.prototype.destroy.call(this),this.header&&this.header.destroy(),this.simpleDayGrid.destroy()},r.prototype.render=function(t){e.prototype.render.call(this,t);var r=this.props.dateProfile,n=this.dayTable=this.buildDayTable(r,this.dateProfileGenerator);this.header&&this.header.receiveProps({dateProfile:r,dates:n.headerDates,datesRepDistinctDays:1===n.rowCnt,renderIntroHtml:this.renderHeadIntroHtml}),this.simpleDayGrid.receiveProps({dateProfile:r,dayTable:n,businessHours:t.businessHours,dateSelection:t.dateSelection,eventStore:t.eventStore,eventUiBases:t.eventUiBases,eventSelection:t.eventSelection,eventDrag:t.eventDrag,eventResize:t.eventResize,isRigid:this.hasRigidRows(),nextDayThreshold:this.nextDayThreshold})},r}(S);function H(e,r){var n=new t.DaySeries(e.renderRange,r);return new t.DayTable(n,/year|month|week/.test(e.currentRangeUnit))}var D=t.createPlugin({defaultView:"dayGridMonth",views:{dayGrid:R,dayGridDay:{type:"dayGrid",duration:{days:1}},dayGridWeek:{type:"dayGrid",duration:{weeks:1}},dayGridMonth:{type:"dayGrid",duration:{months:1},monthMode:!0,fixedWeekCount:!0}}});e.AbstractDayGridView=S,e.DayBgRow=g,e.DayGrid=b,e.DayGridSlicer=E,e.DayGridView=R,e.SimpleDayGrid=C,e.buildBasicDayTable=H,e.default=D,Object.defineProperty(e,"__esModule",{value:!0})}); \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/daygrid/package.json b/AKPlan/static/AKPlan/fullcalendar/daygrid/package.json new file mode 100644 index 00000000..c6e16ce1 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/daygrid/package.json @@ -0,0 +1,33 @@ +{ + "name": "@fullcalendar/daygrid", + "version": "4.3.0", + "title": "FullCalendar Day Grid Plugin", + "description": "Display events on Month view or DayGrid view", + "keywords": [ + "calendar", + "event", + "full-sized" + ], + "homepage": "https://fullcalendar.io/", + "docs": "https://fullcalendar.io/docs/month-view", + "bugs": "https://fullcalendar.io/reporting-bugs", + "repository": { + "type": "git", + "url": "https://github.com/fullcalendar/fullcalendar.git", + "homepage": "https://github.com/fullcalendar/fullcalendar" + }, + "license": "MIT", + "author": { + "name": "Adam Shaw", + "email": "arshaw@arshaw.com", + "url": "http://arshaw.com/" + }, + "copyright": "2019 Adam Shaw", + "peerDependencies": { + "@fullcalendar/core": "~4.3.0" + }, + "main": "main.js", + "module": "main.esm.js", + "unpkg": "main.min.js", + "types": "main.d.ts" +} diff --git a/AKPlan/static/AKPlan/fullcalendar/google-calendar/LICENSE.txt b/AKPlan/static/AKPlan/fullcalendar/google-calendar/LICENSE.txt new file mode 100644 index 00000000..2149cfbe --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/google-calendar/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2019 Adam Shaw + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/AKPlan/static/AKPlan/fullcalendar/google-calendar/README.md b/AKPlan/static/AKPlan/fullcalendar/google-calendar/README.md new file mode 100644 index 00000000..a4d6c5cc --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/google-calendar/README.md @@ -0,0 +1,8 @@ + +# FullCalendar Google Calendar Plugin + +Fetch events from a public Google Calendar feed + +[View the docs »](https://fullcalendar.io/docs/google-calendar) + +This package was created from the [FullCalendar monorepo »](https://github.com/fullcalendar/fullcalendar) diff --git a/AKPlan/static/AKPlan/fullcalendar/google-calendar/main.d.ts b/AKPlan/static/AKPlan/fullcalendar/google-calendar/main.d.ts new file mode 100644 index 00000000..105a6c6d --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/google-calendar/main.d.ts @@ -0,0 +1,20 @@ +// Generated by dts-bundle v0.7.3-fork.1 +// Dependencies for this module: +// main.d.ts + +declare module '@fullcalendar/google-calendar' { + module '@fullcalendar/core' { + interface OptionsInput { + googleCalendarApiKey?: string; + } + } + module '@fullcalendar/core/structs/event-source' { + interface ExtendedEventSourceInput { + googleCalendarApiKey?: string; + googleCalendarId?: string; + } + } + const _default: import("@fullcalendar/core").PluginDef; + export default _default; +} + diff --git a/AKPlan/static/AKPlan/fullcalendar/google-calendar/main.esm.js b/AKPlan/static/AKPlan/fullcalendar/google-calendar/main.esm.js new file mode 100644 index 00000000..274fc5df --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/google-calendar/main.esm.js @@ -0,0 +1,162 @@ +/*! +FullCalendar Google Calendar Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +import { createPlugin, refineProps, requestJson, addDays } from '@fullcalendar/core'; + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ + +var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; + +// TODO: expose somehow +var API_BASE = 'https://www.googleapis.com/calendar/v3/calendars'; +var STANDARD_PROPS = { + url: String, + googleCalendarApiKey: String, + googleCalendarId: String, + data: null +}; +var eventSourceDef = { + parseMeta: function (raw) { + if (typeof raw === 'string') { + raw = { url: raw }; + } + if (typeof raw === 'object') { + var standardProps = refineProps(raw, STANDARD_PROPS); + if (!standardProps.googleCalendarId && standardProps.url) { + standardProps.googleCalendarId = parseGoogleCalendarId(standardProps.url); + } + delete standardProps.url; + if (standardProps.googleCalendarId) { + return standardProps; + } + } + return null; + }, + fetch: function (arg, onSuccess, onFailure) { + var calendar = arg.calendar; + var meta = arg.eventSource.meta; + var apiKey = meta.googleCalendarApiKey || calendar.opt('googleCalendarApiKey'); + if (!apiKey) { + onFailure({ + message: 'Specify a googleCalendarApiKey. See http://fullcalendar.io/docs/google_calendar/' + }); + } + else { + var url = buildUrl(meta); + var requestParams_1 = buildRequestParams(arg.range, apiKey, meta.data, calendar.dateEnv); + requestJson('GET', url, requestParams_1, function (body, xhr) { + if (body.error) { + onFailure({ + message: 'Google Calendar API: ' + body.error.message, + errors: body.error.errors, + xhr: xhr + }); + } + else { + onSuccess({ + rawEvents: gcalItemsToRawEventDefs(body.items, requestParams_1.timeZone), + xhr: xhr + }); + } + }, function (message, xhr) { + onFailure({ message: message, xhr: xhr }); + }); + } + } +}; +function parseGoogleCalendarId(url) { + var match; + // detect if the ID was specified as a single string. + // will match calendars like "asdf1234@calendar.google.com" in addition to person email calendars. + if (/^[^\/]+@([^\/\.]+\.)*(google|googlemail|gmail)\.com$/.test(url)) { + return url; + } + else if ((match = /^https:\/\/www.googleapis.com\/calendar\/v3\/calendars\/([^\/]*)/.exec(url)) || + (match = /^https?:\/\/www.google.com\/calendar\/feeds\/([^\/]*)/.exec(url))) { + return decodeURIComponent(match[1]); + } +} +function buildUrl(meta) { + return API_BASE + '/' + encodeURIComponent(meta.googleCalendarId) + '/events'; +} +function buildRequestParams(range, apiKey, extraParams, dateEnv) { + var params; + var startStr; + var endStr; + if (dateEnv.canComputeOffset) { + // strings will naturally have offsets, which GCal needs + startStr = dateEnv.formatIso(range.start); + endStr = dateEnv.formatIso(range.end); + } + else { + // when timezone isn't known, we don't know what the UTC offset should be, so ask for +/- 1 day + // from the UTC day-start to guarantee we're getting all the events + // (start/end will be UTC-coerced dates, so toISOString is okay) + startStr = addDays(range.start, -1).toISOString(); + endStr = addDays(range.end, 1).toISOString(); + } + params = __assign({}, (extraParams || {}), { key: apiKey, timeMin: startStr, timeMax: endStr, singleEvents: true, maxResults: 9999 }); + if (dateEnv.timeZone !== 'local') { + params.timeZone = dateEnv.timeZone; + } + return params; +} +function gcalItemsToRawEventDefs(items, gcalTimezone) { + return items.map(function (item) { + return gcalItemToRawEventDef(item, gcalTimezone); + }); +} +function gcalItemToRawEventDef(item, gcalTimezone) { + var url = item.htmlLink || null; + // make the URLs for each event show times in the correct timezone + if (url && gcalTimezone) { + url = injectQsComponent(url, 'ctz=' + gcalTimezone); + } + return { + id: item.id, + title: item.summary, + start: item.start.dateTime || item.start.date, + end: item.end.dateTime || item.end.date, + url: url, + location: item.location, + description: item.description + }; +} +// Injects a string like "arg=value" into the querystring of a URL +// TODO: move to a general util file? +function injectQsComponent(url, component) { + // inject it after the querystring but before the fragment + return url.replace(/(\?.*?)?(#|$)/, function (whole, qs, hash) { + return (qs ? qs + '&' : '?') + component + hash; + }); +} +var main = createPlugin({ + eventSourceDefs: [eventSourceDef] +}); + +export default main; diff --git a/AKPlan/static/AKPlan/fullcalendar/google-calendar/main.js b/AKPlan/static/AKPlan/fullcalendar/google-calendar/main.js new file mode 100644 index 00000000..fca85d45 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/google-calendar/main.js @@ -0,0 +1,170 @@ +/*! +FullCalendar Google Calendar Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) : + typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) : + (global = global || self, factory(global.FullCalendarGoogleCalendar = {}, global.FullCalendar)); +}(this, function (exports, core) { 'use strict'; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + + var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + // TODO: expose somehow + var API_BASE = 'https://www.googleapis.com/calendar/v3/calendars'; + var STANDARD_PROPS = { + url: String, + googleCalendarApiKey: String, + googleCalendarId: String, + data: null + }; + var eventSourceDef = { + parseMeta: function (raw) { + if (typeof raw === 'string') { + raw = { url: raw }; + } + if (typeof raw === 'object') { + var standardProps = core.refineProps(raw, STANDARD_PROPS); + if (!standardProps.googleCalendarId && standardProps.url) { + standardProps.googleCalendarId = parseGoogleCalendarId(standardProps.url); + } + delete standardProps.url; + if (standardProps.googleCalendarId) { + return standardProps; + } + } + return null; + }, + fetch: function (arg, onSuccess, onFailure) { + var calendar = arg.calendar; + var meta = arg.eventSource.meta; + var apiKey = meta.googleCalendarApiKey || calendar.opt('googleCalendarApiKey'); + if (!apiKey) { + onFailure({ + message: 'Specify a googleCalendarApiKey. See http://fullcalendar.io/docs/google_calendar/' + }); + } + else { + var url = buildUrl(meta); + var requestParams_1 = buildRequestParams(arg.range, apiKey, meta.data, calendar.dateEnv); + core.requestJson('GET', url, requestParams_1, function (body, xhr) { + if (body.error) { + onFailure({ + message: 'Google Calendar API: ' + body.error.message, + errors: body.error.errors, + xhr: xhr + }); + } + else { + onSuccess({ + rawEvents: gcalItemsToRawEventDefs(body.items, requestParams_1.timeZone), + xhr: xhr + }); + } + }, function (message, xhr) { + onFailure({ message: message, xhr: xhr }); + }); + } + } + }; + function parseGoogleCalendarId(url) { + var match; + // detect if the ID was specified as a single string. + // will match calendars like "asdf1234@calendar.google.com" in addition to person email calendars. + if (/^[^\/]+@([^\/\.]+\.)*(google|googlemail|gmail)\.com$/.test(url)) { + return url; + } + else if ((match = /^https:\/\/www.googleapis.com\/calendar\/v3\/calendars\/([^\/]*)/.exec(url)) || + (match = /^https?:\/\/www.google.com\/calendar\/feeds\/([^\/]*)/.exec(url))) { + return decodeURIComponent(match[1]); + } + } + function buildUrl(meta) { + return API_BASE + '/' + encodeURIComponent(meta.googleCalendarId) + '/events'; + } + function buildRequestParams(range, apiKey, extraParams, dateEnv) { + var params; + var startStr; + var endStr; + if (dateEnv.canComputeOffset) { + // strings will naturally have offsets, which GCal needs + startStr = dateEnv.formatIso(range.start); + endStr = dateEnv.formatIso(range.end); + } + else { + // when timezone isn't known, we don't know what the UTC offset should be, so ask for +/- 1 day + // from the UTC day-start to guarantee we're getting all the events + // (start/end will be UTC-coerced dates, so toISOString is okay) + startStr = core.addDays(range.start, -1).toISOString(); + endStr = core.addDays(range.end, 1).toISOString(); + } + params = __assign({}, (extraParams || {}), { key: apiKey, timeMin: startStr, timeMax: endStr, singleEvents: true, maxResults: 9999 }); + if (dateEnv.timeZone !== 'local') { + params.timeZone = dateEnv.timeZone; + } + return params; + } + function gcalItemsToRawEventDefs(items, gcalTimezone) { + return items.map(function (item) { + return gcalItemToRawEventDef(item, gcalTimezone); + }); + } + function gcalItemToRawEventDef(item, gcalTimezone) { + var url = item.htmlLink || null; + // make the URLs for each event show times in the correct timezone + if (url && gcalTimezone) { + url = injectQsComponent(url, 'ctz=' + gcalTimezone); + } + return { + id: item.id, + title: item.summary, + start: item.start.dateTime || item.start.date, + end: item.end.dateTime || item.end.date, + url: url, + location: item.location, + description: item.description + }; + } + // Injects a string like "arg=value" into the querystring of a URL + // TODO: move to a general util file? + function injectQsComponent(url, component) { + // inject it after the querystring but before the fragment + return url.replace(/(\?.*?)?(#|$)/, function (whole, qs, hash) { + return (qs ? qs + '&' : '?') + component + hash; + }); + } + var main = core.createPlugin({ + eventSourceDefs: [eventSourceDef] + }); + + exports.default = main; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/google-calendar/main.min.js b/AKPlan/static/AKPlan/fullcalendar/google-calendar/main.min.js new file mode 100644 index 00000000..e7626129 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/google-calendar/main.min.js @@ -0,0 +1,6 @@ +/*! +FullCalendar Google Calendar Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ +!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("@fullcalendar/core")):"function"==typeof define&&define.amd?define(["exports","@fullcalendar/core"],r):r((e=e||self).FullCalendarGoogleCalendar={},e.FullCalendar)}(this,function(e,r){"use strict";var t=function(){return(t=Object.assign||function(e){for(var r,t=1,n=arguments.length;t<n;t++)for(var o in r=arguments[t])Object.prototype.hasOwnProperty.call(r,o)&&(e[o]=r[o]);return e}).apply(this,arguments)},n="https://www.googleapis.com/calendar/v3/calendars",o={url:String,googleCalendarApiKey:String,googleCalendarId:String,data:null},a={parseMeta:function(e){if("string"==typeof e&&(e={url:e}),"object"==typeof e){var t=r.refineProps(e,o);if(!t.googleCalendarId&&t.url&&(t.googleCalendarId=function(e){var r;if(/^[^\/]+@([^\/\.]+\.)*(google|googlemail|gmail)\.com$/.test(e))return e;if((r=/^https:\/\/www.googleapis.com\/calendar\/v3\/calendars\/([^\/]*)/.exec(e))||(r=/^https?:\/\/www.google.com\/calendar\/feeds\/([^\/]*)/.exec(e)))return decodeURIComponent(r[1])}(t.url)),delete t.url,t.googleCalendarId)return t}return null},fetch:function(e,o,a){var l=e.calendar,i=e.eventSource.meta,d=i.googleCalendarApiKey||l.opt("googleCalendarApiKey");if(d){var s=function(e){return n+"/"+encodeURIComponent(e.googleCalendarId)+"/events"}(i),c=function(e,n,o,a){var l,i,d;a.canComputeOffset?(i=a.formatIso(e.start),d=a.formatIso(e.end)):(i=r.addDays(e.start,-1).toISOString(),d=r.addDays(e.end,1).toISOString());l=t({},o||{},{key:n,timeMin:i,timeMax:d,singleEvents:!0,maxResults:9999}),"local"!==a.timeZone&&(l.timeZone=a.timeZone);return l}(e.range,d,i.data,l.dateEnv);r.requestJson("GET",s,c,function(e,r){var t,n;e.error?a({message:"Google Calendar API: "+e.error.message,errors:e.error.errors,xhr:r}):o({rawEvents:(t=e.items,n=c.timeZone,t.map(function(e){return function(e,r){var t=e.htmlLink||null;t&&r&&(t=function(e,r){return e.replace(/(\?.*?)?(#|$)/,function(e,t,n){return(t?t+"&":"?")+r+n})}(t,"ctz="+r));return{id:e.id,title:e.summary,start:e.start.dateTime||e.start.date,end:e.end.dateTime||e.end.date,url:t,location:e.location,description:e.description}}(e,n)})),xhr:r})},function(e,r){a({message:e,xhr:r})})}else a({message:"Specify a googleCalendarApiKey. See http://fullcalendar.io/docs/google_calendar/"})}};var l=r.createPlugin({eventSourceDefs:[a]});e.default=l,Object.defineProperty(e,"__esModule",{value:!0})}); \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/google-calendar/package.json b/AKPlan/static/AKPlan/fullcalendar/google-calendar/package.json new file mode 100644 index 00000000..58b1dc6f --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/google-calendar/package.json @@ -0,0 +1,33 @@ +{ + "name": "@fullcalendar/google-calendar", + "version": "4.3.0", + "title": "FullCalendar Google Calendar Plugin", + "description": "Fetch events from a public Google Calendar feed", + "keywords": [ + "calendar", + "event", + "full-sized" + ], + "homepage": "https://fullcalendar.io/", + "docs": "https://fullcalendar.io/docs/google-calendar", + "bugs": "https://fullcalendar.io/reporting-bugs", + "repository": { + "type": "git", + "url": "https://github.com/fullcalendar/fullcalendar.git", + "homepage": "https://github.com/fullcalendar/fullcalendar" + }, + "license": "MIT", + "author": { + "name": "Adam Shaw", + "email": "arshaw@arshaw.com", + "url": "http://arshaw.com/" + }, + "copyright": "2019 Adam Shaw", + "peerDependencies": { + "@fullcalendar/core": "~4.3.0" + }, + "main": "main.js", + "module": "main.esm.js", + "unpkg": "main.min.js", + "types": "main.d.ts" +} diff --git a/AKPlan/static/AKPlan/fullcalendar/interaction/LICENSE.txt b/AKPlan/static/AKPlan/fullcalendar/interaction/LICENSE.txt new file mode 100644 index 00000000..2149cfbe --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/interaction/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2019 Adam Shaw + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/AKPlan/static/AKPlan/fullcalendar/interaction/README.md b/AKPlan/static/AKPlan/fullcalendar/interaction/README.md new file mode 100644 index 00000000..ee5c738a --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/interaction/README.md @@ -0,0 +1,8 @@ + +# FullCalendar Interaction Plugin + +Provides functionality for event drag-n-drop, resizing, dateClick, and selectable actions + +[View the docs »](https://fullcalendar.io/docs/editable) + +This package was created from the [FullCalendar monorepo »](https://github.com/fullcalendar/fullcalendar) diff --git a/AKPlan/static/AKPlan/fullcalendar/interaction/main.d.ts b/AKPlan/static/AKPlan/fullcalendar/interaction/main.d.ts new file mode 100644 index 00000000..b7398ba7 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/interaction/main.d.ts @@ -0,0 +1,323 @@ +// Generated by dts-bundle v0.7.3-fork.1 +// Dependencies for this module: +// ../../../../../@fullcalendar/core + +declare module '@fullcalendar/interaction' { + import FeaturefulElementDragging from '@fullcalendar/interaction/dnd/FeaturefulElementDragging'; + const _default: import("@fullcalendar/core").PluginDef; + export default _default; + export { FeaturefulElementDragging }; + export { default as PointerDragging } from '@fullcalendar/interaction/dnd/PointerDragging'; + export { default as Draggable } from '@fullcalendar/interaction/interactions-external/ExternalDraggable'; + export { default as ThirdPartyDraggable } from '@fullcalendar/interaction/interactions-external/ThirdPartyDraggable'; +} + +declare module '@fullcalendar/interaction/dnd/FeaturefulElementDragging' { + import { PointerDragEvent, ElementDragging } from '@fullcalendar/core'; + import PointerDragging from '@fullcalendar/interaction/dnd/PointerDragging'; + import ElementMirror from '@fullcalendar/interaction/dnd/ElementMirror'; + import AutoScroller from '@fullcalendar/interaction/dnd/AutoScroller'; + export { FeaturefulElementDragging as default, FeaturefulElementDragging }; + class FeaturefulElementDragging extends ElementDragging { + pointer: PointerDragging; + mirror: ElementMirror; + autoScroller: AutoScroller; + delay: number | null; + minDistance: number; + touchScrollAllowed: boolean; + mirrorNeedsRevert: boolean; + isInteracting: boolean; + isDragging: boolean; + isDelayEnded: boolean; + isDistanceSurpassed: boolean; + delayTimeoutId: number | null; + constructor(containerEl: HTMLElement); + destroy(): void; + onPointerDown: (ev: PointerDragEvent) => void; + onPointerMove: (ev: PointerDragEvent) => void; + onPointerUp: (ev: PointerDragEvent) => void; + startDelay(ev: PointerDragEvent): void; + handleDelayEnd(ev: PointerDragEvent): void; + handleDistanceSurpassed(ev: PointerDragEvent): void; + tryStartDrag(ev: PointerDragEvent): void; + tryStopDrag(ev: PointerDragEvent): void; + stopDrag(ev: PointerDragEvent): void; + setIgnoreMove(bool: boolean): void; + setMirrorIsVisible(bool: boolean): void; + setMirrorNeedsRevert(bool: boolean): void; + setAutoScrollEnabled(bool: boolean): void; + } +} + +declare module '@fullcalendar/interaction/dnd/PointerDragging' { + import { EmitterMixin, PointerDragEvent } from '@fullcalendar/core'; + export { PointerDragging as default, PointerDragging }; + class PointerDragging { + containerEl: EventTarget; + subjectEl: HTMLElement | null; + downEl: HTMLElement | null; + emitter: EmitterMixin; + selector: string; + handleSelector: string; + shouldIgnoreMove: boolean; + shouldWatchScroll: boolean; + isDragging: boolean; + isTouchDragging: boolean; + wasTouchScroll: boolean; + origPageX: number; + origPageY: number; + prevPageX: number; + prevPageY: number; + prevScrollX: number; + prevScrollY: number; + constructor(containerEl: EventTarget); + destroy(): void; + tryStart(ev: UIEvent): boolean; + cleanup(): void; + querySubjectEl(ev: UIEvent): HTMLElement; + handleMouseDown: (ev: MouseEvent) => void; + handleMouseMove: (ev: MouseEvent) => void; + handleMouseUp: (ev: MouseEvent) => void; + shouldIgnoreMouse(): number | boolean; + handleTouchStart: (ev: TouchEvent) => void; + handleTouchMove: (ev: TouchEvent) => void; + handleTouchEnd: (ev: TouchEvent) => void; + handleTouchScroll: () => void; + cancelTouchScroll(): void; + initScrollWatch(ev: PointerDragEvent): void; + recordCoords(ev: PointerDragEvent): void; + handleScroll: (ev: UIEvent) => void; + destroyScrollWatch(): void; + createEventFromMouse(ev: MouseEvent, isFirst?: boolean): PointerDragEvent; + createEventFromTouch(ev: TouchEvent, isFirst?: boolean): PointerDragEvent; + } +} + +declare module '@fullcalendar/interaction/interactions-external/ExternalDraggable' { + import { PointerDragEvent } from '@fullcalendar/core'; + import FeaturefulElementDragging from '@fullcalendar/interaction/dnd/FeaturefulElementDragging'; + import { DragMetaGenerator } from '@fullcalendar/interaction/interactions-external/ExternalElementDragging'; + export interface ExternalDraggableSettings { + eventData?: DragMetaGenerator; + itemSelector?: string; + minDistance?: number; + longPressDelay?: number; + appendTo?: HTMLElement; + } + export { ExternalDraggable as default, ExternalDraggable }; + class ExternalDraggable { + dragging: FeaturefulElementDragging; + settings: ExternalDraggableSettings; + constructor(el: HTMLElement, settings?: ExternalDraggableSettings); + handlePointerDown: (ev: PointerDragEvent) => void; + handleDragStart: (ev: PointerDragEvent) => void; + destroy(): void; + } +} + +declare module '@fullcalendar/interaction/interactions-external/ThirdPartyDraggable' { + import { DragMetaGenerator } from '@fullcalendar/interaction/interactions-external/ExternalElementDragging'; + import InferredElementDragging from '@fullcalendar/interaction/interactions-external/InferredElementDragging'; + export interface ThirdPartyDraggableSettings { + eventData?: DragMetaGenerator; + itemSelector?: string; + mirrorSelector?: string; + } + export { ThirdPartyDraggable as default, ThirdPartyDraggable }; + class ThirdPartyDraggable { + dragging: InferredElementDragging; + constructor(containerOrSettings?: EventTarget | ThirdPartyDraggableSettings, settings?: ThirdPartyDraggableSettings); + destroy(): void; + } +} + +declare module '@fullcalendar/interaction/dnd/ElementMirror' { + import { Rect } from '@fullcalendar/core'; + export { ElementMirror as default, ElementMirror }; + class ElementMirror { + isVisible: boolean; + origScreenX?: number; + origScreenY?: number; + deltaX?: number; + deltaY?: number; + sourceEl: HTMLElement | null; + mirrorEl: HTMLElement | null; + sourceElRect: Rect | null; + parentNode: HTMLElement; + zIndex: number; + revertDuration: number; + start(sourceEl: HTMLElement, pageX: number, pageY: number): void; + handleMove(pageX: number, pageY: number): void; + setIsVisible(bool: boolean): void; + stop(needsRevertAnimation: boolean, callback: () => void): void; + doRevertAnimation(callback: () => void, revertDuration: number): void; + cleanup(): void; + updateElPosition(): void; + getMirrorEl(): HTMLElement; + } +} + +declare module '@fullcalendar/interaction/dnd/AutoScroller' { + import { ScrollGeomCache } from '@fullcalendar/interaction/scroll-geom-cache'; + export { AutoScroller as default, AutoScroller }; + class AutoScroller { + isEnabled: boolean; + scrollQuery: (Window | string)[]; + edgeThreshold: number; + maxVelocity: number; + pointerScreenX: number | null; + pointerScreenY: number | null; + isAnimating: boolean; + scrollCaches: ScrollGeomCache[] | null; + msSinceRequest?: number; + everMovedUp: boolean; + everMovedDown: boolean; + everMovedLeft: boolean; + everMovedRight: boolean; + start(pageX: number, pageY: number): void; + handleMove(pageX: number, pageY: number): void; + stop(): void; + requestAnimation(now: number): void; + } +} + +declare module '@fullcalendar/interaction/interactions-external/ExternalElementDragging' { + import { Hit, PointerDragEvent, EventTuple, DatePointApi, Calendar, EventInteractionState, DragMetaInput, DragMeta, View, ElementDragging } from '@fullcalendar/core'; + import HitDragging from '@fullcalendar/interaction/interactions/HitDragging'; + export type DragMetaGenerator = DragMetaInput | ((el: HTMLElement) => DragMetaInput); + export interface ExternalDropApi extends DatePointApi { + draggedEl: HTMLElement; + jsEvent: UIEvent; + view: View; + } + export { ExternalElementDragging as default, ExternalElementDragging }; + class ExternalElementDragging { + hitDragging: HitDragging; + receivingCalendar: Calendar | null; + droppableEvent: EventTuple | null; + suppliedDragMeta: DragMetaGenerator | null; + dragMeta: DragMeta | null; + constructor(dragging: ElementDragging, suppliedDragMeta?: DragMetaGenerator); + handleDragStart: (ev: PointerDragEvent) => void; + buildDragMeta(subjectEl: HTMLElement): DragMeta; + handleHitUpdate: (hit: Hit, isFinal: boolean, ev: PointerDragEvent) => void; + handleDragEnd: (pev: PointerDragEvent) => void; + displayDrag(nextCalendar: Calendar | null, state: EventInteractionState): void; + clearDrag(): void; + canDropElOnCalendar(el: HTMLElement, receivingCalendar: Calendar): boolean; + } +} + +declare module '@fullcalendar/interaction/interactions-external/InferredElementDragging' { + import { PointerDragEvent, ElementDragging } from '@fullcalendar/core'; + import PointerDragging from '@fullcalendar/interaction/dnd/PointerDragging'; + export { InferredElementDragging as default, InferredElementDragging }; + class InferredElementDragging extends ElementDragging { + pointer: PointerDragging; + shouldIgnoreMove: boolean; + mirrorSelector: string; + currentMirrorEl: HTMLElement | null; + constructor(containerEl: HTMLElement); + destroy(): void; + handlePointerDown: (ev: PointerDragEvent) => void; + handlePointerMove: (ev: PointerDragEvent) => void; + handlePointerUp: (ev: PointerDragEvent) => void; + setIgnoreMove(bool: boolean): void; + setMirrorIsVisible(bool: boolean): void; + } +} + +declare module '@fullcalendar/interaction/scroll-geom-cache' { + import { Rect, ScrollController } from '@fullcalendar/core'; + export abstract class ScrollGeomCache extends ScrollController { + clientRect: Rect; + origScrollTop: number; + origScrollLeft: number; + protected scrollController: ScrollController; + protected doesListening: boolean; + protected scrollTop: number; + protected scrollLeft: number; + protected scrollWidth: number; + protected scrollHeight: number; + protected clientWidth: number; + protected clientHeight: number; + constructor(scrollController: ScrollController, doesListening: boolean); + abstract getEventTarget(): EventTarget; + abstract computeClientRect(): Rect; + destroy(): void; + handleScroll: () => void; + getScrollTop(): number; + getScrollLeft(): number; + setScrollTop(top: number): void; + setScrollLeft(top: number): void; + getClientWidth(): number; + getClientHeight(): number; + getScrollWidth(): number; + getScrollHeight(): number; + handleScrollChange(): void; + } + export class ElementScrollGeomCache extends ScrollGeomCache { + constructor(el: HTMLElement, doesListening: boolean); + getEventTarget(): EventTarget; + computeClientRect(): { + left: number; + right: number; + top: number; + bottom: number; + }; + } + export class WindowScrollGeomCache extends ScrollGeomCache { + constructor(doesListening: boolean); + getEventTarget(): EventTarget; + computeClientRect(): Rect; + handleScrollChange(): void; + } +} + +declare module '@fullcalendar/interaction/interactions/HitDragging' { + import { EmitterMixin, PointerDragEvent, Point, Hit, InteractionSettingsStore, ElementDragging } from '@fullcalendar/core'; + import OffsetTracker from '@fullcalendar/interaction/OffsetTracker'; + export { HitDragging as default, HitDragging }; + class HitDragging { + droppableStore: InteractionSettingsStore; + dragging: ElementDragging; + emitter: EmitterMixin; + useSubjectCenter: boolean; + requireInitial: boolean; + offsetTrackers: { + [componentUid: string]: OffsetTracker; + }; + initialHit: Hit | null; + movingHit: Hit | null; + finalHit: Hit | null; + coordAdjust?: Point; + constructor(dragging: ElementDragging, droppableStore: InteractionSettingsStore); + handlePointerDown: (ev: PointerDragEvent) => void; + processFirstCoord(ev: PointerDragEvent): void; + handleDragStart: (ev: PointerDragEvent) => void; + handleDragMove: (ev: PointerDragEvent) => void; + handlePointerUp: (ev: PointerDragEvent) => void; + handleDragEnd: (ev: PointerDragEvent) => void; + handleMove(ev: PointerDragEvent, forceHandle?: boolean): void; + prepareHits(): void; + releaseHits(): void; + queryHitForOffset(offsetLeft: number, offsetTop: number): Hit | null; + } + export function isHitsEqual(hit0: Hit | null, hit1: Hit | null): boolean; +} + +declare module '@fullcalendar/interaction/OffsetTracker' { + import { Rect } from '@fullcalendar/core'; + import { ElementScrollGeomCache } from '@fullcalendar/interaction/scroll-geom-cache'; + export { OffsetTracker as default, OffsetTracker }; + class OffsetTracker { + scrollCaches: ElementScrollGeomCache[]; + origRect: Rect; + constructor(el: HTMLElement); + destroy(): void; + computeLeft(): number; + computeTop(): number; + isWithinClipping(pageX: number, pageY: number): boolean; + } +} + diff --git a/AKPlan/static/AKPlan/fullcalendar/interaction/main.esm.js b/AKPlan/static/AKPlan/fullcalendar/interaction/main.esm.js new file mode 100644 index 00000000..13f834e7 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/interaction/main.esm.js @@ -0,0 +1,2132 @@ +/*! +FullCalendar Interaction Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +import { config, elementClosest, EmitterMixin, applyStyle, whenTransitionDone, removeElement, ScrollController, ElementScrollController, computeInnerRect, WindowScrollController, preventSelection, preventContextMenu, allowSelection, allowContextMenu, ElementDragging, computeRect, getClippingParents, pointInsideRect, isDateSpansEqual, constrainPoint, intersectRects, getRectCenter, diffPoints, mapHash, rangeContainsRange, interactionSettingsToStore, Interaction, enableCursor, disableCursor, compareNumbers, getElSeg, getRelevantEvents, EventApi, createEmptyEventStore, applyMutationToEventStore, interactionSettingsStore, startOfDay, diffDates, createDuration, eventTupleToStore, isInteractionValid, parseDragMeta, elementMatches, parseEventDef, createEventInstance, globalDefaults, createPlugin } from '@fullcalendar/core'; + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} + +var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; + +config.touchMouseIgnoreWait = 500; +var ignoreMouseDepth = 0; +var listenerCnt = 0; +var isWindowTouchMoveCancelled = false; +/* +Uses a "pointer" abstraction, which monitors UI events for both mouse and touch. +Tracks when the pointer "drags" on a certain element, meaning down+move+up. + +Also, tracks if there was touch-scrolling. +Also, can prevent touch-scrolling from happening. +Also, can fire pointermove events when scrolling happens underneath, even when no real pointer movement. + +emits: +- pointerdown +- pointermove +- pointerup +*/ +var PointerDragging = /** @class */ (function () { + function PointerDragging(containerEl) { + var _this = this; + this.subjectEl = null; + this.downEl = null; + // options that can be directly assigned by caller + this.selector = ''; // will cause subjectEl in all emitted events to be this element + this.handleSelector = ''; + this.shouldIgnoreMove = false; + this.shouldWatchScroll = true; // for simulating pointermove on scroll + // internal states + this.isDragging = false; + this.isTouchDragging = false; + this.wasTouchScroll = false; + // Mouse + // ---------------------------------------------------------------------------------------------------- + this.handleMouseDown = function (ev) { + if (!_this.shouldIgnoreMouse() && + isPrimaryMouseButton(ev) && + _this.tryStart(ev)) { + var pev = _this.createEventFromMouse(ev, true); + _this.emitter.trigger('pointerdown', pev); + _this.initScrollWatch(pev); + if (!_this.shouldIgnoreMove) { + document.addEventListener('mousemove', _this.handleMouseMove); + } + document.addEventListener('mouseup', _this.handleMouseUp); + } + }; + this.handleMouseMove = function (ev) { + var pev = _this.createEventFromMouse(ev); + _this.recordCoords(pev); + _this.emitter.trigger('pointermove', pev); + }; + this.handleMouseUp = function (ev) { + document.removeEventListener('mousemove', _this.handleMouseMove); + document.removeEventListener('mouseup', _this.handleMouseUp); + _this.emitter.trigger('pointerup', _this.createEventFromMouse(ev)); + _this.cleanup(); // call last so that pointerup has access to props + }; + // Touch + // ---------------------------------------------------------------------------------------------------- + this.handleTouchStart = function (ev) { + if (_this.tryStart(ev)) { + _this.isTouchDragging = true; + var pev = _this.createEventFromTouch(ev, true); + _this.emitter.trigger('pointerdown', pev); + _this.initScrollWatch(pev); + // unlike mouse, need to attach to target, not document + // https://stackoverflow.com/a/45760014 + var target = ev.target; + if (!_this.shouldIgnoreMove) { + target.addEventListener('touchmove', _this.handleTouchMove); + } + target.addEventListener('touchend', _this.handleTouchEnd); + target.addEventListener('touchcancel', _this.handleTouchEnd); // treat it as a touch end + // attach a handler to get called when ANY scroll action happens on the page. + // this was impossible to do with normal on/off because 'scroll' doesn't bubble. + // http://stackoverflow.com/a/32954565/96342 + window.addEventListener('scroll', _this.handleTouchScroll, true // useCapture + ); + } + }; + this.handleTouchMove = function (ev) { + var pev = _this.createEventFromTouch(ev); + _this.recordCoords(pev); + _this.emitter.trigger('pointermove', pev); + }; + this.handleTouchEnd = function (ev) { + if (_this.isDragging) { // done to guard against touchend followed by touchcancel + var target = ev.target; + target.removeEventListener('touchmove', _this.handleTouchMove); + target.removeEventListener('touchend', _this.handleTouchEnd); + target.removeEventListener('touchcancel', _this.handleTouchEnd); + window.removeEventListener('scroll', _this.handleTouchScroll, true); // useCaptured=true + _this.emitter.trigger('pointerup', _this.createEventFromTouch(ev)); + _this.cleanup(); // call last so that pointerup has access to props + _this.isTouchDragging = false; + startIgnoringMouse(); + } + }; + this.handleTouchScroll = function () { + _this.wasTouchScroll = true; + }; + this.handleScroll = function (ev) { + if (!_this.shouldIgnoreMove) { + var pageX = (window.pageXOffset - _this.prevScrollX) + _this.prevPageX; + var pageY = (window.pageYOffset - _this.prevScrollY) + _this.prevPageY; + _this.emitter.trigger('pointermove', { + origEvent: ev, + isTouch: _this.isTouchDragging, + subjectEl: _this.subjectEl, + pageX: pageX, + pageY: pageY, + deltaX: pageX - _this.origPageX, + deltaY: pageY - _this.origPageY + }); + } + }; + this.containerEl = containerEl; + this.emitter = new EmitterMixin(); + containerEl.addEventListener('mousedown', this.handleMouseDown); + containerEl.addEventListener('touchstart', this.handleTouchStart, { passive: true }); + listenerCreated(); + } + PointerDragging.prototype.destroy = function () { + this.containerEl.removeEventListener('mousedown', this.handleMouseDown); + this.containerEl.removeEventListener('touchstart', this.handleTouchStart, { passive: true }); + listenerDestroyed(); + }; + PointerDragging.prototype.tryStart = function (ev) { + var subjectEl = this.querySubjectEl(ev); + var downEl = ev.target; + if (subjectEl && + (!this.handleSelector || elementClosest(downEl, this.handleSelector))) { + this.subjectEl = subjectEl; + this.downEl = downEl; + this.isDragging = true; // do this first so cancelTouchScroll will work + this.wasTouchScroll = false; + return true; + } + return false; + }; + PointerDragging.prototype.cleanup = function () { + isWindowTouchMoveCancelled = false; + this.isDragging = false; + this.subjectEl = null; + this.downEl = null; + // keep wasTouchScroll around for later access + this.destroyScrollWatch(); + }; + PointerDragging.prototype.querySubjectEl = function (ev) { + if (this.selector) { + return elementClosest(ev.target, this.selector); + } + else { + return this.containerEl; + } + }; + PointerDragging.prototype.shouldIgnoreMouse = function () { + return ignoreMouseDepth || this.isTouchDragging; + }; + // can be called by user of this class, to cancel touch-based scrolling for the current drag + PointerDragging.prototype.cancelTouchScroll = function () { + if (this.isDragging) { + isWindowTouchMoveCancelled = true; + } + }; + // Scrolling that simulates pointermoves + // ---------------------------------------------------------------------------------------------------- + PointerDragging.prototype.initScrollWatch = function (ev) { + if (this.shouldWatchScroll) { + this.recordCoords(ev); + window.addEventListener('scroll', this.handleScroll, true); // useCapture=true + } + }; + PointerDragging.prototype.recordCoords = function (ev) { + if (this.shouldWatchScroll) { + this.prevPageX = ev.pageX; + this.prevPageY = ev.pageY; + this.prevScrollX = window.pageXOffset; + this.prevScrollY = window.pageYOffset; + } + }; + PointerDragging.prototype.destroyScrollWatch = function () { + if (this.shouldWatchScroll) { + window.removeEventListener('scroll', this.handleScroll, true); // useCaptured=true + } + }; + // Event Normalization + // ---------------------------------------------------------------------------------------------------- + PointerDragging.prototype.createEventFromMouse = function (ev, isFirst) { + var deltaX = 0; + var deltaY = 0; + // TODO: repeat code + if (isFirst) { + this.origPageX = ev.pageX; + this.origPageY = ev.pageY; + } + else { + deltaX = ev.pageX - this.origPageX; + deltaY = ev.pageY - this.origPageY; + } + return { + origEvent: ev, + isTouch: false, + subjectEl: this.subjectEl, + pageX: ev.pageX, + pageY: ev.pageY, + deltaX: deltaX, + deltaY: deltaY + }; + }; + PointerDragging.prototype.createEventFromTouch = function (ev, isFirst) { + var touches = ev.touches; + var pageX; + var pageY; + var deltaX = 0; + var deltaY = 0; + // if touch coords available, prefer, + // because FF would give bad ev.pageX ev.pageY + if (touches && touches.length) { + pageX = touches[0].pageX; + pageY = touches[0].pageY; + } + else { + pageX = ev.pageX; + pageY = ev.pageY; + } + // TODO: repeat code + if (isFirst) { + this.origPageX = pageX; + this.origPageY = pageY; + } + else { + deltaX = pageX - this.origPageX; + deltaY = pageY - this.origPageY; + } + return { + origEvent: ev, + isTouch: true, + subjectEl: this.subjectEl, + pageX: pageX, + pageY: pageY, + deltaX: deltaX, + deltaY: deltaY + }; + }; + return PointerDragging; +}()); +// Returns a boolean whether this was a left mouse click and no ctrl key (which means right click on Mac) +function isPrimaryMouseButton(ev) { + return ev.button === 0 && !ev.ctrlKey; +} +// Ignoring fake mouse events generated by touch +// ---------------------------------------------------------------------------------------------------- +function startIgnoringMouse() { + ignoreMouseDepth++; + setTimeout(function () { + ignoreMouseDepth--; + }, config.touchMouseIgnoreWait); +} +// We want to attach touchmove as early as possible for Safari +// ---------------------------------------------------------------------------------------------------- +function listenerCreated() { + if (!(listenerCnt++)) { + window.addEventListener('touchmove', onWindowTouchMove, { passive: false }); + } +} +function listenerDestroyed() { + if (!(--listenerCnt)) { + window.removeEventListener('touchmove', onWindowTouchMove, { passive: false }); + } +} +function onWindowTouchMove(ev) { + if (isWindowTouchMoveCancelled) { + ev.preventDefault(); + } +} + +/* +An effect in which an element follows the movement of a pointer across the screen. +The moving element is a clone of some other element. +Must call start + handleMove + stop. +*/ +var ElementMirror = /** @class */ (function () { + function ElementMirror() { + this.isVisible = false; // must be explicitly enabled + this.sourceEl = null; + this.mirrorEl = null; + this.sourceElRect = null; // screen coords relative to viewport + // options that can be set directly by caller + this.parentNode = document.body; + this.zIndex = 9999; + this.revertDuration = 0; + } + ElementMirror.prototype.start = function (sourceEl, pageX, pageY) { + this.sourceEl = sourceEl; + this.sourceElRect = this.sourceEl.getBoundingClientRect(); + this.origScreenX = pageX - window.pageXOffset; + this.origScreenY = pageY - window.pageYOffset; + this.deltaX = 0; + this.deltaY = 0; + this.updateElPosition(); + }; + ElementMirror.prototype.handleMove = function (pageX, pageY) { + this.deltaX = (pageX - window.pageXOffset) - this.origScreenX; + this.deltaY = (pageY - window.pageYOffset) - this.origScreenY; + this.updateElPosition(); + }; + // can be called before start + ElementMirror.prototype.setIsVisible = function (bool) { + if (bool) { + if (!this.isVisible) { + if (this.mirrorEl) { + this.mirrorEl.style.display = ''; + } + this.isVisible = bool; // needs to happen before updateElPosition + this.updateElPosition(); // because was not updating the position while invisible + } + } + else { + if (this.isVisible) { + if (this.mirrorEl) { + this.mirrorEl.style.display = 'none'; + } + this.isVisible = bool; + } + } + }; + // always async + ElementMirror.prototype.stop = function (needsRevertAnimation, callback) { + var _this = this; + var done = function () { + _this.cleanup(); + callback(); + }; + if (needsRevertAnimation && + this.mirrorEl && + this.isVisible && + this.revertDuration && // if 0, transition won't work + (this.deltaX || this.deltaY) // if same coords, transition won't work + ) { + this.doRevertAnimation(done, this.revertDuration); + } + else { + setTimeout(done, 0); + } + }; + ElementMirror.prototype.doRevertAnimation = function (callback, revertDuration) { + var mirrorEl = this.mirrorEl; + var finalSourceElRect = this.sourceEl.getBoundingClientRect(); // because autoscrolling might have happened + mirrorEl.style.transition = + 'top ' + revertDuration + 'ms,' + + 'left ' + revertDuration + 'ms'; + applyStyle(mirrorEl, { + left: finalSourceElRect.left, + top: finalSourceElRect.top + }); + whenTransitionDone(mirrorEl, function () { + mirrorEl.style.transition = ''; + callback(); + }); + }; + ElementMirror.prototype.cleanup = function () { + if (this.mirrorEl) { + removeElement(this.mirrorEl); + this.mirrorEl = null; + } + this.sourceEl = null; + }; + ElementMirror.prototype.updateElPosition = function () { + if (this.sourceEl && this.isVisible) { + applyStyle(this.getMirrorEl(), { + left: this.sourceElRect.left + this.deltaX, + top: this.sourceElRect.top + this.deltaY + }); + } + }; + ElementMirror.prototype.getMirrorEl = function () { + var sourceElRect = this.sourceElRect; + var mirrorEl = this.mirrorEl; + if (!mirrorEl) { + mirrorEl = this.mirrorEl = this.sourceEl.cloneNode(true); // cloneChildren=true + // we don't want long taps or any mouse interaction causing selection/menus. + // would use preventSelection(), but that prevents selectstart, causing problems. + mirrorEl.classList.add('fc-unselectable'); + mirrorEl.classList.add('fc-dragging'); + applyStyle(mirrorEl, { + position: 'fixed', + zIndex: this.zIndex, + visibility: '', + boxSizing: 'border-box', + width: sourceElRect.right - sourceElRect.left, + height: sourceElRect.bottom - sourceElRect.top, + right: 'auto', + bottom: 'auto', + margin: 0 + }); + this.parentNode.appendChild(mirrorEl); + } + return mirrorEl; + }; + return ElementMirror; +}()); + +/* +Is a cache for a given element's scroll information (all the info that ScrollController stores) +in addition the "client rectangle" of the element.. the area within the scrollbars. + +The cache can be in one of two modes: +- doesListening:false - ignores when the container is scrolled by someone else +- doesListening:true - watch for scrolling and update the cache +*/ +var ScrollGeomCache = /** @class */ (function (_super) { + __extends(ScrollGeomCache, _super); + function ScrollGeomCache(scrollController, doesListening) { + var _this = _super.call(this) || this; + _this.handleScroll = function () { + _this.scrollTop = _this.scrollController.getScrollTop(); + _this.scrollLeft = _this.scrollController.getScrollLeft(); + _this.handleScrollChange(); + }; + _this.scrollController = scrollController; + _this.doesListening = doesListening; + _this.scrollTop = _this.origScrollTop = scrollController.getScrollTop(); + _this.scrollLeft = _this.origScrollLeft = scrollController.getScrollLeft(); + _this.scrollWidth = scrollController.getScrollWidth(); + _this.scrollHeight = scrollController.getScrollHeight(); + _this.clientWidth = scrollController.getClientWidth(); + _this.clientHeight = scrollController.getClientHeight(); + _this.clientRect = _this.computeClientRect(); // do last in case it needs cached values + if (_this.doesListening) { + _this.getEventTarget().addEventListener('scroll', _this.handleScroll); + } + return _this; + } + ScrollGeomCache.prototype.destroy = function () { + if (this.doesListening) { + this.getEventTarget().removeEventListener('scroll', this.handleScroll); + } + }; + ScrollGeomCache.prototype.getScrollTop = function () { + return this.scrollTop; + }; + ScrollGeomCache.prototype.getScrollLeft = function () { + return this.scrollLeft; + }; + ScrollGeomCache.prototype.setScrollTop = function (top) { + this.scrollController.setScrollTop(top); + if (!this.doesListening) { + // we are not relying on the element to normalize out-of-bounds scroll values + // so we need to sanitize ourselves + this.scrollTop = Math.max(Math.min(top, this.getMaxScrollTop()), 0); + this.handleScrollChange(); + } + }; + ScrollGeomCache.prototype.setScrollLeft = function (top) { + this.scrollController.setScrollLeft(top); + if (!this.doesListening) { + // we are not relying on the element to normalize out-of-bounds scroll values + // so we need to sanitize ourselves + this.scrollLeft = Math.max(Math.min(top, this.getMaxScrollLeft()), 0); + this.handleScrollChange(); + } + }; + ScrollGeomCache.prototype.getClientWidth = function () { + return this.clientWidth; + }; + ScrollGeomCache.prototype.getClientHeight = function () { + return this.clientHeight; + }; + ScrollGeomCache.prototype.getScrollWidth = function () { + return this.scrollWidth; + }; + ScrollGeomCache.prototype.getScrollHeight = function () { + return this.scrollHeight; + }; + ScrollGeomCache.prototype.handleScrollChange = function () { + }; + return ScrollGeomCache; +}(ScrollController)); +var ElementScrollGeomCache = /** @class */ (function (_super) { + __extends(ElementScrollGeomCache, _super); + function ElementScrollGeomCache(el, doesListening) { + return _super.call(this, new ElementScrollController(el), doesListening) || this; + } + ElementScrollGeomCache.prototype.getEventTarget = function () { + return this.scrollController.el; + }; + ElementScrollGeomCache.prototype.computeClientRect = function () { + return computeInnerRect(this.scrollController.el); + }; + return ElementScrollGeomCache; +}(ScrollGeomCache)); +var WindowScrollGeomCache = /** @class */ (function (_super) { + __extends(WindowScrollGeomCache, _super); + function WindowScrollGeomCache(doesListening) { + return _super.call(this, new WindowScrollController(), doesListening) || this; + } + WindowScrollGeomCache.prototype.getEventTarget = function () { + return window; + }; + WindowScrollGeomCache.prototype.computeClientRect = function () { + return { + left: this.scrollLeft, + right: this.scrollLeft + this.clientWidth, + top: this.scrollTop, + bottom: this.scrollTop + this.clientHeight + }; + }; + // the window is the only scroll object that changes it's rectangle relative + // to the document's topleft as it scrolls + WindowScrollGeomCache.prototype.handleScrollChange = function () { + this.clientRect = this.computeClientRect(); + }; + return WindowScrollGeomCache; +}(ScrollGeomCache)); + +// If available we are using native "performance" API instead of "Date" +// Read more about it on MDN: +// https://developer.mozilla.org/en-US/docs/Web/API/Performance +var getTime = typeof performance === 'function' ? performance.now : Date.now; +/* +For a pointer interaction, automatically scrolls certain scroll containers when the pointer +approaches the edge. + +The caller must call start + handleMove + stop. +*/ +var AutoScroller = /** @class */ (function () { + function AutoScroller() { + var _this = this; + // options that can be set by caller + this.isEnabled = true; + this.scrollQuery = [window, '.fc-scroller']; + this.edgeThreshold = 50; // pixels + this.maxVelocity = 300; // pixels per second + // internal state + this.pointerScreenX = null; + this.pointerScreenY = null; + this.isAnimating = false; + this.scrollCaches = null; + // protect against the initial pointerdown being too close to an edge and starting the scroll + this.everMovedUp = false; + this.everMovedDown = false; + this.everMovedLeft = false; + this.everMovedRight = false; + this.animate = function () { + if (_this.isAnimating) { // wasn't cancelled between animation calls + var edge = _this.computeBestEdge(_this.pointerScreenX + window.pageXOffset, _this.pointerScreenY + window.pageYOffset); + if (edge) { + var now = getTime(); + _this.handleSide(edge, (now - _this.msSinceRequest) / 1000); + _this.requestAnimation(now); + } + else { + _this.isAnimating = false; // will stop animation + } + } + }; + } + AutoScroller.prototype.start = function (pageX, pageY) { + if (this.isEnabled) { + this.scrollCaches = this.buildCaches(); + this.pointerScreenX = null; + this.pointerScreenY = null; + this.everMovedUp = false; + this.everMovedDown = false; + this.everMovedLeft = false; + this.everMovedRight = false; + this.handleMove(pageX, pageY); + } + }; + AutoScroller.prototype.handleMove = function (pageX, pageY) { + if (this.isEnabled) { + var pointerScreenX = pageX - window.pageXOffset; + var pointerScreenY = pageY - window.pageYOffset; + var yDelta = this.pointerScreenY === null ? 0 : pointerScreenY - this.pointerScreenY; + var xDelta = this.pointerScreenX === null ? 0 : pointerScreenX - this.pointerScreenX; + if (yDelta < 0) { + this.everMovedUp = true; + } + else if (yDelta > 0) { + this.everMovedDown = true; + } + if (xDelta < 0) { + this.everMovedLeft = true; + } + else if (xDelta > 0) { + this.everMovedRight = true; + } + this.pointerScreenX = pointerScreenX; + this.pointerScreenY = pointerScreenY; + if (!this.isAnimating) { + this.isAnimating = true; + this.requestAnimation(getTime()); + } + } + }; + AutoScroller.prototype.stop = function () { + if (this.isEnabled) { + this.isAnimating = false; // will stop animation + for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { + var scrollCache = _a[_i]; + scrollCache.destroy(); + } + this.scrollCaches = null; + } + }; + AutoScroller.prototype.requestAnimation = function (now) { + this.msSinceRequest = now; + requestAnimationFrame(this.animate); + }; + AutoScroller.prototype.handleSide = function (edge, seconds) { + var scrollCache = edge.scrollCache; + var edgeThreshold = this.edgeThreshold; + var invDistance = edgeThreshold - edge.distance; + var velocity = // the closer to the edge, the faster we scroll + (invDistance * invDistance) / (edgeThreshold * edgeThreshold) * // quadratic + this.maxVelocity * seconds; + var sign = 1; + switch (edge.name) { + case 'left': + sign = -1; + // falls through + case 'right': + scrollCache.setScrollLeft(scrollCache.getScrollLeft() + velocity * sign); + break; + case 'top': + sign = -1; + // falls through + case 'bottom': + scrollCache.setScrollTop(scrollCache.getScrollTop() + velocity * sign); + break; + } + }; + // left/top are relative to document topleft + AutoScroller.prototype.computeBestEdge = function (left, top) { + var edgeThreshold = this.edgeThreshold; + var bestSide = null; + for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { + var scrollCache = _a[_i]; + var rect = scrollCache.clientRect; + var leftDist = left - rect.left; + var rightDist = rect.right - left; + var topDist = top - rect.top; + var bottomDist = rect.bottom - top; + // completely within the rect? + if (leftDist >= 0 && rightDist >= 0 && topDist >= 0 && bottomDist >= 0) { + if (topDist <= edgeThreshold && this.everMovedUp && scrollCache.canScrollUp() && + (!bestSide || bestSide.distance > topDist)) { + bestSide = { scrollCache: scrollCache, name: 'top', distance: topDist }; + } + if (bottomDist <= edgeThreshold && this.everMovedDown && scrollCache.canScrollDown() && + (!bestSide || bestSide.distance > bottomDist)) { + bestSide = { scrollCache: scrollCache, name: 'bottom', distance: bottomDist }; + } + if (leftDist <= edgeThreshold && this.everMovedLeft && scrollCache.canScrollLeft() && + (!bestSide || bestSide.distance > leftDist)) { + bestSide = { scrollCache: scrollCache, name: 'left', distance: leftDist }; + } + if (rightDist <= edgeThreshold && this.everMovedRight && scrollCache.canScrollRight() && + (!bestSide || bestSide.distance > rightDist)) { + bestSide = { scrollCache: scrollCache, name: 'right', distance: rightDist }; + } + } + } + return bestSide; + }; + AutoScroller.prototype.buildCaches = function () { + return this.queryScrollEls().map(function (el) { + if (el === window) { + return new WindowScrollGeomCache(false); // false = don't listen to user-generated scrolls + } + else { + return new ElementScrollGeomCache(el, false); // false = don't listen to user-generated scrolls + } + }); + }; + AutoScroller.prototype.queryScrollEls = function () { + var els = []; + for (var _i = 0, _a = this.scrollQuery; _i < _a.length; _i++) { + var query = _a[_i]; + if (typeof query === 'object') { + els.push(query); + } + else { + els.push.apply(els, Array.prototype.slice.call(document.querySelectorAll(query))); + } + } + return els; + }; + return AutoScroller; +}()); + +/* +Monitors dragging on an element. Has a number of high-level features: +- minimum distance required before dragging +- minimum wait time ("delay") before dragging +- a mirror element that follows the pointer +*/ +var FeaturefulElementDragging = /** @class */ (function (_super) { + __extends(FeaturefulElementDragging, _super); + function FeaturefulElementDragging(containerEl) { + var _this = _super.call(this, containerEl) || this; + // options that can be directly set by caller + // the caller can also set the PointerDragging's options as well + _this.delay = null; + _this.minDistance = 0; + _this.touchScrollAllowed = true; // prevents drag from starting and blocks scrolling during drag + _this.mirrorNeedsRevert = false; + _this.isInteracting = false; // is the user validly moving the pointer? lasts until pointerup + _this.isDragging = false; // is it INTENTFULLY dragging? lasts until after revert animation + _this.isDelayEnded = false; + _this.isDistanceSurpassed = false; + _this.delayTimeoutId = null; + _this.onPointerDown = function (ev) { + if (!_this.isDragging) { // so new drag doesn't happen while revert animation is going + _this.isInteracting = true; + _this.isDelayEnded = false; + _this.isDistanceSurpassed = false; + preventSelection(document.body); + preventContextMenu(document.body); + // prevent links from being visited if there's an eventual drag. + // also prevents selection in older browsers (maybe?). + // not necessary for touch, besides, browser would complain about passiveness. + if (!ev.isTouch) { + ev.origEvent.preventDefault(); + } + _this.emitter.trigger('pointerdown', ev); + if (!_this.pointer.shouldIgnoreMove) { + // actions related to initiating dragstart+dragmove+dragend... + _this.mirror.setIsVisible(false); // reset. caller must set-visible + _this.mirror.start(ev.subjectEl, ev.pageX, ev.pageY); // must happen on first pointer down + _this.startDelay(ev); + if (!_this.minDistance) { + _this.handleDistanceSurpassed(ev); + } + } + } + }; + _this.onPointerMove = function (ev) { + if (_this.isInteracting) { // if false, still waiting for previous drag's revert + _this.emitter.trigger('pointermove', ev); + if (!_this.isDistanceSurpassed) { + var minDistance = _this.minDistance; + var distanceSq = void 0; // current distance from the origin, squared + var deltaX = ev.deltaX, deltaY = ev.deltaY; + distanceSq = deltaX * deltaX + deltaY * deltaY; + if (distanceSq >= minDistance * minDistance) { // use pythagorean theorem + _this.handleDistanceSurpassed(ev); + } + } + if (_this.isDragging) { + // a real pointer move? (not one simulated by scrolling) + if (ev.origEvent.type !== 'scroll') { + _this.mirror.handleMove(ev.pageX, ev.pageY); + _this.autoScroller.handleMove(ev.pageX, ev.pageY); + } + _this.emitter.trigger('dragmove', ev); + } + } + }; + _this.onPointerUp = function (ev) { + if (_this.isInteracting) { // if false, still waiting for previous drag's revert + _this.isInteracting = false; + allowSelection(document.body); + allowContextMenu(document.body); + _this.emitter.trigger('pointerup', ev); // can potentially set mirrorNeedsRevert + if (_this.isDragging) { + _this.autoScroller.stop(); + _this.tryStopDrag(ev); // which will stop the mirror + } + if (_this.delayTimeoutId) { + clearTimeout(_this.delayTimeoutId); + _this.delayTimeoutId = null; + } + } + }; + var pointer = _this.pointer = new PointerDragging(containerEl); + pointer.emitter.on('pointerdown', _this.onPointerDown); + pointer.emitter.on('pointermove', _this.onPointerMove); + pointer.emitter.on('pointerup', _this.onPointerUp); + _this.mirror = new ElementMirror(); + _this.autoScroller = new AutoScroller(); + return _this; + } + FeaturefulElementDragging.prototype.destroy = function () { + this.pointer.destroy(); + }; + FeaturefulElementDragging.prototype.startDelay = function (ev) { + var _this = this; + if (typeof this.delay === 'number') { + this.delayTimeoutId = setTimeout(function () { + _this.delayTimeoutId = null; + _this.handleDelayEnd(ev); + }, this.delay); // not assignable to number! + } + else { + this.handleDelayEnd(ev); + } + }; + FeaturefulElementDragging.prototype.handleDelayEnd = function (ev) { + this.isDelayEnded = true; + this.tryStartDrag(ev); + }; + FeaturefulElementDragging.prototype.handleDistanceSurpassed = function (ev) { + this.isDistanceSurpassed = true; + this.tryStartDrag(ev); + }; + FeaturefulElementDragging.prototype.tryStartDrag = function (ev) { + if (this.isDelayEnded && this.isDistanceSurpassed) { + if (!this.pointer.wasTouchScroll || this.touchScrollAllowed) { + this.isDragging = true; + this.mirrorNeedsRevert = false; + this.autoScroller.start(ev.pageX, ev.pageY); + this.emitter.trigger('dragstart', ev); + if (this.touchScrollAllowed === false) { + this.pointer.cancelTouchScroll(); + } + } + } + }; + FeaturefulElementDragging.prototype.tryStopDrag = function (ev) { + // .stop() is ALWAYS asynchronous, which we NEED because we want all pointerup events + // that come from the document to fire beforehand. much more convenient this way. + this.mirror.stop(this.mirrorNeedsRevert, this.stopDrag.bind(this, ev) // bound with args + ); + }; + FeaturefulElementDragging.prototype.stopDrag = function (ev) { + this.isDragging = false; + this.emitter.trigger('dragend', ev); + }; + // fill in the implementations... + FeaturefulElementDragging.prototype.setIgnoreMove = function (bool) { + this.pointer.shouldIgnoreMove = bool; + }; + FeaturefulElementDragging.prototype.setMirrorIsVisible = function (bool) { + this.mirror.setIsVisible(bool); + }; + FeaturefulElementDragging.prototype.setMirrorNeedsRevert = function (bool) { + this.mirrorNeedsRevert = bool; + }; + FeaturefulElementDragging.prototype.setAutoScrollEnabled = function (bool) { + this.autoScroller.isEnabled = bool; + }; + return FeaturefulElementDragging; +}(ElementDragging)); + +/* +When this class is instantiated, it records the offset of an element (relative to the document topleft), +and continues to monitor scrolling, updating the cached coordinates if it needs to. +Does not access the DOM after instantiation, so highly performant. + +Also keeps track of all scrolling/overflow:hidden containers that are parents of the given element +and an determine if a given point is inside the combined clipping rectangle. +*/ +var OffsetTracker = /** @class */ (function () { + function OffsetTracker(el) { + this.origRect = computeRect(el); + // will work fine for divs that have overflow:hidden + this.scrollCaches = getClippingParents(el).map(function (el) { + return new ElementScrollGeomCache(el, true); // listen=true + }); + } + OffsetTracker.prototype.destroy = function () { + for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { + var scrollCache = _a[_i]; + scrollCache.destroy(); + } + }; + OffsetTracker.prototype.computeLeft = function () { + var left = this.origRect.left; + for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { + var scrollCache = _a[_i]; + left += scrollCache.origScrollLeft - scrollCache.getScrollLeft(); + } + return left; + }; + OffsetTracker.prototype.computeTop = function () { + var top = this.origRect.top; + for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { + var scrollCache = _a[_i]; + top += scrollCache.origScrollTop - scrollCache.getScrollTop(); + } + return top; + }; + OffsetTracker.prototype.isWithinClipping = function (pageX, pageY) { + var point = { left: pageX, top: pageY }; + for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { + var scrollCache = _a[_i]; + if (!isIgnoredClipping(scrollCache.getEventTarget()) && + !pointInsideRect(point, scrollCache.clientRect)) { + return false; + } + } + return true; + }; + return OffsetTracker; +}()); +// certain clipping containers should never constrain interactions, like <html> and <body> +// https://github.com/fullcalendar/fullcalendar/issues/3615 +function isIgnoredClipping(node) { + var tagName = node.tagName; + return tagName === 'HTML' || tagName === 'BODY'; +} + +/* +Tracks movement over multiple droppable areas (aka "hits") +that exist in one or more DateComponents. +Relies on an existing draggable. + +emits: +- pointerdown +- dragstart +- hitchange - fires initially, even if not over a hit +- pointerup +- (hitchange - again, to null, if ended over a hit) +- dragend +*/ +var HitDragging = /** @class */ (function () { + function HitDragging(dragging, droppableStore) { + var _this = this; + // options that can be set by caller + this.useSubjectCenter = false; + this.requireInitial = true; // if doesn't start out on a hit, won't emit any events + this.initialHit = null; + this.movingHit = null; + this.finalHit = null; // won't ever be populated if shouldIgnoreMove + this.handlePointerDown = function (ev) { + var dragging = _this.dragging; + _this.initialHit = null; + _this.movingHit = null; + _this.finalHit = null; + _this.prepareHits(); + _this.processFirstCoord(ev); + if (_this.initialHit || !_this.requireInitial) { + dragging.setIgnoreMove(false); + _this.emitter.trigger('pointerdown', ev); // TODO: fire this before computing processFirstCoord, so listeners can cancel. this gets fired by almost every handler :( + } + else { + dragging.setIgnoreMove(true); + } + }; + this.handleDragStart = function (ev) { + _this.emitter.trigger('dragstart', ev); + _this.handleMove(ev, true); // force = fire even if initially null + }; + this.handleDragMove = function (ev) { + _this.emitter.trigger('dragmove', ev); + _this.handleMove(ev); + }; + this.handlePointerUp = function (ev) { + _this.releaseHits(); + _this.emitter.trigger('pointerup', ev); + }; + this.handleDragEnd = function (ev) { + if (_this.movingHit) { + _this.emitter.trigger('hitupdate', null, true, ev); + } + _this.finalHit = _this.movingHit; + _this.movingHit = null; + _this.emitter.trigger('dragend', ev); + }; + this.droppableStore = droppableStore; + dragging.emitter.on('pointerdown', this.handlePointerDown); + dragging.emitter.on('dragstart', this.handleDragStart); + dragging.emitter.on('dragmove', this.handleDragMove); + dragging.emitter.on('pointerup', this.handlePointerUp); + dragging.emitter.on('dragend', this.handleDragEnd); + this.dragging = dragging; + this.emitter = new EmitterMixin(); + } + // sets initialHit + // sets coordAdjust + HitDragging.prototype.processFirstCoord = function (ev) { + var origPoint = { left: ev.pageX, top: ev.pageY }; + var adjustedPoint = origPoint; + var subjectEl = ev.subjectEl; + var subjectRect; + if (subjectEl !== document) { + subjectRect = computeRect(subjectEl); + adjustedPoint = constrainPoint(adjustedPoint, subjectRect); + } + var initialHit = this.initialHit = this.queryHitForOffset(adjustedPoint.left, adjustedPoint.top); + if (initialHit) { + if (this.useSubjectCenter && subjectRect) { + var slicedSubjectRect = intersectRects(subjectRect, initialHit.rect); + if (slicedSubjectRect) { + adjustedPoint = getRectCenter(slicedSubjectRect); + } + } + this.coordAdjust = diffPoints(adjustedPoint, origPoint); + } + else { + this.coordAdjust = { left: 0, top: 0 }; + } + }; + HitDragging.prototype.handleMove = function (ev, forceHandle) { + var hit = this.queryHitForOffset(ev.pageX + this.coordAdjust.left, ev.pageY + this.coordAdjust.top); + if (forceHandle || !isHitsEqual(this.movingHit, hit)) { + this.movingHit = hit; + this.emitter.trigger('hitupdate', hit, false, ev); + } + }; + HitDragging.prototype.prepareHits = function () { + this.offsetTrackers = mapHash(this.droppableStore, function (interactionSettings) { + interactionSettings.component.buildPositionCaches(); + return new OffsetTracker(interactionSettings.el); + }); + }; + HitDragging.prototype.releaseHits = function () { + var offsetTrackers = this.offsetTrackers; + for (var id in offsetTrackers) { + offsetTrackers[id].destroy(); + } + this.offsetTrackers = {}; + }; + HitDragging.prototype.queryHitForOffset = function (offsetLeft, offsetTop) { + var _a = this, droppableStore = _a.droppableStore, offsetTrackers = _a.offsetTrackers; + var bestHit = null; + for (var id in droppableStore) { + var component = droppableStore[id].component; + var offsetTracker = offsetTrackers[id]; + if (offsetTracker.isWithinClipping(offsetLeft, offsetTop)) { + var originLeft = offsetTracker.computeLeft(); + var originTop = offsetTracker.computeTop(); + var positionLeft = offsetLeft - originLeft; + var positionTop = offsetTop - originTop; + var origRect = offsetTracker.origRect; + var width = origRect.right - origRect.left; + var height = origRect.bottom - origRect.top; + if ( + // must be within the element's bounds + positionLeft >= 0 && positionLeft < width && + positionTop >= 0 && positionTop < height) { + var hit = component.queryHit(positionLeft, positionTop, width, height); + if (hit && + ( + // make sure the hit is within activeRange, meaning it's not a deal cell + !component.props.dateProfile || // hack for DayTile + rangeContainsRange(component.props.dateProfile.activeRange, hit.dateSpan.range)) && + (!bestHit || hit.layer > bestHit.layer)) { + // TODO: better way to re-orient rectangle + hit.rect.left += originLeft; + hit.rect.right += originLeft; + hit.rect.top += originTop; + hit.rect.bottom += originTop; + bestHit = hit; + } + } + } + } + return bestHit; + }; + return HitDragging; +}()); +function isHitsEqual(hit0, hit1) { + if (!hit0 && !hit1) { + return true; + } + if (Boolean(hit0) !== Boolean(hit1)) { + return false; + } + return isDateSpansEqual(hit0.dateSpan, hit1.dateSpan); +} + +/* +Monitors when the user clicks on a specific date/time of a component. +A pointerdown+pointerup on the same "hit" constitutes a click. +*/ +var DateClicking = /** @class */ (function (_super) { + __extends(DateClicking, _super); + function DateClicking(settings) { + var _this = _super.call(this, settings) || this; + _this.handlePointerDown = function (ev) { + var dragging = _this.dragging; + // do this in pointerdown (not dragend) because DOM might be mutated by the time dragend is fired + dragging.setIgnoreMove(!_this.component.isValidDateDownEl(dragging.pointer.downEl)); + }; + // won't even fire if moving was ignored + _this.handleDragEnd = function (ev) { + var component = _this.component; + var pointer = _this.dragging.pointer; + if (!pointer.wasTouchScroll) { + var _a = _this.hitDragging, initialHit = _a.initialHit, finalHit = _a.finalHit; + if (initialHit && finalHit && isHitsEqual(initialHit, finalHit)) { + component.calendar.triggerDateClick(initialHit.dateSpan, initialHit.dayEl, component.view, ev.origEvent); + } + } + }; + var component = settings.component; + // we DO want to watch pointer moves because otherwise finalHit won't get populated + _this.dragging = new FeaturefulElementDragging(component.el); + _this.dragging.autoScroller.isEnabled = false; + var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, interactionSettingsToStore(settings)); + hitDragging.emitter.on('pointerdown', _this.handlePointerDown); + hitDragging.emitter.on('dragend', _this.handleDragEnd); + return _this; + } + DateClicking.prototype.destroy = function () { + this.dragging.destroy(); + }; + return DateClicking; +}(Interaction)); + +/* +Tracks when the user selects a portion of time of a component, +constituted by a drag over date cells, with a possible delay at the beginning of the drag. +*/ +var DateSelecting = /** @class */ (function (_super) { + __extends(DateSelecting, _super); + function DateSelecting(settings) { + var _this = _super.call(this, settings) || this; + _this.dragSelection = null; + _this.handlePointerDown = function (ev) { + var _a = _this, component = _a.component, dragging = _a.dragging; + var canSelect = component.opt('selectable') && + component.isValidDateDownEl(ev.origEvent.target); + // don't bother to watch expensive moves if component won't do selection + dragging.setIgnoreMove(!canSelect); + // if touch, require user to hold down + dragging.delay = ev.isTouch ? getComponentTouchDelay(component) : null; + }; + _this.handleDragStart = function (ev) { + _this.component.calendar.unselect(ev); // unselect previous selections + }; + _this.handleHitUpdate = function (hit, isFinal) { + var calendar = _this.component.calendar; + var dragSelection = null; + var isInvalid = false; + if (hit) { + dragSelection = joinHitsIntoSelection(_this.hitDragging.initialHit, hit, calendar.pluginSystem.hooks.dateSelectionTransformers); + if (!dragSelection || !_this.component.isDateSelectionValid(dragSelection)) { + isInvalid = true; + dragSelection = null; + } + } + if (dragSelection) { + calendar.dispatch({ type: 'SELECT_DATES', selection: dragSelection }); + } + else if (!isFinal) { // only unselect if moved away while dragging + calendar.dispatch({ type: 'UNSELECT_DATES' }); + } + if (!isInvalid) { + enableCursor(); + } + else { + disableCursor(); + } + if (!isFinal) { + _this.dragSelection = dragSelection; // only clear if moved away from all hits while dragging + } + }; + _this.handlePointerUp = function (pev) { + if (_this.dragSelection) { + // selection is already rendered, so just need to report selection + _this.component.calendar.triggerDateSelect(_this.dragSelection, pev); + _this.dragSelection = null; + } + }; + var component = settings.component; + var dragging = _this.dragging = new FeaturefulElementDragging(component.el); + dragging.touchScrollAllowed = false; + dragging.minDistance = component.opt('selectMinDistance') || 0; + dragging.autoScroller.isEnabled = component.opt('dragScroll'); + var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, interactionSettingsToStore(settings)); + hitDragging.emitter.on('pointerdown', _this.handlePointerDown); + hitDragging.emitter.on('dragstart', _this.handleDragStart); + hitDragging.emitter.on('hitupdate', _this.handleHitUpdate); + hitDragging.emitter.on('pointerup', _this.handlePointerUp); + return _this; + } + DateSelecting.prototype.destroy = function () { + this.dragging.destroy(); + }; + return DateSelecting; +}(Interaction)); +function getComponentTouchDelay(component) { + var delay = component.opt('selectLongPressDelay'); + if (delay == null) { + delay = component.opt('longPressDelay'); + } + return delay; +} +function joinHitsIntoSelection(hit0, hit1, dateSelectionTransformers) { + var dateSpan0 = hit0.dateSpan; + var dateSpan1 = hit1.dateSpan; + var ms = [ + dateSpan0.range.start, + dateSpan0.range.end, + dateSpan1.range.start, + dateSpan1.range.end + ]; + ms.sort(compareNumbers); + var props = {}; + for (var _i = 0, dateSelectionTransformers_1 = dateSelectionTransformers; _i < dateSelectionTransformers_1.length; _i++) { + var transformer = dateSelectionTransformers_1[_i]; + var res = transformer(hit0, hit1); + if (res === false) { + return null; + } + else if (res) { + __assign(props, res); + } + } + props.range = { start: ms[0], end: ms[3] }; + props.allDay = dateSpan0.allDay; + return props; +} + +var EventDragging = /** @class */ (function (_super) { + __extends(EventDragging, _super); + function EventDragging(settings) { + var _this = _super.call(this, settings) || this; + // internal state + _this.subjectSeg = null; // the seg being selected/dragged + _this.isDragging = false; + _this.eventRange = null; + _this.relevantEvents = null; // the events being dragged + _this.receivingCalendar = null; + _this.validMutation = null; + _this.mutatedRelevantEvents = null; + _this.handlePointerDown = function (ev) { + var origTarget = ev.origEvent.target; + var _a = _this, component = _a.component, dragging = _a.dragging; + var mirror = dragging.mirror; + var initialCalendar = component.calendar; + var subjectSeg = _this.subjectSeg = getElSeg(ev.subjectEl); + var eventRange = _this.eventRange = subjectSeg.eventRange; + var eventInstanceId = eventRange.instance.instanceId; + _this.relevantEvents = getRelevantEvents(initialCalendar.state.eventStore, eventInstanceId); + dragging.minDistance = ev.isTouch ? 0 : component.opt('eventDragMinDistance'); + dragging.delay = + // only do a touch delay if touch and this event hasn't been selected yet + (ev.isTouch && eventInstanceId !== component.props.eventSelection) ? + getComponentTouchDelay$1(component) : + null; + mirror.parentNode = initialCalendar.el; + mirror.revertDuration = component.opt('dragRevertDuration'); + var isValid = component.isValidSegDownEl(origTarget) && + !elementClosest(origTarget, '.fc-resizer'); // NOT on a resizer + dragging.setIgnoreMove(!isValid); + // disable dragging for elements that are resizable (ie, selectable) + // but are not draggable + _this.isDragging = isValid && + ev.subjectEl.classList.contains('fc-draggable'); + }; + _this.handleDragStart = function (ev) { + var initialCalendar = _this.component.calendar; + var eventRange = _this.eventRange; + var eventInstanceId = eventRange.instance.instanceId; + if (ev.isTouch) { + // need to select a different event? + if (eventInstanceId !== _this.component.props.eventSelection) { + initialCalendar.dispatch({ type: 'SELECT_EVENT', eventInstanceId: eventInstanceId }); + } + } + else { + // if now using mouse, but was previous touch interaction, clear selected event + initialCalendar.dispatch({ type: 'UNSELECT_EVENT' }); + } + if (_this.isDragging) { + initialCalendar.unselect(ev); // unselect *date* selection + initialCalendar.publiclyTrigger('eventDragStart', [ + { + el: _this.subjectSeg.el, + event: new EventApi(initialCalendar, eventRange.def, eventRange.instance), + jsEvent: ev.origEvent, + view: _this.component.view + } + ]); + } + }; + _this.handleHitUpdate = function (hit, isFinal) { + if (!_this.isDragging) { + return; + } + var relevantEvents = _this.relevantEvents; + var initialHit = _this.hitDragging.initialHit; + var initialCalendar = _this.component.calendar; + // states based on new hit + var receivingCalendar = null; + var mutation = null; + var mutatedRelevantEvents = null; + var isInvalid = false; + var interaction = { + affectedEvents: relevantEvents, + mutatedEvents: createEmptyEventStore(), + isEvent: true, + origSeg: _this.subjectSeg + }; + if (hit) { + var receivingComponent = hit.component; + receivingCalendar = receivingComponent.calendar; + if (initialCalendar === receivingCalendar || + receivingComponent.opt('editable') && receivingComponent.opt('droppable')) { + mutation = computeEventMutation(initialHit, hit, receivingCalendar.pluginSystem.hooks.eventDragMutationMassagers); + if (mutation) { + mutatedRelevantEvents = applyMutationToEventStore(relevantEvents, receivingCalendar.eventUiBases, mutation, receivingCalendar); + interaction.mutatedEvents = mutatedRelevantEvents; + if (!receivingComponent.isInteractionValid(interaction)) { + isInvalid = true; + mutation = null; + mutatedRelevantEvents = null; + interaction.mutatedEvents = createEmptyEventStore(); + } + } + } + else { + receivingCalendar = null; + } + } + _this.displayDrag(receivingCalendar, interaction); + if (!isInvalid) { + enableCursor(); + } + else { + disableCursor(); + } + if (!isFinal) { + if (initialCalendar === receivingCalendar && // TODO: write test for this + isHitsEqual(initialHit, hit)) { + mutation = null; + } + _this.dragging.setMirrorNeedsRevert(!mutation); + // render the mirror if no already-rendered mirror + // TODO: wish we could somehow wait for dispatch to guarantee render + _this.dragging.setMirrorIsVisible(!hit || !document.querySelector('.fc-mirror')); + // assign states based on new hit + _this.receivingCalendar = receivingCalendar; + _this.validMutation = mutation; + _this.mutatedRelevantEvents = mutatedRelevantEvents; + } + }; + _this.handlePointerUp = function () { + if (!_this.isDragging) { + _this.cleanup(); // because handleDragEnd won't fire + } + }; + _this.handleDragEnd = function (ev) { + if (_this.isDragging) { + var initialCalendar_1 = _this.component.calendar; + var initialView = _this.component.view; + var _a = _this, receivingCalendar = _a.receivingCalendar, validMutation = _a.validMutation; + var eventDef = _this.eventRange.def; + var eventInstance = _this.eventRange.instance; + var eventApi = new EventApi(initialCalendar_1, eventDef, eventInstance); + var relevantEvents_1 = _this.relevantEvents; + var mutatedRelevantEvents = _this.mutatedRelevantEvents; + var finalHit = _this.hitDragging.finalHit; + _this.clearDrag(); // must happen after revert animation + initialCalendar_1.publiclyTrigger('eventDragStop', [ + { + el: _this.subjectSeg.el, + event: eventApi, + jsEvent: ev.origEvent, + view: initialView + } + ]); + if (validMutation) { + // dropped within same calendar + if (receivingCalendar === initialCalendar_1) { + initialCalendar_1.dispatch({ + type: 'MERGE_EVENTS', + eventStore: mutatedRelevantEvents + }); + var transformed = {}; + for (var _i = 0, _b = initialCalendar_1.pluginSystem.hooks.eventDropTransformers; _i < _b.length; _i++) { + var transformer = _b[_i]; + __assign(transformed, transformer(validMutation, initialCalendar_1)); + } + var eventDropArg = __assign({}, transformed, { el: ev.subjectEl, delta: validMutation.datesDelta, oldEvent: eventApi, event: new EventApi(// the data AFTER the mutation + initialCalendar_1, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null), revert: function () { + initialCalendar_1.dispatch({ + type: 'MERGE_EVENTS', + eventStore: relevantEvents_1 + }); + }, jsEvent: ev.origEvent, view: initialView }); + initialCalendar_1.publiclyTrigger('eventDrop', [eventDropArg]); + // dropped in different calendar + } + else if (receivingCalendar) { + initialCalendar_1.publiclyTrigger('eventLeave', [ + { + draggedEl: ev.subjectEl, + event: eventApi, + view: initialView + } + ]); + initialCalendar_1.dispatch({ + type: 'REMOVE_EVENT_INSTANCES', + instances: _this.mutatedRelevantEvents.instances + }); + receivingCalendar.dispatch({ + type: 'MERGE_EVENTS', + eventStore: _this.mutatedRelevantEvents + }); + if (ev.isTouch) { + receivingCalendar.dispatch({ + type: 'SELECT_EVENT', + eventInstanceId: eventInstance.instanceId + }); + } + var dropArg = __assign({}, receivingCalendar.buildDatePointApi(finalHit.dateSpan), { draggedEl: ev.subjectEl, jsEvent: ev.origEvent, view: finalHit.component // should this be finalHit.component.view? See #4644 + }); + receivingCalendar.publiclyTrigger('drop', [dropArg]); + receivingCalendar.publiclyTrigger('eventReceive', [ + { + draggedEl: ev.subjectEl, + event: new EventApi(// the data AFTER the mutation + receivingCalendar, mutatedRelevantEvents.defs[eventDef.defId], mutatedRelevantEvents.instances[eventInstance.instanceId]), + view: finalHit.component // should this be finalHit.component.view? See #4644 + } + ]); + } + } + else { + initialCalendar_1.publiclyTrigger('_noEventDrop'); + } + } + _this.cleanup(); + }; + var component = _this.component; + var dragging = _this.dragging = new FeaturefulElementDragging(component.el); + dragging.pointer.selector = EventDragging.SELECTOR; + dragging.touchScrollAllowed = false; + dragging.autoScroller.isEnabled = component.opt('dragScroll'); + var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, interactionSettingsStore); + hitDragging.useSubjectCenter = settings.useEventCenter; + hitDragging.emitter.on('pointerdown', _this.handlePointerDown); + hitDragging.emitter.on('dragstart', _this.handleDragStart); + hitDragging.emitter.on('hitupdate', _this.handleHitUpdate); + hitDragging.emitter.on('pointerup', _this.handlePointerUp); + hitDragging.emitter.on('dragend', _this.handleDragEnd); + return _this; + } + EventDragging.prototype.destroy = function () { + this.dragging.destroy(); + }; + // render a drag state on the next receivingCalendar + EventDragging.prototype.displayDrag = function (nextCalendar, state) { + var initialCalendar = this.component.calendar; + var prevCalendar = this.receivingCalendar; + // does the previous calendar need to be cleared? + if (prevCalendar && prevCalendar !== nextCalendar) { + // does the initial calendar need to be cleared? + // if so, don't clear all the way. we still need to to hide the affectedEvents + if (prevCalendar === initialCalendar) { + prevCalendar.dispatch({ + type: 'SET_EVENT_DRAG', + state: { + affectedEvents: state.affectedEvents, + mutatedEvents: createEmptyEventStore(), + isEvent: true, + origSeg: state.origSeg + } + }); + // completely clear the old calendar if it wasn't the initial + } + else { + prevCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' }); + } + } + if (nextCalendar) { + nextCalendar.dispatch({ type: 'SET_EVENT_DRAG', state: state }); + } + }; + EventDragging.prototype.clearDrag = function () { + var initialCalendar = this.component.calendar; + var receivingCalendar = this.receivingCalendar; + if (receivingCalendar) { + receivingCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' }); + } + // the initial calendar might have an dummy drag state from displayDrag + if (initialCalendar !== receivingCalendar) { + initialCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' }); + } + }; + EventDragging.prototype.cleanup = function () { + this.subjectSeg = null; + this.isDragging = false; + this.eventRange = null; + this.relevantEvents = null; + this.receivingCalendar = null; + this.validMutation = null; + this.mutatedRelevantEvents = null; + }; + EventDragging.SELECTOR = '.fc-draggable, .fc-resizable'; // TODO: test this in IE11 + return EventDragging; +}(Interaction)); +function computeEventMutation(hit0, hit1, massagers) { + var dateSpan0 = hit0.dateSpan; + var dateSpan1 = hit1.dateSpan; + var date0 = dateSpan0.range.start; + var date1 = dateSpan1.range.start; + var standardProps = {}; + if (dateSpan0.allDay !== dateSpan1.allDay) { + standardProps.allDay = dateSpan1.allDay; + standardProps.hasEnd = hit1.component.opt('allDayMaintainDuration'); + if (dateSpan1.allDay) { + // means date1 is already start-of-day, + // but date0 needs to be converted + date0 = startOfDay(date0); + } + } + var delta = diffDates(date0, date1, hit0.component.dateEnv, hit0.component === hit1.component ? + hit0.component.largeUnit : + null); + if (delta.milliseconds) { // has hours/minutes/seconds + standardProps.allDay = false; + } + var mutation = { + datesDelta: delta, + standardProps: standardProps + }; + for (var _i = 0, massagers_1 = massagers; _i < massagers_1.length; _i++) { + var massager = massagers_1[_i]; + massager(mutation, hit0, hit1); + } + return mutation; +} +function getComponentTouchDelay$1(component) { + var delay = component.opt('eventLongPressDelay'); + if (delay == null) { + delay = component.opt('longPressDelay'); + } + return delay; +} + +var EventDragging$1 = /** @class */ (function (_super) { + __extends(EventDragging, _super); + function EventDragging(settings) { + var _this = _super.call(this, settings) || this; + // internal state + _this.draggingSeg = null; // TODO: rename to resizingSeg? subjectSeg? + _this.eventRange = null; + _this.relevantEvents = null; + _this.validMutation = null; + _this.mutatedRelevantEvents = null; + _this.handlePointerDown = function (ev) { + var component = _this.component; + var seg = _this.querySeg(ev); + var eventRange = _this.eventRange = seg.eventRange; + _this.dragging.minDistance = component.opt('eventDragMinDistance'); + // if touch, need to be working with a selected event + _this.dragging.setIgnoreMove(!_this.component.isValidSegDownEl(ev.origEvent.target) || + (ev.isTouch && _this.component.props.eventSelection !== eventRange.instance.instanceId)); + }; + _this.handleDragStart = function (ev) { + var calendar = _this.component.calendar; + var eventRange = _this.eventRange; + _this.relevantEvents = getRelevantEvents(calendar.state.eventStore, _this.eventRange.instance.instanceId); + _this.draggingSeg = _this.querySeg(ev); + calendar.unselect(); + calendar.publiclyTrigger('eventResizeStart', [ + { + el: _this.draggingSeg.el, + event: new EventApi(calendar, eventRange.def, eventRange.instance), + jsEvent: ev.origEvent, + view: _this.component.view + } + ]); + }; + _this.handleHitUpdate = function (hit, isFinal, ev) { + var calendar = _this.component.calendar; + var relevantEvents = _this.relevantEvents; + var initialHit = _this.hitDragging.initialHit; + var eventInstance = _this.eventRange.instance; + var mutation = null; + var mutatedRelevantEvents = null; + var isInvalid = false; + var interaction = { + affectedEvents: relevantEvents, + mutatedEvents: createEmptyEventStore(), + isEvent: true, + origSeg: _this.draggingSeg + }; + if (hit) { + mutation = computeMutation(initialHit, hit, ev.subjectEl.classList.contains('fc-start-resizer'), eventInstance.range, calendar.pluginSystem.hooks.eventResizeJoinTransforms); + } + if (mutation) { + mutatedRelevantEvents = applyMutationToEventStore(relevantEvents, calendar.eventUiBases, mutation, calendar); + interaction.mutatedEvents = mutatedRelevantEvents; + if (!_this.component.isInteractionValid(interaction)) { + isInvalid = true; + mutation = null; + mutatedRelevantEvents = null; + interaction.mutatedEvents = null; + } + } + if (mutatedRelevantEvents) { + calendar.dispatch({ + type: 'SET_EVENT_RESIZE', + state: interaction + }); + } + else { + calendar.dispatch({ type: 'UNSET_EVENT_RESIZE' }); + } + if (!isInvalid) { + enableCursor(); + } + else { + disableCursor(); + } + if (!isFinal) { + if (mutation && isHitsEqual(initialHit, hit)) { + mutation = null; + } + _this.validMutation = mutation; + _this.mutatedRelevantEvents = mutatedRelevantEvents; + } + }; + _this.handleDragEnd = function (ev) { + var calendar = _this.component.calendar; + var view = _this.component.view; + var eventDef = _this.eventRange.def; + var eventInstance = _this.eventRange.instance; + var eventApi = new EventApi(calendar, eventDef, eventInstance); + var relevantEvents = _this.relevantEvents; + var mutatedRelevantEvents = _this.mutatedRelevantEvents; + calendar.publiclyTrigger('eventResizeStop', [ + { + el: _this.draggingSeg.el, + event: eventApi, + jsEvent: ev.origEvent, + view: view + } + ]); + if (_this.validMutation) { + calendar.dispatch({ + type: 'MERGE_EVENTS', + eventStore: mutatedRelevantEvents + }); + calendar.publiclyTrigger('eventResize', [ + { + el: _this.draggingSeg.el, + startDelta: _this.validMutation.startDelta || createDuration(0), + endDelta: _this.validMutation.endDelta || createDuration(0), + prevEvent: eventApi, + event: new EventApi(// the data AFTER the mutation + calendar, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null), + revert: function () { + calendar.dispatch({ + type: 'MERGE_EVENTS', + eventStore: relevantEvents + }); + }, + jsEvent: ev.origEvent, + view: view + } + ]); + } + else { + calendar.publiclyTrigger('_noEventResize'); + } + // reset all internal state + _this.draggingSeg = null; + _this.relevantEvents = null; + _this.validMutation = null; + // okay to keep eventInstance around. useful to set it in handlePointerDown + }; + var component = settings.component; + var dragging = _this.dragging = new FeaturefulElementDragging(component.el); + dragging.pointer.selector = '.fc-resizer'; + dragging.touchScrollAllowed = false; + dragging.autoScroller.isEnabled = component.opt('dragScroll'); + var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, interactionSettingsToStore(settings)); + hitDragging.emitter.on('pointerdown', _this.handlePointerDown); + hitDragging.emitter.on('dragstart', _this.handleDragStart); + hitDragging.emitter.on('hitupdate', _this.handleHitUpdate); + hitDragging.emitter.on('dragend', _this.handleDragEnd); + return _this; + } + EventDragging.prototype.destroy = function () { + this.dragging.destroy(); + }; + EventDragging.prototype.querySeg = function (ev) { + return getElSeg(elementClosest(ev.subjectEl, this.component.fgSegSelector)); + }; + return EventDragging; +}(Interaction)); +function computeMutation(hit0, hit1, isFromStart, instanceRange, transforms) { + var dateEnv = hit0.component.dateEnv; + var date0 = hit0.dateSpan.range.start; + var date1 = hit1.dateSpan.range.start; + var delta = diffDates(date0, date1, dateEnv, hit0.component.largeUnit); + var props = {}; + for (var _i = 0, transforms_1 = transforms; _i < transforms_1.length; _i++) { + var transform = transforms_1[_i]; + var res = transform(hit0, hit1); + if (res === false) { + return null; + } + else if (res) { + __assign(props, res); + } + } + if (isFromStart) { + if (dateEnv.add(instanceRange.start, delta) < instanceRange.end) { + props.startDelta = delta; + return props; + } + } + else { + if (dateEnv.add(instanceRange.end, delta) > instanceRange.start) { + props.endDelta = delta; + return props; + } + } + return null; +} + +var UnselectAuto = /** @class */ (function () { + function UnselectAuto(calendar) { + var _this = this; + this.isRecentPointerDateSelect = false; // wish we could use a selector to detect date selection, but uses hit system + this.onSelect = function (selectInfo) { + if (selectInfo.jsEvent) { + _this.isRecentPointerDateSelect = true; + } + }; + this.onDocumentPointerUp = function (pev) { + var _a = _this, calendar = _a.calendar, documentPointer = _a.documentPointer; + var state = calendar.state; + // touch-scrolling should never unfocus any type of selection + if (!documentPointer.wasTouchScroll) { + if (state.dateSelection && // an existing date selection? + !_this.isRecentPointerDateSelect // a new pointer-initiated date selection since last onDocumentPointerUp? + ) { + var unselectAuto = calendar.viewOpt('unselectAuto'); + var unselectCancel = calendar.viewOpt('unselectCancel'); + if (unselectAuto && (!unselectAuto || !elementClosest(documentPointer.downEl, unselectCancel))) { + calendar.unselect(pev); + } + } + if (state.eventSelection && // an existing event selected? + !elementClosest(documentPointer.downEl, EventDragging.SELECTOR) // interaction DIDN'T start on an event + ) { + calendar.dispatch({ type: 'UNSELECT_EVENT' }); + } + } + _this.isRecentPointerDateSelect = false; + }; + this.calendar = calendar; + var documentPointer = this.documentPointer = new PointerDragging(document); + documentPointer.shouldIgnoreMove = true; + documentPointer.shouldWatchScroll = false; + documentPointer.emitter.on('pointerup', this.onDocumentPointerUp); + /* + TODO: better way to know about whether there was a selection with the pointer + */ + calendar.on('select', this.onSelect); + } + UnselectAuto.prototype.destroy = function () { + this.calendar.off('select', this.onSelect); + this.documentPointer.destroy(); + }; + return UnselectAuto; +}()); + +/* +Given an already instantiated draggable object for one-or-more elements, +Interprets any dragging as an attempt to drag an events that lives outside +of a calendar onto a calendar. +*/ +var ExternalElementDragging = /** @class */ (function () { + function ExternalElementDragging(dragging, suppliedDragMeta) { + var _this = this; + this.receivingCalendar = null; + this.droppableEvent = null; // will exist for all drags, even if create:false + this.suppliedDragMeta = null; + this.dragMeta = null; + this.handleDragStart = function (ev) { + _this.dragMeta = _this.buildDragMeta(ev.subjectEl); + }; + this.handleHitUpdate = function (hit, isFinal, ev) { + var dragging = _this.hitDragging.dragging; + var receivingCalendar = null; + var droppableEvent = null; + var isInvalid = false; + var interaction = { + affectedEvents: createEmptyEventStore(), + mutatedEvents: createEmptyEventStore(), + isEvent: _this.dragMeta.create, + origSeg: null + }; + if (hit) { + receivingCalendar = hit.component.calendar; + if (_this.canDropElOnCalendar(ev.subjectEl, receivingCalendar)) { + droppableEvent = computeEventForDateSpan(hit.dateSpan, _this.dragMeta, receivingCalendar); + interaction.mutatedEvents = eventTupleToStore(droppableEvent); + isInvalid = !isInteractionValid(interaction, receivingCalendar); + if (isInvalid) { + interaction.mutatedEvents = createEmptyEventStore(); + droppableEvent = null; + } + } + } + _this.displayDrag(receivingCalendar, interaction); + // show mirror if no already-rendered mirror element OR if we are shutting down the mirror (?) + // TODO: wish we could somehow wait for dispatch to guarantee render + dragging.setMirrorIsVisible(isFinal || !droppableEvent || !document.querySelector('.fc-mirror')); + if (!isInvalid) { + enableCursor(); + } + else { + disableCursor(); + } + if (!isFinal) { + dragging.setMirrorNeedsRevert(!droppableEvent); + _this.receivingCalendar = receivingCalendar; + _this.droppableEvent = droppableEvent; + } + }; + this.handleDragEnd = function (pev) { + var _a = _this, receivingCalendar = _a.receivingCalendar, droppableEvent = _a.droppableEvent; + _this.clearDrag(); + if (receivingCalendar && droppableEvent) { + var finalHit = _this.hitDragging.finalHit; + var finalView = finalHit.component.view; + var dragMeta = _this.dragMeta; + var arg = __assign({}, receivingCalendar.buildDatePointApi(finalHit.dateSpan), { draggedEl: pev.subjectEl, jsEvent: pev.origEvent, view: finalView }); + receivingCalendar.publiclyTrigger('drop', [arg]); + if (dragMeta.create) { + receivingCalendar.dispatch({ + type: 'MERGE_EVENTS', + eventStore: eventTupleToStore(droppableEvent) + }); + if (pev.isTouch) { + receivingCalendar.dispatch({ + type: 'SELECT_EVENT', + eventInstanceId: droppableEvent.instance.instanceId + }); + } + // signal that an external event landed + receivingCalendar.publiclyTrigger('eventReceive', [ + { + draggedEl: pev.subjectEl, + event: new EventApi(receivingCalendar, droppableEvent.def, droppableEvent.instance), + view: finalView + } + ]); + } + } + _this.receivingCalendar = null; + _this.droppableEvent = null; + }; + var hitDragging = this.hitDragging = new HitDragging(dragging, interactionSettingsStore); + hitDragging.requireInitial = false; // will start outside of a component + hitDragging.emitter.on('dragstart', this.handleDragStart); + hitDragging.emitter.on('hitupdate', this.handleHitUpdate); + hitDragging.emitter.on('dragend', this.handleDragEnd); + this.suppliedDragMeta = suppliedDragMeta; + } + ExternalElementDragging.prototype.buildDragMeta = function (subjectEl) { + if (typeof this.suppliedDragMeta === 'object') { + return parseDragMeta(this.suppliedDragMeta); + } + else if (typeof this.suppliedDragMeta === 'function') { + return parseDragMeta(this.suppliedDragMeta(subjectEl)); + } + else { + return getDragMetaFromEl(subjectEl); + } + }; + ExternalElementDragging.prototype.displayDrag = function (nextCalendar, state) { + var prevCalendar = this.receivingCalendar; + if (prevCalendar && prevCalendar !== nextCalendar) { + prevCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' }); + } + if (nextCalendar) { + nextCalendar.dispatch({ type: 'SET_EVENT_DRAG', state: state }); + } + }; + ExternalElementDragging.prototype.clearDrag = function () { + if (this.receivingCalendar) { + this.receivingCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' }); + } + }; + ExternalElementDragging.prototype.canDropElOnCalendar = function (el, receivingCalendar) { + var dropAccept = receivingCalendar.opt('dropAccept'); + if (typeof dropAccept === 'function') { + return dropAccept(el); + } + else if (typeof dropAccept === 'string' && dropAccept) { + return Boolean(elementMatches(el, dropAccept)); + } + return true; + }; + return ExternalElementDragging; +}()); +// Utils for computing event store from the DragMeta +// ---------------------------------------------------------------------------------------------------- +function computeEventForDateSpan(dateSpan, dragMeta, calendar) { + var defProps = __assign({}, dragMeta.leftoverProps); + for (var _i = 0, _a = calendar.pluginSystem.hooks.externalDefTransforms; _i < _a.length; _i++) { + var transform = _a[_i]; + __assign(defProps, transform(dateSpan, dragMeta)); + } + var def = parseEventDef(defProps, dragMeta.sourceId, dateSpan.allDay, calendar.opt('forceEventDuration') || Boolean(dragMeta.duration), // hasEnd + calendar); + var start = dateSpan.range.start; + // only rely on time info if drop zone is all-day, + // otherwise, we already know the time + if (dateSpan.allDay && dragMeta.startTime) { + start = calendar.dateEnv.add(start, dragMeta.startTime); + } + var end = dragMeta.duration ? + calendar.dateEnv.add(start, dragMeta.duration) : + calendar.getDefaultEventEnd(dateSpan.allDay, start); + var instance = createEventInstance(def.defId, { start: start, end: end }); + return { def: def, instance: instance }; +} +// Utils for extracting data from element +// ---------------------------------------------------------------------------------------------------- +function getDragMetaFromEl(el) { + var str = getEmbeddedElData(el, 'event'); + var obj = str ? + JSON.parse(str) : + { create: false }; // if no embedded data, assume no event creation + return parseDragMeta(obj); +} +config.dataAttrPrefix = ''; +function getEmbeddedElData(el, name) { + var prefix = config.dataAttrPrefix; + var prefixedName = (prefix ? prefix + '-' : '') + name; + return el.getAttribute('data-' + prefixedName) || ''; +} + +/* +Makes an element (that is *external* to any calendar) draggable. +Can pass in data that determines how an event will be created when dropped onto a calendar. +Leverages FullCalendar's internal drag-n-drop functionality WITHOUT a third-party drag system. +*/ +var ExternalDraggable = /** @class */ (function () { + function ExternalDraggable(el, settings) { + var _this = this; + if (settings === void 0) { settings = {}; } + this.handlePointerDown = function (ev) { + var dragging = _this.dragging; + var _a = _this.settings, minDistance = _a.minDistance, longPressDelay = _a.longPressDelay; + dragging.minDistance = + minDistance != null ? + minDistance : + (ev.isTouch ? 0 : globalDefaults.eventDragMinDistance); + dragging.delay = + ev.isTouch ? // TODO: eventually read eventLongPressDelay instead vvv + (longPressDelay != null ? longPressDelay : globalDefaults.longPressDelay) : + 0; + }; + this.handleDragStart = function (ev) { + if (ev.isTouch && + _this.dragging.delay && + ev.subjectEl.classList.contains('fc-event')) { + _this.dragging.mirror.getMirrorEl().classList.add('fc-selected'); + } + }; + this.settings = settings; + var dragging = this.dragging = new FeaturefulElementDragging(el); + dragging.touchScrollAllowed = false; + if (settings.itemSelector != null) { + dragging.pointer.selector = settings.itemSelector; + } + if (settings.appendTo != null) { + dragging.mirror.parentNode = settings.appendTo; // TODO: write tests + } + dragging.emitter.on('pointerdown', this.handlePointerDown); + dragging.emitter.on('dragstart', this.handleDragStart); + new ExternalElementDragging(dragging, settings.eventData); + } + ExternalDraggable.prototype.destroy = function () { + this.dragging.destroy(); + }; + return ExternalDraggable; +}()); + +/* +Detects when a *THIRD-PARTY* drag-n-drop system interacts with elements. +The third-party system is responsible for drawing the visuals effects of the drag. +This class simply monitors for pointer movements and fires events. +It also has the ability to hide the moving element (the "mirror") during the drag. +*/ +var InferredElementDragging = /** @class */ (function (_super) { + __extends(InferredElementDragging, _super); + function InferredElementDragging(containerEl) { + var _this = _super.call(this, containerEl) || this; + _this.shouldIgnoreMove = false; + _this.mirrorSelector = ''; + _this.currentMirrorEl = null; + _this.handlePointerDown = function (ev) { + _this.emitter.trigger('pointerdown', ev); + if (!_this.shouldIgnoreMove) { + // fire dragstart right away. does not support delay or min-distance + _this.emitter.trigger('dragstart', ev); + } + }; + _this.handlePointerMove = function (ev) { + if (!_this.shouldIgnoreMove) { + _this.emitter.trigger('dragmove', ev); + } + }; + _this.handlePointerUp = function (ev) { + _this.emitter.trigger('pointerup', ev); + if (!_this.shouldIgnoreMove) { + // fire dragend right away. does not support a revert animation + _this.emitter.trigger('dragend', ev); + } + }; + var pointer = _this.pointer = new PointerDragging(containerEl); + pointer.emitter.on('pointerdown', _this.handlePointerDown); + pointer.emitter.on('pointermove', _this.handlePointerMove); + pointer.emitter.on('pointerup', _this.handlePointerUp); + return _this; + } + InferredElementDragging.prototype.destroy = function () { + this.pointer.destroy(); + }; + InferredElementDragging.prototype.setIgnoreMove = function (bool) { + this.shouldIgnoreMove = bool; + }; + InferredElementDragging.prototype.setMirrorIsVisible = function (bool) { + if (bool) { + // restore a previously hidden element. + // use the reference in case the selector class has already been removed. + if (this.currentMirrorEl) { + this.currentMirrorEl.style.visibility = ''; + this.currentMirrorEl = null; + } + } + else { + var mirrorEl = this.mirrorSelector ? + document.querySelector(this.mirrorSelector) : + null; + if (mirrorEl) { + this.currentMirrorEl = mirrorEl; + mirrorEl.style.visibility = 'hidden'; + } + } + }; + return InferredElementDragging; +}(ElementDragging)); + +/* +Bridges third-party drag-n-drop systems with FullCalendar. +Must be instantiated and destroyed by caller. +*/ +var ThirdPartyDraggable = /** @class */ (function () { + function ThirdPartyDraggable(containerOrSettings, settings) { + var containerEl = document; + if ( + // wish we could just test instanceof EventTarget, but doesn't work in IE11 + containerOrSettings === document || + containerOrSettings instanceof Element) { + containerEl = containerOrSettings; + settings = settings || {}; + } + else { + settings = (containerOrSettings || {}); + } + var dragging = this.dragging = new InferredElementDragging(containerEl); + if (typeof settings.itemSelector === 'string') { + dragging.pointer.selector = settings.itemSelector; + } + else if (containerEl === document) { + dragging.pointer.selector = '[data-event]'; + } + if (typeof settings.mirrorSelector === 'string') { + dragging.mirrorSelector = settings.mirrorSelector; + } + new ExternalElementDragging(dragging, settings.eventData); + } + ThirdPartyDraggable.prototype.destroy = function () { + this.dragging.destroy(); + }; + return ThirdPartyDraggable; +}()); + +var main = createPlugin({ + componentInteractions: [DateClicking, DateSelecting, EventDragging, EventDragging$1], + calendarInteractions: [UnselectAuto], + elementDraggingImpl: FeaturefulElementDragging +}); + +export default main; +export { ExternalDraggable as Draggable, FeaturefulElementDragging, PointerDragging, ThirdPartyDraggable }; diff --git a/AKPlan/static/AKPlan/fullcalendar/interaction/main.js b/AKPlan/static/AKPlan/fullcalendar/interaction/main.js new file mode 100644 index 00000000..10589f28 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/interaction/main.js @@ -0,0 +1,2143 @@ +/*! +FullCalendar Interaction Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) : + typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) : + (global = global || self, factory(global.FullCalendarInteraction = {}, global.FullCalendar)); +}(this, function (exports, core) { 'use strict'; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + core.config.touchMouseIgnoreWait = 500; + var ignoreMouseDepth = 0; + var listenerCnt = 0; + var isWindowTouchMoveCancelled = false; + /* + Uses a "pointer" abstraction, which monitors UI events for both mouse and touch. + Tracks when the pointer "drags" on a certain element, meaning down+move+up. + + Also, tracks if there was touch-scrolling. + Also, can prevent touch-scrolling from happening. + Also, can fire pointermove events when scrolling happens underneath, even when no real pointer movement. + + emits: + - pointerdown + - pointermove + - pointerup + */ + var PointerDragging = /** @class */ (function () { + function PointerDragging(containerEl) { + var _this = this; + this.subjectEl = null; + this.downEl = null; + // options that can be directly assigned by caller + this.selector = ''; // will cause subjectEl in all emitted events to be this element + this.handleSelector = ''; + this.shouldIgnoreMove = false; + this.shouldWatchScroll = true; // for simulating pointermove on scroll + // internal states + this.isDragging = false; + this.isTouchDragging = false; + this.wasTouchScroll = false; + // Mouse + // ---------------------------------------------------------------------------------------------------- + this.handleMouseDown = function (ev) { + if (!_this.shouldIgnoreMouse() && + isPrimaryMouseButton(ev) && + _this.tryStart(ev)) { + var pev = _this.createEventFromMouse(ev, true); + _this.emitter.trigger('pointerdown', pev); + _this.initScrollWatch(pev); + if (!_this.shouldIgnoreMove) { + document.addEventListener('mousemove', _this.handleMouseMove); + } + document.addEventListener('mouseup', _this.handleMouseUp); + } + }; + this.handleMouseMove = function (ev) { + var pev = _this.createEventFromMouse(ev); + _this.recordCoords(pev); + _this.emitter.trigger('pointermove', pev); + }; + this.handleMouseUp = function (ev) { + document.removeEventListener('mousemove', _this.handleMouseMove); + document.removeEventListener('mouseup', _this.handleMouseUp); + _this.emitter.trigger('pointerup', _this.createEventFromMouse(ev)); + _this.cleanup(); // call last so that pointerup has access to props + }; + // Touch + // ---------------------------------------------------------------------------------------------------- + this.handleTouchStart = function (ev) { + if (_this.tryStart(ev)) { + _this.isTouchDragging = true; + var pev = _this.createEventFromTouch(ev, true); + _this.emitter.trigger('pointerdown', pev); + _this.initScrollWatch(pev); + // unlike mouse, need to attach to target, not document + // https://stackoverflow.com/a/45760014 + var target = ev.target; + if (!_this.shouldIgnoreMove) { + target.addEventListener('touchmove', _this.handleTouchMove); + } + target.addEventListener('touchend', _this.handleTouchEnd); + target.addEventListener('touchcancel', _this.handleTouchEnd); // treat it as a touch end + // attach a handler to get called when ANY scroll action happens on the page. + // this was impossible to do with normal on/off because 'scroll' doesn't bubble. + // http://stackoverflow.com/a/32954565/96342 + window.addEventListener('scroll', _this.handleTouchScroll, true // useCapture + ); + } + }; + this.handleTouchMove = function (ev) { + var pev = _this.createEventFromTouch(ev); + _this.recordCoords(pev); + _this.emitter.trigger('pointermove', pev); + }; + this.handleTouchEnd = function (ev) { + if (_this.isDragging) { // done to guard against touchend followed by touchcancel + var target = ev.target; + target.removeEventListener('touchmove', _this.handleTouchMove); + target.removeEventListener('touchend', _this.handleTouchEnd); + target.removeEventListener('touchcancel', _this.handleTouchEnd); + window.removeEventListener('scroll', _this.handleTouchScroll, true); // useCaptured=true + _this.emitter.trigger('pointerup', _this.createEventFromTouch(ev)); + _this.cleanup(); // call last so that pointerup has access to props + _this.isTouchDragging = false; + startIgnoringMouse(); + } + }; + this.handleTouchScroll = function () { + _this.wasTouchScroll = true; + }; + this.handleScroll = function (ev) { + if (!_this.shouldIgnoreMove) { + var pageX = (window.pageXOffset - _this.prevScrollX) + _this.prevPageX; + var pageY = (window.pageYOffset - _this.prevScrollY) + _this.prevPageY; + _this.emitter.trigger('pointermove', { + origEvent: ev, + isTouch: _this.isTouchDragging, + subjectEl: _this.subjectEl, + pageX: pageX, + pageY: pageY, + deltaX: pageX - _this.origPageX, + deltaY: pageY - _this.origPageY + }); + } + }; + this.containerEl = containerEl; + this.emitter = new core.EmitterMixin(); + containerEl.addEventListener('mousedown', this.handleMouseDown); + containerEl.addEventListener('touchstart', this.handleTouchStart, { passive: true }); + listenerCreated(); + } + PointerDragging.prototype.destroy = function () { + this.containerEl.removeEventListener('mousedown', this.handleMouseDown); + this.containerEl.removeEventListener('touchstart', this.handleTouchStart, { passive: true }); + listenerDestroyed(); + }; + PointerDragging.prototype.tryStart = function (ev) { + var subjectEl = this.querySubjectEl(ev); + var downEl = ev.target; + if (subjectEl && + (!this.handleSelector || core.elementClosest(downEl, this.handleSelector))) { + this.subjectEl = subjectEl; + this.downEl = downEl; + this.isDragging = true; // do this first so cancelTouchScroll will work + this.wasTouchScroll = false; + return true; + } + return false; + }; + PointerDragging.prototype.cleanup = function () { + isWindowTouchMoveCancelled = false; + this.isDragging = false; + this.subjectEl = null; + this.downEl = null; + // keep wasTouchScroll around for later access + this.destroyScrollWatch(); + }; + PointerDragging.prototype.querySubjectEl = function (ev) { + if (this.selector) { + return core.elementClosest(ev.target, this.selector); + } + else { + return this.containerEl; + } + }; + PointerDragging.prototype.shouldIgnoreMouse = function () { + return ignoreMouseDepth || this.isTouchDragging; + }; + // can be called by user of this class, to cancel touch-based scrolling for the current drag + PointerDragging.prototype.cancelTouchScroll = function () { + if (this.isDragging) { + isWindowTouchMoveCancelled = true; + } + }; + // Scrolling that simulates pointermoves + // ---------------------------------------------------------------------------------------------------- + PointerDragging.prototype.initScrollWatch = function (ev) { + if (this.shouldWatchScroll) { + this.recordCoords(ev); + window.addEventListener('scroll', this.handleScroll, true); // useCapture=true + } + }; + PointerDragging.prototype.recordCoords = function (ev) { + if (this.shouldWatchScroll) { + this.prevPageX = ev.pageX; + this.prevPageY = ev.pageY; + this.prevScrollX = window.pageXOffset; + this.prevScrollY = window.pageYOffset; + } + }; + PointerDragging.prototype.destroyScrollWatch = function () { + if (this.shouldWatchScroll) { + window.removeEventListener('scroll', this.handleScroll, true); // useCaptured=true + } + }; + // Event Normalization + // ---------------------------------------------------------------------------------------------------- + PointerDragging.prototype.createEventFromMouse = function (ev, isFirst) { + var deltaX = 0; + var deltaY = 0; + // TODO: repeat code + if (isFirst) { + this.origPageX = ev.pageX; + this.origPageY = ev.pageY; + } + else { + deltaX = ev.pageX - this.origPageX; + deltaY = ev.pageY - this.origPageY; + } + return { + origEvent: ev, + isTouch: false, + subjectEl: this.subjectEl, + pageX: ev.pageX, + pageY: ev.pageY, + deltaX: deltaX, + deltaY: deltaY + }; + }; + PointerDragging.prototype.createEventFromTouch = function (ev, isFirst) { + var touches = ev.touches; + var pageX; + var pageY; + var deltaX = 0; + var deltaY = 0; + // if touch coords available, prefer, + // because FF would give bad ev.pageX ev.pageY + if (touches && touches.length) { + pageX = touches[0].pageX; + pageY = touches[0].pageY; + } + else { + pageX = ev.pageX; + pageY = ev.pageY; + } + // TODO: repeat code + if (isFirst) { + this.origPageX = pageX; + this.origPageY = pageY; + } + else { + deltaX = pageX - this.origPageX; + deltaY = pageY - this.origPageY; + } + return { + origEvent: ev, + isTouch: true, + subjectEl: this.subjectEl, + pageX: pageX, + pageY: pageY, + deltaX: deltaX, + deltaY: deltaY + }; + }; + return PointerDragging; + }()); + // Returns a boolean whether this was a left mouse click and no ctrl key (which means right click on Mac) + function isPrimaryMouseButton(ev) { + return ev.button === 0 && !ev.ctrlKey; + } + // Ignoring fake mouse events generated by touch + // ---------------------------------------------------------------------------------------------------- + function startIgnoringMouse() { + ignoreMouseDepth++; + setTimeout(function () { + ignoreMouseDepth--; + }, core.config.touchMouseIgnoreWait); + } + // We want to attach touchmove as early as possible for Safari + // ---------------------------------------------------------------------------------------------------- + function listenerCreated() { + if (!(listenerCnt++)) { + window.addEventListener('touchmove', onWindowTouchMove, { passive: false }); + } + } + function listenerDestroyed() { + if (!(--listenerCnt)) { + window.removeEventListener('touchmove', onWindowTouchMove, { passive: false }); + } + } + function onWindowTouchMove(ev) { + if (isWindowTouchMoveCancelled) { + ev.preventDefault(); + } + } + + /* + An effect in which an element follows the movement of a pointer across the screen. + The moving element is a clone of some other element. + Must call start + handleMove + stop. + */ + var ElementMirror = /** @class */ (function () { + function ElementMirror() { + this.isVisible = false; // must be explicitly enabled + this.sourceEl = null; + this.mirrorEl = null; + this.sourceElRect = null; // screen coords relative to viewport + // options that can be set directly by caller + this.parentNode = document.body; + this.zIndex = 9999; + this.revertDuration = 0; + } + ElementMirror.prototype.start = function (sourceEl, pageX, pageY) { + this.sourceEl = sourceEl; + this.sourceElRect = this.sourceEl.getBoundingClientRect(); + this.origScreenX = pageX - window.pageXOffset; + this.origScreenY = pageY - window.pageYOffset; + this.deltaX = 0; + this.deltaY = 0; + this.updateElPosition(); + }; + ElementMirror.prototype.handleMove = function (pageX, pageY) { + this.deltaX = (pageX - window.pageXOffset) - this.origScreenX; + this.deltaY = (pageY - window.pageYOffset) - this.origScreenY; + this.updateElPosition(); + }; + // can be called before start + ElementMirror.prototype.setIsVisible = function (bool) { + if (bool) { + if (!this.isVisible) { + if (this.mirrorEl) { + this.mirrorEl.style.display = ''; + } + this.isVisible = bool; // needs to happen before updateElPosition + this.updateElPosition(); // because was not updating the position while invisible + } + } + else { + if (this.isVisible) { + if (this.mirrorEl) { + this.mirrorEl.style.display = 'none'; + } + this.isVisible = bool; + } + } + }; + // always async + ElementMirror.prototype.stop = function (needsRevertAnimation, callback) { + var _this = this; + var done = function () { + _this.cleanup(); + callback(); + }; + if (needsRevertAnimation && + this.mirrorEl && + this.isVisible && + this.revertDuration && // if 0, transition won't work + (this.deltaX || this.deltaY) // if same coords, transition won't work + ) { + this.doRevertAnimation(done, this.revertDuration); + } + else { + setTimeout(done, 0); + } + }; + ElementMirror.prototype.doRevertAnimation = function (callback, revertDuration) { + var mirrorEl = this.mirrorEl; + var finalSourceElRect = this.sourceEl.getBoundingClientRect(); // because autoscrolling might have happened + mirrorEl.style.transition = + 'top ' + revertDuration + 'ms,' + + 'left ' + revertDuration + 'ms'; + core.applyStyle(mirrorEl, { + left: finalSourceElRect.left, + top: finalSourceElRect.top + }); + core.whenTransitionDone(mirrorEl, function () { + mirrorEl.style.transition = ''; + callback(); + }); + }; + ElementMirror.prototype.cleanup = function () { + if (this.mirrorEl) { + core.removeElement(this.mirrorEl); + this.mirrorEl = null; + } + this.sourceEl = null; + }; + ElementMirror.prototype.updateElPosition = function () { + if (this.sourceEl && this.isVisible) { + core.applyStyle(this.getMirrorEl(), { + left: this.sourceElRect.left + this.deltaX, + top: this.sourceElRect.top + this.deltaY + }); + } + }; + ElementMirror.prototype.getMirrorEl = function () { + var sourceElRect = this.sourceElRect; + var mirrorEl = this.mirrorEl; + if (!mirrorEl) { + mirrorEl = this.mirrorEl = this.sourceEl.cloneNode(true); // cloneChildren=true + // we don't want long taps or any mouse interaction causing selection/menus. + // would use preventSelection(), but that prevents selectstart, causing problems. + mirrorEl.classList.add('fc-unselectable'); + mirrorEl.classList.add('fc-dragging'); + core.applyStyle(mirrorEl, { + position: 'fixed', + zIndex: this.zIndex, + visibility: '', + boxSizing: 'border-box', + width: sourceElRect.right - sourceElRect.left, + height: sourceElRect.bottom - sourceElRect.top, + right: 'auto', + bottom: 'auto', + margin: 0 + }); + this.parentNode.appendChild(mirrorEl); + } + return mirrorEl; + }; + return ElementMirror; + }()); + + /* + Is a cache for a given element's scroll information (all the info that ScrollController stores) + in addition the "client rectangle" of the element.. the area within the scrollbars. + + The cache can be in one of two modes: + - doesListening:false - ignores when the container is scrolled by someone else + - doesListening:true - watch for scrolling and update the cache + */ + var ScrollGeomCache = /** @class */ (function (_super) { + __extends(ScrollGeomCache, _super); + function ScrollGeomCache(scrollController, doesListening) { + var _this = _super.call(this) || this; + _this.handleScroll = function () { + _this.scrollTop = _this.scrollController.getScrollTop(); + _this.scrollLeft = _this.scrollController.getScrollLeft(); + _this.handleScrollChange(); + }; + _this.scrollController = scrollController; + _this.doesListening = doesListening; + _this.scrollTop = _this.origScrollTop = scrollController.getScrollTop(); + _this.scrollLeft = _this.origScrollLeft = scrollController.getScrollLeft(); + _this.scrollWidth = scrollController.getScrollWidth(); + _this.scrollHeight = scrollController.getScrollHeight(); + _this.clientWidth = scrollController.getClientWidth(); + _this.clientHeight = scrollController.getClientHeight(); + _this.clientRect = _this.computeClientRect(); // do last in case it needs cached values + if (_this.doesListening) { + _this.getEventTarget().addEventListener('scroll', _this.handleScroll); + } + return _this; + } + ScrollGeomCache.prototype.destroy = function () { + if (this.doesListening) { + this.getEventTarget().removeEventListener('scroll', this.handleScroll); + } + }; + ScrollGeomCache.prototype.getScrollTop = function () { + return this.scrollTop; + }; + ScrollGeomCache.prototype.getScrollLeft = function () { + return this.scrollLeft; + }; + ScrollGeomCache.prototype.setScrollTop = function (top) { + this.scrollController.setScrollTop(top); + if (!this.doesListening) { + // we are not relying on the element to normalize out-of-bounds scroll values + // so we need to sanitize ourselves + this.scrollTop = Math.max(Math.min(top, this.getMaxScrollTop()), 0); + this.handleScrollChange(); + } + }; + ScrollGeomCache.prototype.setScrollLeft = function (top) { + this.scrollController.setScrollLeft(top); + if (!this.doesListening) { + // we are not relying on the element to normalize out-of-bounds scroll values + // so we need to sanitize ourselves + this.scrollLeft = Math.max(Math.min(top, this.getMaxScrollLeft()), 0); + this.handleScrollChange(); + } + }; + ScrollGeomCache.prototype.getClientWidth = function () { + return this.clientWidth; + }; + ScrollGeomCache.prototype.getClientHeight = function () { + return this.clientHeight; + }; + ScrollGeomCache.prototype.getScrollWidth = function () { + return this.scrollWidth; + }; + ScrollGeomCache.prototype.getScrollHeight = function () { + return this.scrollHeight; + }; + ScrollGeomCache.prototype.handleScrollChange = function () { + }; + return ScrollGeomCache; + }(core.ScrollController)); + var ElementScrollGeomCache = /** @class */ (function (_super) { + __extends(ElementScrollGeomCache, _super); + function ElementScrollGeomCache(el, doesListening) { + return _super.call(this, new core.ElementScrollController(el), doesListening) || this; + } + ElementScrollGeomCache.prototype.getEventTarget = function () { + return this.scrollController.el; + }; + ElementScrollGeomCache.prototype.computeClientRect = function () { + return core.computeInnerRect(this.scrollController.el); + }; + return ElementScrollGeomCache; + }(ScrollGeomCache)); + var WindowScrollGeomCache = /** @class */ (function (_super) { + __extends(WindowScrollGeomCache, _super); + function WindowScrollGeomCache(doesListening) { + return _super.call(this, new core.WindowScrollController(), doesListening) || this; + } + WindowScrollGeomCache.prototype.getEventTarget = function () { + return window; + }; + WindowScrollGeomCache.prototype.computeClientRect = function () { + return { + left: this.scrollLeft, + right: this.scrollLeft + this.clientWidth, + top: this.scrollTop, + bottom: this.scrollTop + this.clientHeight + }; + }; + // the window is the only scroll object that changes it's rectangle relative + // to the document's topleft as it scrolls + WindowScrollGeomCache.prototype.handleScrollChange = function () { + this.clientRect = this.computeClientRect(); + }; + return WindowScrollGeomCache; + }(ScrollGeomCache)); + + // If available we are using native "performance" API instead of "Date" + // Read more about it on MDN: + // https://developer.mozilla.org/en-US/docs/Web/API/Performance + var getTime = typeof performance === 'function' ? performance.now : Date.now; + /* + For a pointer interaction, automatically scrolls certain scroll containers when the pointer + approaches the edge. + + The caller must call start + handleMove + stop. + */ + var AutoScroller = /** @class */ (function () { + function AutoScroller() { + var _this = this; + // options that can be set by caller + this.isEnabled = true; + this.scrollQuery = [window, '.fc-scroller']; + this.edgeThreshold = 50; // pixels + this.maxVelocity = 300; // pixels per second + // internal state + this.pointerScreenX = null; + this.pointerScreenY = null; + this.isAnimating = false; + this.scrollCaches = null; + // protect against the initial pointerdown being too close to an edge and starting the scroll + this.everMovedUp = false; + this.everMovedDown = false; + this.everMovedLeft = false; + this.everMovedRight = false; + this.animate = function () { + if (_this.isAnimating) { // wasn't cancelled between animation calls + var edge = _this.computeBestEdge(_this.pointerScreenX + window.pageXOffset, _this.pointerScreenY + window.pageYOffset); + if (edge) { + var now = getTime(); + _this.handleSide(edge, (now - _this.msSinceRequest) / 1000); + _this.requestAnimation(now); + } + else { + _this.isAnimating = false; // will stop animation + } + } + }; + } + AutoScroller.prototype.start = function (pageX, pageY) { + if (this.isEnabled) { + this.scrollCaches = this.buildCaches(); + this.pointerScreenX = null; + this.pointerScreenY = null; + this.everMovedUp = false; + this.everMovedDown = false; + this.everMovedLeft = false; + this.everMovedRight = false; + this.handleMove(pageX, pageY); + } + }; + AutoScroller.prototype.handleMove = function (pageX, pageY) { + if (this.isEnabled) { + var pointerScreenX = pageX - window.pageXOffset; + var pointerScreenY = pageY - window.pageYOffset; + var yDelta = this.pointerScreenY === null ? 0 : pointerScreenY - this.pointerScreenY; + var xDelta = this.pointerScreenX === null ? 0 : pointerScreenX - this.pointerScreenX; + if (yDelta < 0) { + this.everMovedUp = true; + } + else if (yDelta > 0) { + this.everMovedDown = true; + } + if (xDelta < 0) { + this.everMovedLeft = true; + } + else if (xDelta > 0) { + this.everMovedRight = true; + } + this.pointerScreenX = pointerScreenX; + this.pointerScreenY = pointerScreenY; + if (!this.isAnimating) { + this.isAnimating = true; + this.requestAnimation(getTime()); + } + } + }; + AutoScroller.prototype.stop = function () { + if (this.isEnabled) { + this.isAnimating = false; // will stop animation + for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { + var scrollCache = _a[_i]; + scrollCache.destroy(); + } + this.scrollCaches = null; + } + }; + AutoScroller.prototype.requestAnimation = function (now) { + this.msSinceRequest = now; + requestAnimationFrame(this.animate); + }; + AutoScroller.prototype.handleSide = function (edge, seconds) { + var scrollCache = edge.scrollCache; + var edgeThreshold = this.edgeThreshold; + var invDistance = edgeThreshold - edge.distance; + var velocity = // the closer to the edge, the faster we scroll + (invDistance * invDistance) / (edgeThreshold * edgeThreshold) * // quadratic + this.maxVelocity * seconds; + var sign = 1; + switch (edge.name) { + case 'left': + sign = -1; + // falls through + case 'right': + scrollCache.setScrollLeft(scrollCache.getScrollLeft() + velocity * sign); + break; + case 'top': + sign = -1; + // falls through + case 'bottom': + scrollCache.setScrollTop(scrollCache.getScrollTop() + velocity * sign); + break; + } + }; + // left/top are relative to document topleft + AutoScroller.prototype.computeBestEdge = function (left, top) { + var edgeThreshold = this.edgeThreshold; + var bestSide = null; + for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { + var scrollCache = _a[_i]; + var rect = scrollCache.clientRect; + var leftDist = left - rect.left; + var rightDist = rect.right - left; + var topDist = top - rect.top; + var bottomDist = rect.bottom - top; + // completely within the rect? + if (leftDist >= 0 && rightDist >= 0 && topDist >= 0 && bottomDist >= 0) { + if (topDist <= edgeThreshold && this.everMovedUp && scrollCache.canScrollUp() && + (!bestSide || bestSide.distance > topDist)) { + bestSide = { scrollCache: scrollCache, name: 'top', distance: topDist }; + } + if (bottomDist <= edgeThreshold && this.everMovedDown && scrollCache.canScrollDown() && + (!bestSide || bestSide.distance > bottomDist)) { + bestSide = { scrollCache: scrollCache, name: 'bottom', distance: bottomDist }; + } + if (leftDist <= edgeThreshold && this.everMovedLeft && scrollCache.canScrollLeft() && + (!bestSide || bestSide.distance > leftDist)) { + bestSide = { scrollCache: scrollCache, name: 'left', distance: leftDist }; + } + if (rightDist <= edgeThreshold && this.everMovedRight && scrollCache.canScrollRight() && + (!bestSide || bestSide.distance > rightDist)) { + bestSide = { scrollCache: scrollCache, name: 'right', distance: rightDist }; + } + } + } + return bestSide; + }; + AutoScroller.prototype.buildCaches = function () { + return this.queryScrollEls().map(function (el) { + if (el === window) { + return new WindowScrollGeomCache(false); // false = don't listen to user-generated scrolls + } + else { + return new ElementScrollGeomCache(el, false); // false = don't listen to user-generated scrolls + } + }); + }; + AutoScroller.prototype.queryScrollEls = function () { + var els = []; + for (var _i = 0, _a = this.scrollQuery; _i < _a.length; _i++) { + var query = _a[_i]; + if (typeof query === 'object') { + els.push(query); + } + else { + els.push.apply(els, Array.prototype.slice.call(document.querySelectorAll(query))); + } + } + return els; + }; + return AutoScroller; + }()); + + /* + Monitors dragging on an element. Has a number of high-level features: + - minimum distance required before dragging + - minimum wait time ("delay") before dragging + - a mirror element that follows the pointer + */ + var FeaturefulElementDragging = /** @class */ (function (_super) { + __extends(FeaturefulElementDragging, _super); + function FeaturefulElementDragging(containerEl) { + var _this = _super.call(this, containerEl) || this; + // options that can be directly set by caller + // the caller can also set the PointerDragging's options as well + _this.delay = null; + _this.minDistance = 0; + _this.touchScrollAllowed = true; // prevents drag from starting and blocks scrolling during drag + _this.mirrorNeedsRevert = false; + _this.isInteracting = false; // is the user validly moving the pointer? lasts until pointerup + _this.isDragging = false; // is it INTENTFULLY dragging? lasts until after revert animation + _this.isDelayEnded = false; + _this.isDistanceSurpassed = false; + _this.delayTimeoutId = null; + _this.onPointerDown = function (ev) { + if (!_this.isDragging) { // so new drag doesn't happen while revert animation is going + _this.isInteracting = true; + _this.isDelayEnded = false; + _this.isDistanceSurpassed = false; + core.preventSelection(document.body); + core.preventContextMenu(document.body); + // prevent links from being visited if there's an eventual drag. + // also prevents selection in older browsers (maybe?). + // not necessary for touch, besides, browser would complain about passiveness. + if (!ev.isTouch) { + ev.origEvent.preventDefault(); + } + _this.emitter.trigger('pointerdown', ev); + if (!_this.pointer.shouldIgnoreMove) { + // actions related to initiating dragstart+dragmove+dragend... + _this.mirror.setIsVisible(false); // reset. caller must set-visible + _this.mirror.start(ev.subjectEl, ev.pageX, ev.pageY); // must happen on first pointer down + _this.startDelay(ev); + if (!_this.minDistance) { + _this.handleDistanceSurpassed(ev); + } + } + } + }; + _this.onPointerMove = function (ev) { + if (_this.isInteracting) { // if false, still waiting for previous drag's revert + _this.emitter.trigger('pointermove', ev); + if (!_this.isDistanceSurpassed) { + var minDistance = _this.minDistance; + var distanceSq = void 0; // current distance from the origin, squared + var deltaX = ev.deltaX, deltaY = ev.deltaY; + distanceSq = deltaX * deltaX + deltaY * deltaY; + if (distanceSq >= minDistance * minDistance) { // use pythagorean theorem + _this.handleDistanceSurpassed(ev); + } + } + if (_this.isDragging) { + // a real pointer move? (not one simulated by scrolling) + if (ev.origEvent.type !== 'scroll') { + _this.mirror.handleMove(ev.pageX, ev.pageY); + _this.autoScroller.handleMove(ev.pageX, ev.pageY); + } + _this.emitter.trigger('dragmove', ev); + } + } + }; + _this.onPointerUp = function (ev) { + if (_this.isInteracting) { // if false, still waiting for previous drag's revert + _this.isInteracting = false; + core.allowSelection(document.body); + core.allowContextMenu(document.body); + _this.emitter.trigger('pointerup', ev); // can potentially set mirrorNeedsRevert + if (_this.isDragging) { + _this.autoScroller.stop(); + _this.tryStopDrag(ev); // which will stop the mirror + } + if (_this.delayTimeoutId) { + clearTimeout(_this.delayTimeoutId); + _this.delayTimeoutId = null; + } + } + }; + var pointer = _this.pointer = new PointerDragging(containerEl); + pointer.emitter.on('pointerdown', _this.onPointerDown); + pointer.emitter.on('pointermove', _this.onPointerMove); + pointer.emitter.on('pointerup', _this.onPointerUp); + _this.mirror = new ElementMirror(); + _this.autoScroller = new AutoScroller(); + return _this; + } + FeaturefulElementDragging.prototype.destroy = function () { + this.pointer.destroy(); + }; + FeaturefulElementDragging.prototype.startDelay = function (ev) { + var _this = this; + if (typeof this.delay === 'number') { + this.delayTimeoutId = setTimeout(function () { + _this.delayTimeoutId = null; + _this.handleDelayEnd(ev); + }, this.delay); // not assignable to number! + } + else { + this.handleDelayEnd(ev); + } + }; + FeaturefulElementDragging.prototype.handleDelayEnd = function (ev) { + this.isDelayEnded = true; + this.tryStartDrag(ev); + }; + FeaturefulElementDragging.prototype.handleDistanceSurpassed = function (ev) { + this.isDistanceSurpassed = true; + this.tryStartDrag(ev); + }; + FeaturefulElementDragging.prototype.tryStartDrag = function (ev) { + if (this.isDelayEnded && this.isDistanceSurpassed) { + if (!this.pointer.wasTouchScroll || this.touchScrollAllowed) { + this.isDragging = true; + this.mirrorNeedsRevert = false; + this.autoScroller.start(ev.pageX, ev.pageY); + this.emitter.trigger('dragstart', ev); + if (this.touchScrollAllowed === false) { + this.pointer.cancelTouchScroll(); + } + } + } + }; + FeaturefulElementDragging.prototype.tryStopDrag = function (ev) { + // .stop() is ALWAYS asynchronous, which we NEED because we want all pointerup events + // that come from the document to fire beforehand. much more convenient this way. + this.mirror.stop(this.mirrorNeedsRevert, this.stopDrag.bind(this, ev) // bound with args + ); + }; + FeaturefulElementDragging.prototype.stopDrag = function (ev) { + this.isDragging = false; + this.emitter.trigger('dragend', ev); + }; + // fill in the implementations... + FeaturefulElementDragging.prototype.setIgnoreMove = function (bool) { + this.pointer.shouldIgnoreMove = bool; + }; + FeaturefulElementDragging.prototype.setMirrorIsVisible = function (bool) { + this.mirror.setIsVisible(bool); + }; + FeaturefulElementDragging.prototype.setMirrorNeedsRevert = function (bool) { + this.mirrorNeedsRevert = bool; + }; + FeaturefulElementDragging.prototype.setAutoScrollEnabled = function (bool) { + this.autoScroller.isEnabled = bool; + }; + return FeaturefulElementDragging; + }(core.ElementDragging)); + + /* + When this class is instantiated, it records the offset of an element (relative to the document topleft), + and continues to monitor scrolling, updating the cached coordinates if it needs to. + Does not access the DOM after instantiation, so highly performant. + + Also keeps track of all scrolling/overflow:hidden containers that are parents of the given element + and an determine if a given point is inside the combined clipping rectangle. + */ + var OffsetTracker = /** @class */ (function () { + function OffsetTracker(el) { + this.origRect = core.computeRect(el); + // will work fine for divs that have overflow:hidden + this.scrollCaches = core.getClippingParents(el).map(function (el) { + return new ElementScrollGeomCache(el, true); // listen=true + }); + } + OffsetTracker.prototype.destroy = function () { + for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { + var scrollCache = _a[_i]; + scrollCache.destroy(); + } + }; + OffsetTracker.prototype.computeLeft = function () { + var left = this.origRect.left; + for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { + var scrollCache = _a[_i]; + left += scrollCache.origScrollLeft - scrollCache.getScrollLeft(); + } + return left; + }; + OffsetTracker.prototype.computeTop = function () { + var top = this.origRect.top; + for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { + var scrollCache = _a[_i]; + top += scrollCache.origScrollTop - scrollCache.getScrollTop(); + } + return top; + }; + OffsetTracker.prototype.isWithinClipping = function (pageX, pageY) { + var point = { left: pageX, top: pageY }; + for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) { + var scrollCache = _a[_i]; + if (!isIgnoredClipping(scrollCache.getEventTarget()) && + !core.pointInsideRect(point, scrollCache.clientRect)) { + return false; + } + } + return true; + }; + return OffsetTracker; + }()); + // certain clipping containers should never constrain interactions, like <html> and <body> + // https://github.com/fullcalendar/fullcalendar/issues/3615 + function isIgnoredClipping(node) { + var tagName = node.tagName; + return tagName === 'HTML' || tagName === 'BODY'; + } + + /* + Tracks movement over multiple droppable areas (aka "hits") + that exist in one or more DateComponents. + Relies on an existing draggable. + + emits: + - pointerdown + - dragstart + - hitchange - fires initially, even if not over a hit + - pointerup + - (hitchange - again, to null, if ended over a hit) + - dragend + */ + var HitDragging = /** @class */ (function () { + function HitDragging(dragging, droppableStore) { + var _this = this; + // options that can be set by caller + this.useSubjectCenter = false; + this.requireInitial = true; // if doesn't start out on a hit, won't emit any events + this.initialHit = null; + this.movingHit = null; + this.finalHit = null; // won't ever be populated if shouldIgnoreMove + this.handlePointerDown = function (ev) { + var dragging = _this.dragging; + _this.initialHit = null; + _this.movingHit = null; + _this.finalHit = null; + _this.prepareHits(); + _this.processFirstCoord(ev); + if (_this.initialHit || !_this.requireInitial) { + dragging.setIgnoreMove(false); + _this.emitter.trigger('pointerdown', ev); // TODO: fire this before computing processFirstCoord, so listeners can cancel. this gets fired by almost every handler :( + } + else { + dragging.setIgnoreMove(true); + } + }; + this.handleDragStart = function (ev) { + _this.emitter.trigger('dragstart', ev); + _this.handleMove(ev, true); // force = fire even if initially null + }; + this.handleDragMove = function (ev) { + _this.emitter.trigger('dragmove', ev); + _this.handleMove(ev); + }; + this.handlePointerUp = function (ev) { + _this.releaseHits(); + _this.emitter.trigger('pointerup', ev); + }; + this.handleDragEnd = function (ev) { + if (_this.movingHit) { + _this.emitter.trigger('hitupdate', null, true, ev); + } + _this.finalHit = _this.movingHit; + _this.movingHit = null; + _this.emitter.trigger('dragend', ev); + }; + this.droppableStore = droppableStore; + dragging.emitter.on('pointerdown', this.handlePointerDown); + dragging.emitter.on('dragstart', this.handleDragStart); + dragging.emitter.on('dragmove', this.handleDragMove); + dragging.emitter.on('pointerup', this.handlePointerUp); + dragging.emitter.on('dragend', this.handleDragEnd); + this.dragging = dragging; + this.emitter = new core.EmitterMixin(); + } + // sets initialHit + // sets coordAdjust + HitDragging.prototype.processFirstCoord = function (ev) { + var origPoint = { left: ev.pageX, top: ev.pageY }; + var adjustedPoint = origPoint; + var subjectEl = ev.subjectEl; + var subjectRect; + if (subjectEl !== document) { + subjectRect = core.computeRect(subjectEl); + adjustedPoint = core.constrainPoint(adjustedPoint, subjectRect); + } + var initialHit = this.initialHit = this.queryHitForOffset(adjustedPoint.left, adjustedPoint.top); + if (initialHit) { + if (this.useSubjectCenter && subjectRect) { + var slicedSubjectRect = core.intersectRects(subjectRect, initialHit.rect); + if (slicedSubjectRect) { + adjustedPoint = core.getRectCenter(slicedSubjectRect); + } + } + this.coordAdjust = core.diffPoints(adjustedPoint, origPoint); + } + else { + this.coordAdjust = { left: 0, top: 0 }; + } + }; + HitDragging.prototype.handleMove = function (ev, forceHandle) { + var hit = this.queryHitForOffset(ev.pageX + this.coordAdjust.left, ev.pageY + this.coordAdjust.top); + if (forceHandle || !isHitsEqual(this.movingHit, hit)) { + this.movingHit = hit; + this.emitter.trigger('hitupdate', hit, false, ev); + } + }; + HitDragging.prototype.prepareHits = function () { + this.offsetTrackers = core.mapHash(this.droppableStore, function (interactionSettings) { + interactionSettings.component.buildPositionCaches(); + return new OffsetTracker(interactionSettings.el); + }); + }; + HitDragging.prototype.releaseHits = function () { + var offsetTrackers = this.offsetTrackers; + for (var id in offsetTrackers) { + offsetTrackers[id].destroy(); + } + this.offsetTrackers = {}; + }; + HitDragging.prototype.queryHitForOffset = function (offsetLeft, offsetTop) { + var _a = this, droppableStore = _a.droppableStore, offsetTrackers = _a.offsetTrackers; + var bestHit = null; + for (var id in droppableStore) { + var component = droppableStore[id].component; + var offsetTracker = offsetTrackers[id]; + if (offsetTracker.isWithinClipping(offsetLeft, offsetTop)) { + var originLeft = offsetTracker.computeLeft(); + var originTop = offsetTracker.computeTop(); + var positionLeft = offsetLeft - originLeft; + var positionTop = offsetTop - originTop; + var origRect = offsetTracker.origRect; + var width = origRect.right - origRect.left; + var height = origRect.bottom - origRect.top; + if ( + // must be within the element's bounds + positionLeft >= 0 && positionLeft < width && + positionTop >= 0 && positionTop < height) { + var hit = component.queryHit(positionLeft, positionTop, width, height); + if (hit && + ( + // make sure the hit is within activeRange, meaning it's not a deal cell + !component.props.dateProfile || // hack for DayTile + core.rangeContainsRange(component.props.dateProfile.activeRange, hit.dateSpan.range)) && + (!bestHit || hit.layer > bestHit.layer)) { + // TODO: better way to re-orient rectangle + hit.rect.left += originLeft; + hit.rect.right += originLeft; + hit.rect.top += originTop; + hit.rect.bottom += originTop; + bestHit = hit; + } + } + } + } + return bestHit; + }; + return HitDragging; + }()); + function isHitsEqual(hit0, hit1) { + if (!hit0 && !hit1) { + return true; + } + if (Boolean(hit0) !== Boolean(hit1)) { + return false; + } + return core.isDateSpansEqual(hit0.dateSpan, hit1.dateSpan); + } + + /* + Monitors when the user clicks on a specific date/time of a component. + A pointerdown+pointerup on the same "hit" constitutes a click. + */ + var DateClicking = /** @class */ (function (_super) { + __extends(DateClicking, _super); + function DateClicking(settings) { + var _this = _super.call(this, settings) || this; + _this.handlePointerDown = function (ev) { + var dragging = _this.dragging; + // do this in pointerdown (not dragend) because DOM might be mutated by the time dragend is fired + dragging.setIgnoreMove(!_this.component.isValidDateDownEl(dragging.pointer.downEl)); + }; + // won't even fire if moving was ignored + _this.handleDragEnd = function (ev) { + var component = _this.component; + var pointer = _this.dragging.pointer; + if (!pointer.wasTouchScroll) { + var _a = _this.hitDragging, initialHit = _a.initialHit, finalHit = _a.finalHit; + if (initialHit && finalHit && isHitsEqual(initialHit, finalHit)) { + component.calendar.triggerDateClick(initialHit.dateSpan, initialHit.dayEl, component.view, ev.origEvent); + } + } + }; + var component = settings.component; + // we DO want to watch pointer moves because otherwise finalHit won't get populated + _this.dragging = new FeaturefulElementDragging(component.el); + _this.dragging.autoScroller.isEnabled = false; + var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, core.interactionSettingsToStore(settings)); + hitDragging.emitter.on('pointerdown', _this.handlePointerDown); + hitDragging.emitter.on('dragend', _this.handleDragEnd); + return _this; + } + DateClicking.prototype.destroy = function () { + this.dragging.destroy(); + }; + return DateClicking; + }(core.Interaction)); + + /* + Tracks when the user selects a portion of time of a component, + constituted by a drag over date cells, with a possible delay at the beginning of the drag. + */ + var DateSelecting = /** @class */ (function (_super) { + __extends(DateSelecting, _super); + function DateSelecting(settings) { + var _this = _super.call(this, settings) || this; + _this.dragSelection = null; + _this.handlePointerDown = function (ev) { + var _a = _this, component = _a.component, dragging = _a.dragging; + var canSelect = component.opt('selectable') && + component.isValidDateDownEl(ev.origEvent.target); + // don't bother to watch expensive moves if component won't do selection + dragging.setIgnoreMove(!canSelect); + // if touch, require user to hold down + dragging.delay = ev.isTouch ? getComponentTouchDelay(component) : null; + }; + _this.handleDragStart = function (ev) { + _this.component.calendar.unselect(ev); // unselect previous selections + }; + _this.handleHitUpdate = function (hit, isFinal) { + var calendar = _this.component.calendar; + var dragSelection = null; + var isInvalid = false; + if (hit) { + dragSelection = joinHitsIntoSelection(_this.hitDragging.initialHit, hit, calendar.pluginSystem.hooks.dateSelectionTransformers); + if (!dragSelection || !_this.component.isDateSelectionValid(dragSelection)) { + isInvalid = true; + dragSelection = null; + } + } + if (dragSelection) { + calendar.dispatch({ type: 'SELECT_DATES', selection: dragSelection }); + } + else if (!isFinal) { // only unselect if moved away while dragging + calendar.dispatch({ type: 'UNSELECT_DATES' }); + } + if (!isInvalid) { + core.enableCursor(); + } + else { + core.disableCursor(); + } + if (!isFinal) { + _this.dragSelection = dragSelection; // only clear if moved away from all hits while dragging + } + }; + _this.handlePointerUp = function (pev) { + if (_this.dragSelection) { + // selection is already rendered, so just need to report selection + _this.component.calendar.triggerDateSelect(_this.dragSelection, pev); + _this.dragSelection = null; + } + }; + var component = settings.component; + var dragging = _this.dragging = new FeaturefulElementDragging(component.el); + dragging.touchScrollAllowed = false; + dragging.minDistance = component.opt('selectMinDistance') || 0; + dragging.autoScroller.isEnabled = component.opt('dragScroll'); + var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, core.interactionSettingsToStore(settings)); + hitDragging.emitter.on('pointerdown', _this.handlePointerDown); + hitDragging.emitter.on('dragstart', _this.handleDragStart); + hitDragging.emitter.on('hitupdate', _this.handleHitUpdate); + hitDragging.emitter.on('pointerup', _this.handlePointerUp); + return _this; + } + DateSelecting.prototype.destroy = function () { + this.dragging.destroy(); + }; + return DateSelecting; + }(core.Interaction)); + function getComponentTouchDelay(component) { + var delay = component.opt('selectLongPressDelay'); + if (delay == null) { + delay = component.opt('longPressDelay'); + } + return delay; + } + function joinHitsIntoSelection(hit0, hit1, dateSelectionTransformers) { + var dateSpan0 = hit0.dateSpan; + var dateSpan1 = hit1.dateSpan; + var ms = [ + dateSpan0.range.start, + dateSpan0.range.end, + dateSpan1.range.start, + dateSpan1.range.end + ]; + ms.sort(core.compareNumbers); + var props = {}; + for (var _i = 0, dateSelectionTransformers_1 = dateSelectionTransformers; _i < dateSelectionTransformers_1.length; _i++) { + var transformer = dateSelectionTransformers_1[_i]; + var res = transformer(hit0, hit1); + if (res === false) { + return null; + } + else if (res) { + __assign(props, res); + } + } + props.range = { start: ms[0], end: ms[3] }; + props.allDay = dateSpan0.allDay; + return props; + } + + var EventDragging = /** @class */ (function (_super) { + __extends(EventDragging, _super); + function EventDragging(settings) { + var _this = _super.call(this, settings) || this; + // internal state + _this.subjectSeg = null; // the seg being selected/dragged + _this.isDragging = false; + _this.eventRange = null; + _this.relevantEvents = null; // the events being dragged + _this.receivingCalendar = null; + _this.validMutation = null; + _this.mutatedRelevantEvents = null; + _this.handlePointerDown = function (ev) { + var origTarget = ev.origEvent.target; + var _a = _this, component = _a.component, dragging = _a.dragging; + var mirror = dragging.mirror; + var initialCalendar = component.calendar; + var subjectSeg = _this.subjectSeg = core.getElSeg(ev.subjectEl); + var eventRange = _this.eventRange = subjectSeg.eventRange; + var eventInstanceId = eventRange.instance.instanceId; + _this.relevantEvents = core.getRelevantEvents(initialCalendar.state.eventStore, eventInstanceId); + dragging.minDistance = ev.isTouch ? 0 : component.opt('eventDragMinDistance'); + dragging.delay = + // only do a touch delay if touch and this event hasn't been selected yet + (ev.isTouch && eventInstanceId !== component.props.eventSelection) ? + getComponentTouchDelay$1(component) : + null; + mirror.parentNode = initialCalendar.el; + mirror.revertDuration = component.opt('dragRevertDuration'); + var isValid = component.isValidSegDownEl(origTarget) && + !core.elementClosest(origTarget, '.fc-resizer'); // NOT on a resizer + dragging.setIgnoreMove(!isValid); + // disable dragging for elements that are resizable (ie, selectable) + // but are not draggable + _this.isDragging = isValid && + ev.subjectEl.classList.contains('fc-draggable'); + }; + _this.handleDragStart = function (ev) { + var initialCalendar = _this.component.calendar; + var eventRange = _this.eventRange; + var eventInstanceId = eventRange.instance.instanceId; + if (ev.isTouch) { + // need to select a different event? + if (eventInstanceId !== _this.component.props.eventSelection) { + initialCalendar.dispatch({ type: 'SELECT_EVENT', eventInstanceId: eventInstanceId }); + } + } + else { + // if now using mouse, but was previous touch interaction, clear selected event + initialCalendar.dispatch({ type: 'UNSELECT_EVENT' }); + } + if (_this.isDragging) { + initialCalendar.unselect(ev); // unselect *date* selection + initialCalendar.publiclyTrigger('eventDragStart', [ + { + el: _this.subjectSeg.el, + event: new core.EventApi(initialCalendar, eventRange.def, eventRange.instance), + jsEvent: ev.origEvent, + view: _this.component.view + } + ]); + } + }; + _this.handleHitUpdate = function (hit, isFinal) { + if (!_this.isDragging) { + return; + } + var relevantEvents = _this.relevantEvents; + var initialHit = _this.hitDragging.initialHit; + var initialCalendar = _this.component.calendar; + // states based on new hit + var receivingCalendar = null; + var mutation = null; + var mutatedRelevantEvents = null; + var isInvalid = false; + var interaction = { + affectedEvents: relevantEvents, + mutatedEvents: core.createEmptyEventStore(), + isEvent: true, + origSeg: _this.subjectSeg + }; + if (hit) { + var receivingComponent = hit.component; + receivingCalendar = receivingComponent.calendar; + if (initialCalendar === receivingCalendar || + receivingComponent.opt('editable') && receivingComponent.opt('droppable')) { + mutation = computeEventMutation(initialHit, hit, receivingCalendar.pluginSystem.hooks.eventDragMutationMassagers); + if (mutation) { + mutatedRelevantEvents = core.applyMutationToEventStore(relevantEvents, receivingCalendar.eventUiBases, mutation, receivingCalendar); + interaction.mutatedEvents = mutatedRelevantEvents; + if (!receivingComponent.isInteractionValid(interaction)) { + isInvalid = true; + mutation = null; + mutatedRelevantEvents = null; + interaction.mutatedEvents = core.createEmptyEventStore(); + } + } + } + else { + receivingCalendar = null; + } + } + _this.displayDrag(receivingCalendar, interaction); + if (!isInvalid) { + core.enableCursor(); + } + else { + core.disableCursor(); + } + if (!isFinal) { + if (initialCalendar === receivingCalendar && // TODO: write test for this + isHitsEqual(initialHit, hit)) { + mutation = null; + } + _this.dragging.setMirrorNeedsRevert(!mutation); + // render the mirror if no already-rendered mirror + // TODO: wish we could somehow wait for dispatch to guarantee render + _this.dragging.setMirrorIsVisible(!hit || !document.querySelector('.fc-mirror')); + // assign states based on new hit + _this.receivingCalendar = receivingCalendar; + _this.validMutation = mutation; + _this.mutatedRelevantEvents = mutatedRelevantEvents; + } + }; + _this.handlePointerUp = function () { + if (!_this.isDragging) { + _this.cleanup(); // because handleDragEnd won't fire + } + }; + _this.handleDragEnd = function (ev) { + if (_this.isDragging) { + var initialCalendar_1 = _this.component.calendar; + var initialView = _this.component.view; + var _a = _this, receivingCalendar = _a.receivingCalendar, validMutation = _a.validMutation; + var eventDef = _this.eventRange.def; + var eventInstance = _this.eventRange.instance; + var eventApi = new core.EventApi(initialCalendar_1, eventDef, eventInstance); + var relevantEvents_1 = _this.relevantEvents; + var mutatedRelevantEvents = _this.mutatedRelevantEvents; + var finalHit = _this.hitDragging.finalHit; + _this.clearDrag(); // must happen after revert animation + initialCalendar_1.publiclyTrigger('eventDragStop', [ + { + el: _this.subjectSeg.el, + event: eventApi, + jsEvent: ev.origEvent, + view: initialView + } + ]); + if (validMutation) { + // dropped within same calendar + if (receivingCalendar === initialCalendar_1) { + initialCalendar_1.dispatch({ + type: 'MERGE_EVENTS', + eventStore: mutatedRelevantEvents + }); + var transformed = {}; + for (var _i = 0, _b = initialCalendar_1.pluginSystem.hooks.eventDropTransformers; _i < _b.length; _i++) { + var transformer = _b[_i]; + __assign(transformed, transformer(validMutation, initialCalendar_1)); + } + var eventDropArg = __assign({}, transformed, { el: ev.subjectEl, delta: validMutation.datesDelta, oldEvent: eventApi, event: new core.EventApi(// the data AFTER the mutation + initialCalendar_1, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null), revert: function () { + initialCalendar_1.dispatch({ + type: 'MERGE_EVENTS', + eventStore: relevantEvents_1 + }); + }, jsEvent: ev.origEvent, view: initialView }); + initialCalendar_1.publiclyTrigger('eventDrop', [eventDropArg]); + // dropped in different calendar + } + else if (receivingCalendar) { + initialCalendar_1.publiclyTrigger('eventLeave', [ + { + draggedEl: ev.subjectEl, + event: eventApi, + view: initialView + } + ]); + initialCalendar_1.dispatch({ + type: 'REMOVE_EVENT_INSTANCES', + instances: _this.mutatedRelevantEvents.instances + }); + receivingCalendar.dispatch({ + type: 'MERGE_EVENTS', + eventStore: _this.mutatedRelevantEvents + }); + if (ev.isTouch) { + receivingCalendar.dispatch({ + type: 'SELECT_EVENT', + eventInstanceId: eventInstance.instanceId + }); + } + var dropArg = __assign({}, receivingCalendar.buildDatePointApi(finalHit.dateSpan), { draggedEl: ev.subjectEl, jsEvent: ev.origEvent, view: finalHit.component // should this be finalHit.component.view? See #4644 + }); + receivingCalendar.publiclyTrigger('drop', [dropArg]); + receivingCalendar.publiclyTrigger('eventReceive', [ + { + draggedEl: ev.subjectEl, + event: new core.EventApi(// the data AFTER the mutation + receivingCalendar, mutatedRelevantEvents.defs[eventDef.defId], mutatedRelevantEvents.instances[eventInstance.instanceId]), + view: finalHit.component // should this be finalHit.component.view? See #4644 + } + ]); + } + } + else { + initialCalendar_1.publiclyTrigger('_noEventDrop'); + } + } + _this.cleanup(); + }; + var component = _this.component; + var dragging = _this.dragging = new FeaturefulElementDragging(component.el); + dragging.pointer.selector = EventDragging.SELECTOR; + dragging.touchScrollAllowed = false; + dragging.autoScroller.isEnabled = component.opt('dragScroll'); + var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, core.interactionSettingsStore); + hitDragging.useSubjectCenter = settings.useEventCenter; + hitDragging.emitter.on('pointerdown', _this.handlePointerDown); + hitDragging.emitter.on('dragstart', _this.handleDragStart); + hitDragging.emitter.on('hitupdate', _this.handleHitUpdate); + hitDragging.emitter.on('pointerup', _this.handlePointerUp); + hitDragging.emitter.on('dragend', _this.handleDragEnd); + return _this; + } + EventDragging.prototype.destroy = function () { + this.dragging.destroy(); + }; + // render a drag state on the next receivingCalendar + EventDragging.prototype.displayDrag = function (nextCalendar, state) { + var initialCalendar = this.component.calendar; + var prevCalendar = this.receivingCalendar; + // does the previous calendar need to be cleared? + if (prevCalendar && prevCalendar !== nextCalendar) { + // does the initial calendar need to be cleared? + // if so, don't clear all the way. we still need to to hide the affectedEvents + if (prevCalendar === initialCalendar) { + prevCalendar.dispatch({ + type: 'SET_EVENT_DRAG', + state: { + affectedEvents: state.affectedEvents, + mutatedEvents: core.createEmptyEventStore(), + isEvent: true, + origSeg: state.origSeg + } + }); + // completely clear the old calendar if it wasn't the initial + } + else { + prevCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' }); + } + } + if (nextCalendar) { + nextCalendar.dispatch({ type: 'SET_EVENT_DRAG', state: state }); + } + }; + EventDragging.prototype.clearDrag = function () { + var initialCalendar = this.component.calendar; + var receivingCalendar = this.receivingCalendar; + if (receivingCalendar) { + receivingCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' }); + } + // the initial calendar might have an dummy drag state from displayDrag + if (initialCalendar !== receivingCalendar) { + initialCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' }); + } + }; + EventDragging.prototype.cleanup = function () { + this.subjectSeg = null; + this.isDragging = false; + this.eventRange = null; + this.relevantEvents = null; + this.receivingCalendar = null; + this.validMutation = null; + this.mutatedRelevantEvents = null; + }; + EventDragging.SELECTOR = '.fc-draggable, .fc-resizable'; // TODO: test this in IE11 + return EventDragging; + }(core.Interaction)); + function computeEventMutation(hit0, hit1, massagers) { + var dateSpan0 = hit0.dateSpan; + var dateSpan1 = hit1.dateSpan; + var date0 = dateSpan0.range.start; + var date1 = dateSpan1.range.start; + var standardProps = {}; + if (dateSpan0.allDay !== dateSpan1.allDay) { + standardProps.allDay = dateSpan1.allDay; + standardProps.hasEnd = hit1.component.opt('allDayMaintainDuration'); + if (dateSpan1.allDay) { + // means date1 is already start-of-day, + // but date0 needs to be converted + date0 = core.startOfDay(date0); + } + } + var delta = core.diffDates(date0, date1, hit0.component.dateEnv, hit0.component === hit1.component ? + hit0.component.largeUnit : + null); + if (delta.milliseconds) { // has hours/minutes/seconds + standardProps.allDay = false; + } + var mutation = { + datesDelta: delta, + standardProps: standardProps + }; + for (var _i = 0, massagers_1 = massagers; _i < massagers_1.length; _i++) { + var massager = massagers_1[_i]; + massager(mutation, hit0, hit1); + } + return mutation; + } + function getComponentTouchDelay$1(component) { + var delay = component.opt('eventLongPressDelay'); + if (delay == null) { + delay = component.opt('longPressDelay'); + } + return delay; + } + + var EventDragging$1 = /** @class */ (function (_super) { + __extends(EventDragging, _super); + function EventDragging(settings) { + var _this = _super.call(this, settings) || this; + // internal state + _this.draggingSeg = null; // TODO: rename to resizingSeg? subjectSeg? + _this.eventRange = null; + _this.relevantEvents = null; + _this.validMutation = null; + _this.mutatedRelevantEvents = null; + _this.handlePointerDown = function (ev) { + var component = _this.component; + var seg = _this.querySeg(ev); + var eventRange = _this.eventRange = seg.eventRange; + _this.dragging.minDistance = component.opt('eventDragMinDistance'); + // if touch, need to be working with a selected event + _this.dragging.setIgnoreMove(!_this.component.isValidSegDownEl(ev.origEvent.target) || + (ev.isTouch && _this.component.props.eventSelection !== eventRange.instance.instanceId)); + }; + _this.handleDragStart = function (ev) { + var calendar = _this.component.calendar; + var eventRange = _this.eventRange; + _this.relevantEvents = core.getRelevantEvents(calendar.state.eventStore, _this.eventRange.instance.instanceId); + _this.draggingSeg = _this.querySeg(ev); + calendar.unselect(); + calendar.publiclyTrigger('eventResizeStart', [ + { + el: _this.draggingSeg.el, + event: new core.EventApi(calendar, eventRange.def, eventRange.instance), + jsEvent: ev.origEvent, + view: _this.component.view + } + ]); + }; + _this.handleHitUpdate = function (hit, isFinal, ev) { + var calendar = _this.component.calendar; + var relevantEvents = _this.relevantEvents; + var initialHit = _this.hitDragging.initialHit; + var eventInstance = _this.eventRange.instance; + var mutation = null; + var mutatedRelevantEvents = null; + var isInvalid = false; + var interaction = { + affectedEvents: relevantEvents, + mutatedEvents: core.createEmptyEventStore(), + isEvent: true, + origSeg: _this.draggingSeg + }; + if (hit) { + mutation = computeMutation(initialHit, hit, ev.subjectEl.classList.contains('fc-start-resizer'), eventInstance.range, calendar.pluginSystem.hooks.eventResizeJoinTransforms); + } + if (mutation) { + mutatedRelevantEvents = core.applyMutationToEventStore(relevantEvents, calendar.eventUiBases, mutation, calendar); + interaction.mutatedEvents = mutatedRelevantEvents; + if (!_this.component.isInteractionValid(interaction)) { + isInvalid = true; + mutation = null; + mutatedRelevantEvents = null; + interaction.mutatedEvents = null; + } + } + if (mutatedRelevantEvents) { + calendar.dispatch({ + type: 'SET_EVENT_RESIZE', + state: interaction + }); + } + else { + calendar.dispatch({ type: 'UNSET_EVENT_RESIZE' }); + } + if (!isInvalid) { + core.enableCursor(); + } + else { + core.disableCursor(); + } + if (!isFinal) { + if (mutation && isHitsEqual(initialHit, hit)) { + mutation = null; + } + _this.validMutation = mutation; + _this.mutatedRelevantEvents = mutatedRelevantEvents; + } + }; + _this.handleDragEnd = function (ev) { + var calendar = _this.component.calendar; + var view = _this.component.view; + var eventDef = _this.eventRange.def; + var eventInstance = _this.eventRange.instance; + var eventApi = new core.EventApi(calendar, eventDef, eventInstance); + var relevantEvents = _this.relevantEvents; + var mutatedRelevantEvents = _this.mutatedRelevantEvents; + calendar.publiclyTrigger('eventResizeStop', [ + { + el: _this.draggingSeg.el, + event: eventApi, + jsEvent: ev.origEvent, + view: view + } + ]); + if (_this.validMutation) { + calendar.dispatch({ + type: 'MERGE_EVENTS', + eventStore: mutatedRelevantEvents + }); + calendar.publiclyTrigger('eventResize', [ + { + el: _this.draggingSeg.el, + startDelta: _this.validMutation.startDelta || core.createDuration(0), + endDelta: _this.validMutation.endDelta || core.createDuration(0), + prevEvent: eventApi, + event: new core.EventApi(// the data AFTER the mutation + calendar, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null), + revert: function () { + calendar.dispatch({ + type: 'MERGE_EVENTS', + eventStore: relevantEvents + }); + }, + jsEvent: ev.origEvent, + view: view + } + ]); + } + else { + calendar.publiclyTrigger('_noEventResize'); + } + // reset all internal state + _this.draggingSeg = null; + _this.relevantEvents = null; + _this.validMutation = null; + // okay to keep eventInstance around. useful to set it in handlePointerDown + }; + var component = settings.component; + var dragging = _this.dragging = new FeaturefulElementDragging(component.el); + dragging.pointer.selector = '.fc-resizer'; + dragging.touchScrollAllowed = false; + dragging.autoScroller.isEnabled = component.opt('dragScroll'); + var hitDragging = _this.hitDragging = new HitDragging(_this.dragging, core.interactionSettingsToStore(settings)); + hitDragging.emitter.on('pointerdown', _this.handlePointerDown); + hitDragging.emitter.on('dragstart', _this.handleDragStart); + hitDragging.emitter.on('hitupdate', _this.handleHitUpdate); + hitDragging.emitter.on('dragend', _this.handleDragEnd); + return _this; + } + EventDragging.prototype.destroy = function () { + this.dragging.destroy(); + }; + EventDragging.prototype.querySeg = function (ev) { + return core.getElSeg(core.elementClosest(ev.subjectEl, this.component.fgSegSelector)); + }; + return EventDragging; + }(core.Interaction)); + function computeMutation(hit0, hit1, isFromStart, instanceRange, transforms) { + var dateEnv = hit0.component.dateEnv; + var date0 = hit0.dateSpan.range.start; + var date1 = hit1.dateSpan.range.start; + var delta = core.diffDates(date0, date1, dateEnv, hit0.component.largeUnit); + var props = {}; + for (var _i = 0, transforms_1 = transforms; _i < transforms_1.length; _i++) { + var transform = transforms_1[_i]; + var res = transform(hit0, hit1); + if (res === false) { + return null; + } + else if (res) { + __assign(props, res); + } + } + if (isFromStart) { + if (dateEnv.add(instanceRange.start, delta) < instanceRange.end) { + props.startDelta = delta; + return props; + } + } + else { + if (dateEnv.add(instanceRange.end, delta) > instanceRange.start) { + props.endDelta = delta; + return props; + } + } + return null; + } + + var UnselectAuto = /** @class */ (function () { + function UnselectAuto(calendar) { + var _this = this; + this.isRecentPointerDateSelect = false; // wish we could use a selector to detect date selection, but uses hit system + this.onSelect = function (selectInfo) { + if (selectInfo.jsEvent) { + _this.isRecentPointerDateSelect = true; + } + }; + this.onDocumentPointerUp = function (pev) { + var _a = _this, calendar = _a.calendar, documentPointer = _a.documentPointer; + var state = calendar.state; + // touch-scrolling should never unfocus any type of selection + if (!documentPointer.wasTouchScroll) { + if (state.dateSelection && // an existing date selection? + !_this.isRecentPointerDateSelect // a new pointer-initiated date selection since last onDocumentPointerUp? + ) { + var unselectAuto = calendar.viewOpt('unselectAuto'); + var unselectCancel = calendar.viewOpt('unselectCancel'); + if (unselectAuto && (!unselectAuto || !core.elementClosest(documentPointer.downEl, unselectCancel))) { + calendar.unselect(pev); + } + } + if (state.eventSelection && // an existing event selected? + !core.elementClosest(documentPointer.downEl, EventDragging.SELECTOR) // interaction DIDN'T start on an event + ) { + calendar.dispatch({ type: 'UNSELECT_EVENT' }); + } + } + _this.isRecentPointerDateSelect = false; + }; + this.calendar = calendar; + var documentPointer = this.documentPointer = new PointerDragging(document); + documentPointer.shouldIgnoreMove = true; + documentPointer.shouldWatchScroll = false; + documentPointer.emitter.on('pointerup', this.onDocumentPointerUp); + /* + TODO: better way to know about whether there was a selection with the pointer + */ + calendar.on('select', this.onSelect); + } + UnselectAuto.prototype.destroy = function () { + this.calendar.off('select', this.onSelect); + this.documentPointer.destroy(); + }; + return UnselectAuto; + }()); + + /* + Given an already instantiated draggable object for one-or-more elements, + Interprets any dragging as an attempt to drag an events that lives outside + of a calendar onto a calendar. + */ + var ExternalElementDragging = /** @class */ (function () { + function ExternalElementDragging(dragging, suppliedDragMeta) { + var _this = this; + this.receivingCalendar = null; + this.droppableEvent = null; // will exist for all drags, even if create:false + this.suppliedDragMeta = null; + this.dragMeta = null; + this.handleDragStart = function (ev) { + _this.dragMeta = _this.buildDragMeta(ev.subjectEl); + }; + this.handleHitUpdate = function (hit, isFinal, ev) { + var dragging = _this.hitDragging.dragging; + var receivingCalendar = null; + var droppableEvent = null; + var isInvalid = false; + var interaction = { + affectedEvents: core.createEmptyEventStore(), + mutatedEvents: core.createEmptyEventStore(), + isEvent: _this.dragMeta.create, + origSeg: null + }; + if (hit) { + receivingCalendar = hit.component.calendar; + if (_this.canDropElOnCalendar(ev.subjectEl, receivingCalendar)) { + droppableEvent = computeEventForDateSpan(hit.dateSpan, _this.dragMeta, receivingCalendar); + interaction.mutatedEvents = core.eventTupleToStore(droppableEvent); + isInvalid = !core.isInteractionValid(interaction, receivingCalendar); + if (isInvalid) { + interaction.mutatedEvents = core.createEmptyEventStore(); + droppableEvent = null; + } + } + } + _this.displayDrag(receivingCalendar, interaction); + // show mirror if no already-rendered mirror element OR if we are shutting down the mirror (?) + // TODO: wish we could somehow wait for dispatch to guarantee render + dragging.setMirrorIsVisible(isFinal || !droppableEvent || !document.querySelector('.fc-mirror')); + if (!isInvalid) { + core.enableCursor(); + } + else { + core.disableCursor(); + } + if (!isFinal) { + dragging.setMirrorNeedsRevert(!droppableEvent); + _this.receivingCalendar = receivingCalendar; + _this.droppableEvent = droppableEvent; + } + }; + this.handleDragEnd = function (pev) { + var _a = _this, receivingCalendar = _a.receivingCalendar, droppableEvent = _a.droppableEvent; + _this.clearDrag(); + if (receivingCalendar && droppableEvent) { + var finalHit = _this.hitDragging.finalHit; + var finalView = finalHit.component.view; + var dragMeta = _this.dragMeta; + var arg = __assign({}, receivingCalendar.buildDatePointApi(finalHit.dateSpan), { draggedEl: pev.subjectEl, jsEvent: pev.origEvent, view: finalView }); + receivingCalendar.publiclyTrigger('drop', [arg]); + if (dragMeta.create) { + receivingCalendar.dispatch({ + type: 'MERGE_EVENTS', + eventStore: core.eventTupleToStore(droppableEvent) + }); + if (pev.isTouch) { + receivingCalendar.dispatch({ + type: 'SELECT_EVENT', + eventInstanceId: droppableEvent.instance.instanceId + }); + } + // signal that an external event landed + receivingCalendar.publiclyTrigger('eventReceive', [ + { + draggedEl: pev.subjectEl, + event: new core.EventApi(receivingCalendar, droppableEvent.def, droppableEvent.instance), + view: finalView + } + ]); + } + } + _this.receivingCalendar = null; + _this.droppableEvent = null; + }; + var hitDragging = this.hitDragging = new HitDragging(dragging, core.interactionSettingsStore); + hitDragging.requireInitial = false; // will start outside of a component + hitDragging.emitter.on('dragstart', this.handleDragStart); + hitDragging.emitter.on('hitupdate', this.handleHitUpdate); + hitDragging.emitter.on('dragend', this.handleDragEnd); + this.suppliedDragMeta = suppliedDragMeta; + } + ExternalElementDragging.prototype.buildDragMeta = function (subjectEl) { + if (typeof this.suppliedDragMeta === 'object') { + return core.parseDragMeta(this.suppliedDragMeta); + } + else if (typeof this.suppliedDragMeta === 'function') { + return core.parseDragMeta(this.suppliedDragMeta(subjectEl)); + } + else { + return getDragMetaFromEl(subjectEl); + } + }; + ExternalElementDragging.prototype.displayDrag = function (nextCalendar, state) { + var prevCalendar = this.receivingCalendar; + if (prevCalendar && prevCalendar !== nextCalendar) { + prevCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' }); + } + if (nextCalendar) { + nextCalendar.dispatch({ type: 'SET_EVENT_DRAG', state: state }); + } + }; + ExternalElementDragging.prototype.clearDrag = function () { + if (this.receivingCalendar) { + this.receivingCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' }); + } + }; + ExternalElementDragging.prototype.canDropElOnCalendar = function (el, receivingCalendar) { + var dropAccept = receivingCalendar.opt('dropAccept'); + if (typeof dropAccept === 'function') { + return dropAccept(el); + } + else if (typeof dropAccept === 'string' && dropAccept) { + return Boolean(core.elementMatches(el, dropAccept)); + } + return true; + }; + return ExternalElementDragging; + }()); + // Utils for computing event store from the DragMeta + // ---------------------------------------------------------------------------------------------------- + function computeEventForDateSpan(dateSpan, dragMeta, calendar) { + var defProps = __assign({}, dragMeta.leftoverProps); + for (var _i = 0, _a = calendar.pluginSystem.hooks.externalDefTransforms; _i < _a.length; _i++) { + var transform = _a[_i]; + __assign(defProps, transform(dateSpan, dragMeta)); + } + var def = core.parseEventDef(defProps, dragMeta.sourceId, dateSpan.allDay, calendar.opt('forceEventDuration') || Boolean(dragMeta.duration), // hasEnd + calendar); + var start = dateSpan.range.start; + // only rely on time info if drop zone is all-day, + // otherwise, we already know the time + if (dateSpan.allDay && dragMeta.startTime) { + start = calendar.dateEnv.add(start, dragMeta.startTime); + } + var end = dragMeta.duration ? + calendar.dateEnv.add(start, dragMeta.duration) : + calendar.getDefaultEventEnd(dateSpan.allDay, start); + var instance = core.createEventInstance(def.defId, { start: start, end: end }); + return { def: def, instance: instance }; + } + // Utils for extracting data from element + // ---------------------------------------------------------------------------------------------------- + function getDragMetaFromEl(el) { + var str = getEmbeddedElData(el, 'event'); + var obj = str ? + JSON.parse(str) : + { create: false }; // if no embedded data, assume no event creation + return core.parseDragMeta(obj); + } + core.config.dataAttrPrefix = ''; + function getEmbeddedElData(el, name) { + var prefix = core.config.dataAttrPrefix; + var prefixedName = (prefix ? prefix + '-' : '') + name; + return el.getAttribute('data-' + prefixedName) || ''; + } + + /* + Makes an element (that is *external* to any calendar) draggable. + Can pass in data that determines how an event will be created when dropped onto a calendar. + Leverages FullCalendar's internal drag-n-drop functionality WITHOUT a third-party drag system. + */ + var ExternalDraggable = /** @class */ (function () { + function ExternalDraggable(el, settings) { + var _this = this; + if (settings === void 0) { settings = {}; } + this.handlePointerDown = function (ev) { + var dragging = _this.dragging; + var _a = _this.settings, minDistance = _a.minDistance, longPressDelay = _a.longPressDelay; + dragging.minDistance = + minDistance != null ? + minDistance : + (ev.isTouch ? 0 : core.globalDefaults.eventDragMinDistance); + dragging.delay = + ev.isTouch ? // TODO: eventually read eventLongPressDelay instead vvv + (longPressDelay != null ? longPressDelay : core.globalDefaults.longPressDelay) : + 0; + }; + this.handleDragStart = function (ev) { + if (ev.isTouch && + _this.dragging.delay && + ev.subjectEl.classList.contains('fc-event')) { + _this.dragging.mirror.getMirrorEl().classList.add('fc-selected'); + } + }; + this.settings = settings; + var dragging = this.dragging = new FeaturefulElementDragging(el); + dragging.touchScrollAllowed = false; + if (settings.itemSelector != null) { + dragging.pointer.selector = settings.itemSelector; + } + if (settings.appendTo != null) { + dragging.mirror.parentNode = settings.appendTo; // TODO: write tests + } + dragging.emitter.on('pointerdown', this.handlePointerDown); + dragging.emitter.on('dragstart', this.handleDragStart); + new ExternalElementDragging(dragging, settings.eventData); + } + ExternalDraggable.prototype.destroy = function () { + this.dragging.destroy(); + }; + return ExternalDraggable; + }()); + + /* + Detects when a *THIRD-PARTY* drag-n-drop system interacts with elements. + The third-party system is responsible for drawing the visuals effects of the drag. + This class simply monitors for pointer movements and fires events. + It also has the ability to hide the moving element (the "mirror") during the drag. + */ + var InferredElementDragging = /** @class */ (function (_super) { + __extends(InferredElementDragging, _super); + function InferredElementDragging(containerEl) { + var _this = _super.call(this, containerEl) || this; + _this.shouldIgnoreMove = false; + _this.mirrorSelector = ''; + _this.currentMirrorEl = null; + _this.handlePointerDown = function (ev) { + _this.emitter.trigger('pointerdown', ev); + if (!_this.shouldIgnoreMove) { + // fire dragstart right away. does not support delay or min-distance + _this.emitter.trigger('dragstart', ev); + } + }; + _this.handlePointerMove = function (ev) { + if (!_this.shouldIgnoreMove) { + _this.emitter.trigger('dragmove', ev); + } + }; + _this.handlePointerUp = function (ev) { + _this.emitter.trigger('pointerup', ev); + if (!_this.shouldIgnoreMove) { + // fire dragend right away. does not support a revert animation + _this.emitter.trigger('dragend', ev); + } + }; + var pointer = _this.pointer = new PointerDragging(containerEl); + pointer.emitter.on('pointerdown', _this.handlePointerDown); + pointer.emitter.on('pointermove', _this.handlePointerMove); + pointer.emitter.on('pointerup', _this.handlePointerUp); + return _this; + } + InferredElementDragging.prototype.destroy = function () { + this.pointer.destroy(); + }; + InferredElementDragging.prototype.setIgnoreMove = function (bool) { + this.shouldIgnoreMove = bool; + }; + InferredElementDragging.prototype.setMirrorIsVisible = function (bool) { + if (bool) { + // restore a previously hidden element. + // use the reference in case the selector class has already been removed. + if (this.currentMirrorEl) { + this.currentMirrorEl.style.visibility = ''; + this.currentMirrorEl = null; + } + } + else { + var mirrorEl = this.mirrorSelector ? + document.querySelector(this.mirrorSelector) : + null; + if (mirrorEl) { + this.currentMirrorEl = mirrorEl; + mirrorEl.style.visibility = 'hidden'; + } + } + }; + return InferredElementDragging; + }(core.ElementDragging)); + + /* + Bridges third-party drag-n-drop systems with FullCalendar. + Must be instantiated and destroyed by caller. + */ + var ThirdPartyDraggable = /** @class */ (function () { + function ThirdPartyDraggable(containerOrSettings, settings) { + var containerEl = document; + if ( + // wish we could just test instanceof EventTarget, but doesn't work in IE11 + containerOrSettings === document || + containerOrSettings instanceof Element) { + containerEl = containerOrSettings; + settings = settings || {}; + } + else { + settings = (containerOrSettings || {}); + } + var dragging = this.dragging = new InferredElementDragging(containerEl); + if (typeof settings.itemSelector === 'string') { + dragging.pointer.selector = settings.itemSelector; + } + else if (containerEl === document) { + dragging.pointer.selector = '[data-event]'; + } + if (typeof settings.mirrorSelector === 'string') { + dragging.mirrorSelector = settings.mirrorSelector; + } + new ExternalElementDragging(dragging, settings.eventData); + } + ThirdPartyDraggable.prototype.destroy = function () { + this.dragging.destroy(); + }; + return ThirdPartyDraggable; + }()); + + var main = core.createPlugin({ + componentInteractions: [DateClicking, DateSelecting, EventDragging, EventDragging$1], + calendarInteractions: [UnselectAuto], + elementDraggingImpl: FeaturefulElementDragging + }); + + exports.Draggable = ExternalDraggable; + exports.FeaturefulElementDragging = FeaturefulElementDragging; + exports.PointerDragging = PointerDragging; + exports.ThirdPartyDraggable = ThirdPartyDraggable; + exports.default = main; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/interaction/main.min.js b/AKPlan/static/AKPlan/fullcalendar/interaction/main.min.js new file mode 100644 index 00000000..7a36731f --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/interaction/main.min.js @@ -0,0 +1,6 @@ +/*! +FullCalendar Interaction Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@fullcalendar/core")):"function"==typeof define&&define.amd?define(["exports","@fullcalendar/core"],t):t((e=e||self).FullCalendarInteraction={},e.FullCalendar)}(this,function(e,t){"use strict";var n=function(e,t){return(n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)};function r(e,t){function r(){this.constructor=e}n(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}var i=function(){return(i=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)};t.config.touchMouseIgnoreWait=500;var o=0,a=0,l=!1,s=function(){function e(e){var n=this;this.subjectEl=null,this.downEl=null,this.selector="",this.handleSelector="",this.shouldIgnoreMove=!1,this.shouldWatchScroll=!0,this.isDragging=!1,this.isTouchDragging=!1,this.wasTouchScroll=!1,this.handleMouseDown=function(e){if(!n.shouldIgnoreMouse()&&function(e){return 0===e.button&&!e.ctrlKey}(e)&&n.tryStart(e)){var t=n.createEventFromMouse(e,!0);n.emitter.trigger("pointerdown",t),n.initScrollWatch(t),n.shouldIgnoreMove||document.addEventListener("mousemove",n.handleMouseMove),document.addEventListener("mouseup",n.handleMouseUp)}},this.handleMouseMove=function(e){var t=n.createEventFromMouse(e);n.recordCoords(t),n.emitter.trigger("pointermove",t)},this.handleMouseUp=function(e){document.removeEventListener("mousemove",n.handleMouseMove),document.removeEventListener("mouseup",n.handleMouseUp),n.emitter.trigger("pointerup",n.createEventFromMouse(e)),n.cleanup()},this.handleTouchStart=function(e){if(n.tryStart(e)){n.isTouchDragging=!0;var t=n.createEventFromTouch(e,!0);n.emitter.trigger("pointerdown",t),n.initScrollWatch(t);var r=e.target;n.shouldIgnoreMove||r.addEventListener("touchmove",n.handleTouchMove),r.addEventListener("touchend",n.handleTouchEnd),r.addEventListener("touchcancel",n.handleTouchEnd),window.addEventListener("scroll",n.handleTouchScroll,!0)}},this.handleTouchMove=function(e){var t=n.createEventFromTouch(e);n.recordCoords(t),n.emitter.trigger("pointermove",t)},this.handleTouchEnd=function(e){if(n.isDragging){var r=e.target;r.removeEventListener("touchmove",n.handleTouchMove),r.removeEventListener("touchend",n.handleTouchEnd),r.removeEventListener("touchcancel",n.handleTouchEnd),window.removeEventListener("scroll",n.handleTouchScroll,!0),n.emitter.trigger("pointerup",n.createEventFromTouch(e)),n.cleanup(),n.isTouchDragging=!1,o++,setTimeout(function(){o--},t.config.touchMouseIgnoreWait)}},this.handleTouchScroll=function(){n.wasTouchScroll=!0},this.handleScroll=function(e){if(!n.shouldIgnoreMove){var t=window.pageXOffset-n.prevScrollX+n.prevPageX,r=window.pageYOffset-n.prevScrollY+n.prevPageY;n.emitter.trigger("pointermove",{origEvent:e,isTouch:n.isTouchDragging,subjectEl:n.subjectEl,pageX:t,pageY:r,deltaX:t-n.origPageX,deltaY:r-n.origPageY})}},this.containerEl=e,this.emitter=new t.EmitterMixin,e.addEventListener("mousedown",this.handleMouseDown),e.addEventListener("touchstart",this.handleTouchStart,{passive:!0}),a++||window.addEventListener("touchmove",c,{passive:!1})}return e.prototype.destroy=function(){this.containerEl.removeEventListener("mousedown",this.handleMouseDown),this.containerEl.removeEventListener("touchstart",this.handleTouchStart,{passive:!0}),--a||window.removeEventListener("touchmove",c,{passive:!1})},e.prototype.tryStart=function(e){var n=this.querySubjectEl(e),r=e.target;return!(!n||this.handleSelector&&!t.elementClosest(r,this.handleSelector))&&(this.subjectEl=n,this.downEl=r,this.isDragging=!0,this.wasTouchScroll=!1,!0)},e.prototype.cleanup=function(){l=!1,this.isDragging=!1,this.subjectEl=null,this.downEl=null,this.destroyScrollWatch()},e.prototype.querySubjectEl=function(e){return this.selector?t.elementClosest(e.target,this.selector):this.containerEl},e.prototype.shouldIgnoreMouse=function(){return o||this.isTouchDragging},e.prototype.cancelTouchScroll=function(){this.isDragging&&(l=!0)},e.prototype.initScrollWatch=function(e){this.shouldWatchScroll&&(this.recordCoords(e),window.addEventListener("scroll",this.handleScroll,!0))},e.prototype.recordCoords=function(e){this.shouldWatchScroll&&(this.prevPageX=e.pageX,this.prevPageY=e.pageY,this.prevScrollX=window.pageXOffset,this.prevScrollY=window.pageYOffset)},e.prototype.destroyScrollWatch=function(){this.shouldWatchScroll&&window.removeEventListener("scroll",this.handleScroll,!0)},e.prototype.createEventFromMouse=function(e,t){var n=0,r=0;return t?(this.origPageX=e.pageX,this.origPageY=e.pageY):(n=e.pageX-this.origPageX,r=e.pageY-this.origPageY),{origEvent:e,isTouch:!1,subjectEl:this.subjectEl,pageX:e.pageX,pageY:e.pageY,deltaX:n,deltaY:r}},e.prototype.createEventFromTouch=function(e,t){var n,r,i=e.touches,o=0,a=0;return i&&i.length?(n=i[0].pageX,r=i[0].pageY):(n=e.pageX,r=e.pageY),t?(this.origPageX=n,this.origPageY=r):(o=n-this.origPageX,a=r-this.origPageY),{origEvent:e,isTouch:!0,subjectEl:this.subjectEl,pageX:n,pageY:r,deltaX:o,deltaY:a}},e}();function c(e){l&&e.preventDefault()}var d=function(){function e(){this.isVisible=!1,this.sourceEl=null,this.mirrorEl=null,this.sourceElRect=null,this.parentNode=document.body,this.zIndex=9999,this.revertDuration=0}return e.prototype.start=function(e,t,n){this.sourceEl=e,this.sourceElRect=this.sourceEl.getBoundingClientRect(),this.origScreenX=t-window.pageXOffset,this.origScreenY=n-window.pageYOffset,this.deltaX=0,this.deltaY=0,this.updateElPosition()},e.prototype.handleMove=function(e,t){this.deltaX=e-window.pageXOffset-this.origScreenX,this.deltaY=t-window.pageYOffset-this.origScreenY,this.updateElPosition()},e.prototype.setIsVisible=function(e){e?this.isVisible||(this.mirrorEl&&(this.mirrorEl.style.display=""),this.isVisible=e,this.updateElPosition()):this.isVisible&&(this.mirrorEl&&(this.mirrorEl.style.display="none"),this.isVisible=e)},e.prototype.stop=function(e,t){var n=this,r=function(){n.cleanup(),t()};e&&this.mirrorEl&&this.isVisible&&this.revertDuration&&(this.deltaX||this.deltaY)?this.doRevertAnimation(r,this.revertDuration):setTimeout(r,0)},e.prototype.doRevertAnimation=function(e,n){var r=this.mirrorEl,i=this.sourceEl.getBoundingClientRect();r.style.transition="top "+n+"ms,left "+n+"ms",t.applyStyle(r,{left:i.left,top:i.top}),t.whenTransitionDone(r,function(){r.style.transition="",e()})},e.prototype.cleanup=function(){this.mirrorEl&&(t.removeElement(this.mirrorEl),this.mirrorEl=null),this.sourceEl=null},e.prototype.updateElPosition=function(){this.sourceEl&&this.isVisible&&t.applyStyle(this.getMirrorEl(),{left:this.sourceElRect.left+this.deltaX,top:this.sourceElRect.top+this.deltaY})},e.prototype.getMirrorEl=function(){var e=this.sourceElRect,n=this.mirrorEl;return n||((n=this.mirrorEl=this.sourceEl.cloneNode(!0)).classList.add("fc-unselectable"),n.classList.add("fc-dragging"),t.applyStyle(n,{position:"fixed",zIndex:this.zIndex,visibility:"",boxSizing:"border-box",width:e.right-e.left,height:e.bottom-e.top,right:"auto",bottom:"auto",margin:0}),this.parentNode.appendChild(n)),n},e}(),g=function(e){function t(t,n){var r=e.call(this)||this;return r.handleScroll=function(){r.scrollTop=r.scrollController.getScrollTop(),r.scrollLeft=r.scrollController.getScrollLeft(),r.handleScrollChange()},r.scrollController=t,r.doesListening=n,r.scrollTop=r.origScrollTop=t.getScrollTop(),r.scrollLeft=r.origScrollLeft=t.getScrollLeft(),r.scrollWidth=t.getScrollWidth(),r.scrollHeight=t.getScrollHeight(),r.clientWidth=t.getClientWidth(),r.clientHeight=t.getClientHeight(),r.clientRect=r.computeClientRect(),r.doesListening&&r.getEventTarget().addEventListener("scroll",r.handleScroll),r}return r(t,e),t.prototype.destroy=function(){this.doesListening&&this.getEventTarget().removeEventListener("scroll",this.handleScroll)},t.prototype.getScrollTop=function(){return this.scrollTop},t.prototype.getScrollLeft=function(){return this.scrollLeft},t.prototype.setScrollTop=function(e){this.scrollController.setScrollTop(e),this.doesListening||(this.scrollTop=Math.max(Math.min(e,this.getMaxScrollTop()),0),this.handleScrollChange())},t.prototype.setScrollLeft=function(e){this.scrollController.setScrollLeft(e),this.doesListening||(this.scrollLeft=Math.max(Math.min(e,this.getMaxScrollLeft()),0),this.handleScrollChange())},t.prototype.getClientWidth=function(){return this.clientWidth},t.prototype.getClientHeight=function(){return this.clientHeight},t.prototype.getScrollWidth=function(){return this.scrollWidth},t.prototype.getScrollHeight=function(){return this.scrollHeight},t.prototype.handleScrollChange=function(){},t}(t.ScrollController),u=function(e){function n(n,r){return e.call(this,new t.ElementScrollController(n),r)||this}return r(n,e),n.prototype.getEventTarget=function(){return this.scrollController.el},n.prototype.computeClientRect=function(){return t.computeInnerRect(this.scrollController.el)},n}(g),h=function(e){function n(n){return e.call(this,new t.WindowScrollController,n)||this}return r(n,e),n.prototype.getEventTarget=function(){return window},n.prototype.computeClientRect=function(){return{left:this.scrollLeft,right:this.scrollLeft+this.clientWidth,top:this.scrollTop,bottom:this.scrollTop+this.clientHeight}},n.prototype.handleScrollChange=function(){this.clientRect=this.computeClientRect()},n}(g),p="function"==typeof performance?performance.now:Date.now,v=function(){function e(){var e=this;this.isEnabled=!0,this.scrollQuery=[window,".fc-scroller"],this.edgeThreshold=50,this.maxVelocity=300,this.pointerScreenX=null,this.pointerScreenY=null,this.isAnimating=!1,this.scrollCaches=null,this.everMovedUp=!1,this.everMovedDown=!1,this.everMovedLeft=!1,this.everMovedRight=!1,this.animate=function(){if(e.isAnimating){var t=e.computeBestEdge(e.pointerScreenX+window.pageXOffset,e.pointerScreenY+window.pageYOffset);if(t){var n=p();e.handleSide(t,(n-e.msSinceRequest)/1e3),e.requestAnimation(n)}else e.isAnimating=!1}}}return e.prototype.start=function(e,t){this.isEnabled&&(this.scrollCaches=this.buildCaches(),this.pointerScreenX=null,this.pointerScreenY=null,this.everMovedUp=!1,this.everMovedDown=!1,this.everMovedLeft=!1,this.everMovedRight=!1,this.handleMove(e,t))},e.prototype.handleMove=function(e,t){if(this.isEnabled){var n=e-window.pageXOffset,r=t-window.pageYOffset,i=null===this.pointerScreenY?0:r-this.pointerScreenY,o=null===this.pointerScreenX?0:n-this.pointerScreenX;i<0?this.everMovedUp=!0:i>0&&(this.everMovedDown=!0),o<0?this.everMovedLeft=!0:o>0&&(this.everMovedRight=!0),this.pointerScreenX=n,this.pointerScreenY=r,this.isAnimating||(this.isAnimating=!0,this.requestAnimation(p()))}},e.prototype.stop=function(){if(this.isEnabled){this.isAnimating=!1;for(var e=0,t=this.scrollCaches;e<t.length;e++){t[e].destroy()}this.scrollCaches=null}},e.prototype.requestAnimation=function(e){this.msSinceRequest=e,requestAnimationFrame(this.animate)},e.prototype.handleSide=function(e,t){var n=e.scrollCache,r=this.edgeThreshold,i=r-e.distance,o=i*i/(r*r)*this.maxVelocity*t,a=1;switch(e.name){case"left":a=-1;case"right":n.setScrollLeft(n.getScrollLeft()+o*a);break;case"top":a=-1;case"bottom":n.setScrollTop(n.getScrollTop()+o*a)}},e.prototype.computeBestEdge=function(e,t){for(var n=this.edgeThreshold,r=null,i=0,o=this.scrollCaches;i<o.length;i++){var a=o[i],l=a.clientRect,s=e-l.left,c=l.right-e,d=t-l.top,g=l.bottom-t;s>=0&&c>=0&&d>=0&&g>=0&&(d<=n&&this.everMovedUp&&a.canScrollUp()&&(!r||r.distance>d)&&(r={scrollCache:a,name:"top",distance:d}),g<=n&&this.everMovedDown&&a.canScrollDown()&&(!r||r.distance>g)&&(r={scrollCache:a,name:"bottom",distance:g}),s<=n&&this.everMovedLeft&&a.canScrollLeft()&&(!r||r.distance>s)&&(r={scrollCache:a,name:"left",distance:s}),c<=n&&this.everMovedRight&&a.canScrollRight()&&(!r||r.distance>c)&&(r={scrollCache:a,name:"right",distance:c}))}return r},e.prototype.buildCaches=function(){return this.queryScrollEls().map(function(e){return e===window?new h(!1):new u(e,!1)})},e.prototype.queryScrollEls=function(){for(var e=[],t=0,n=this.scrollQuery;t<n.length;t++){var r=n[t];"object"==typeof r?e.push(r):e.push.apply(e,Array.prototype.slice.call(document.querySelectorAll(r)))}return e},e}(),f=function(e){function n(n){var r=e.call(this,n)||this;r.delay=null,r.minDistance=0,r.touchScrollAllowed=!0,r.mirrorNeedsRevert=!1,r.isInteracting=!1,r.isDragging=!1,r.isDelayEnded=!1,r.isDistanceSurpassed=!1,r.delayTimeoutId=null,r.onPointerDown=function(e){r.isDragging||(r.isInteracting=!0,r.isDelayEnded=!1,r.isDistanceSurpassed=!1,t.preventSelection(document.body),t.preventContextMenu(document.body),e.isTouch||e.origEvent.preventDefault(),r.emitter.trigger("pointerdown",e),r.pointer.shouldIgnoreMove||(r.mirror.setIsVisible(!1),r.mirror.start(e.subjectEl,e.pageX,e.pageY),r.startDelay(e),r.minDistance||r.handleDistanceSurpassed(e)))},r.onPointerMove=function(e){if(r.isInteracting){if(r.emitter.trigger("pointermove",e),!r.isDistanceSurpassed){var t=r.minDistance,n=e.deltaX,i=e.deltaY;n*n+i*i>=t*t&&r.handleDistanceSurpassed(e)}r.isDragging&&("scroll"!==e.origEvent.type&&(r.mirror.handleMove(e.pageX,e.pageY),r.autoScroller.handleMove(e.pageX,e.pageY)),r.emitter.trigger("dragmove",e))}},r.onPointerUp=function(e){r.isInteracting&&(r.isInteracting=!1,t.allowSelection(document.body),t.allowContextMenu(document.body),r.emitter.trigger("pointerup",e),r.isDragging&&(r.autoScroller.stop(),r.tryStopDrag(e)),r.delayTimeoutId&&(clearTimeout(r.delayTimeoutId),r.delayTimeoutId=null))};var i=r.pointer=new s(n);return i.emitter.on("pointerdown",r.onPointerDown),i.emitter.on("pointermove",r.onPointerMove),i.emitter.on("pointerup",r.onPointerUp),r.mirror=new d,r.autoScroller=new v,r}return r(n,e),n.prototype.destroy=function(){this.pointer.destroy()},n.prototype.startDelay=function(e){var t=this;"number"==typeof this.delay?this.delayTimeoutId=setTimeout(function(){t.delayTimeoutId=null,t.handleDelayEnd(e)},this.delay):this.handleDelayEnd(e)},n.prototype.handleDelayEnd=function(e){this.isDelayEnded=!0,this.tryStartDrag(e)},n.prototype.handleDistanceSurpassed=function(e){this.isDistanceSurpassed=!0,this.tryStartDrag(e)},n.prototype.tryStartDrag=function(e){this.isDelayEnded&&this.isDistanceSurpassed&&(this.pointer.wasTouchScroll&&!this.touchScrollAllowed||(this.isDragging=!0,this.mirrorNeedsRevert=!1,this.autoScroller.start(e.pageX,e.pageY),this.emitter.trigger("dragstart",e),!1===this.touchScrollAllowed&&this.pointer.cancelTouchScroll()))},n.prototype.tryStopDrag=function(e){this.mirror.stop(this.mirrorNeedsRevert,this.stopDrag.bind(this,e))},n.prototype.stopDrag=function(e){this.isDragging=!1,this.emitter.trigger("dragend",e)},n.prototype.setIgnoreMove=function(e){this.pointer.shouldIgnoreMove=e},n.prototype.setMirrorIsVisible=function(e){this.mirror.setIsVisible(e)},n.prototype.setMirrorNeedsRevert=function(e){this.mirrorNeedsRevert=e},n.prototype.setAutoScrollEnabled=function(e){this.autoScroller.isEnabled=e},n}(t.ElementDragging),E=function(){function e(e){this.origRect=t.computeRect(e),this.scrollCaches=t.getClippingParents(e).map(function(e){return new u(e,!0)})}return e.prototype.destroy=function(){for(var e=0,t=this.scrollCaches;e<t.length;e++){t[e].destroy()}},e.prototype.computeLeft=function(){for(var e=this.origRect.left,t=0,n=this.scrollCaches;t<n.length;t++){var r=n[t];e+=r.origScrollLeft-r.getScrollLeft()}return e},e.prototype.computeTop=function(){for(var e=this.origRect.top,t=0,n=this.scrollCaches;t<n.length;t++){var r=n[t];e+=r.origScrollTop-r.getScrollTop()}return e},e.prototype.isWithinClipping=function(e,n){for(var r,i,o={left:e,top:n},a=0,l=this.scrollCaches;a<l.length;a++){var s=l[a];if(r=s.getEventTarget(),i=void 0,"HTML"!==(i=r.tagName)&&"BODY"!==i&&!t.pointInsideRect(o,s.clientRect))return!1}return!0},e}();var m=function(){function e(e,n){var r=this;this.useSubjectCenter=!1,this.requireInitial=!0,this.initialHit=null,this.movingHit=null,this.finalHit=null,this.handlePointerDown=function(e){var t=r.dragging;r.initialHit=null,r.movingHit=null,r.finalHit=null,r.prepareHits(),r.processFirstCoord(e),r.initialHit||!r.requireInitial?(t.setIgnoreMove(!1),r.emitter.trigger("pointerdown",e)):t.setIgnoreMove(!0)},this.handleDragStart=function(e){r.emitter.trigger("dragstart",e),r.handleMove(e,!0)},this.handleDragMove=function(e){r.emitter.trigger("dragmove",e),r.handleMove(e)},this.handlePointerUp=function(e){r.releaseHits(),r.emitter.trigger("pointerup",e)},this.handleDragEnd=function(e){r.movingHit&&r.emitter.trigger("hitupdate",null,!0,e),r.finalHit=r.movingHit,r.movingHit=null,r.emitter.trigger("dragend",e)},this.droppableStore=n,e.emitter.on("pointerdown",this.handlePointerDown),e.emitter.on("dragstart",this.handleDragStart),e.emitter.on("dragmove",this.handleDragMove),e.emitter.on("pointerup",this.handlePointerUp),e.emitter.on("dragend",this.handleDragEnd),this.dragging=e,this.emitter=new t.EmitterMixin}return e.prototype.processFirstCoord=function(e){var n,r={left:e.pageX,top:e.pageY},i=r,o=e.subjectEl;o!==document&&(n=t.computeRect(o),i=t.constrainPoint(i,n));var a=this.initialHit=this.queryHitForOffset(i.left,i.top);if(a){if(this.useSubjectCenter&&n){var l=t.intersectRects(n,a.rect);l&&(i=t.getRectCenter(l))}this.coordAdjust=t.diffPoints(i,r)}else this.coordAdjust={left:0,top:0}},e.prototype.handleMove=function(e,t){var n=this.queryHitForOffset(e.pageX+this.coordAdjust.left,e.pageY+this.coordAdjust.top);!t&&S(this.movingHit,n)||(this.movingHit=n,this.emitter.trigger("hitupdate",n,!1,e))},e.prototype.prepareHits=function(){this.offsetTrackers=t.mapHash(this.droppableStore,function(e){return e.component.buildPositionCaches(),new E(e.el)})},e.prototype.releaseHits=function(){var e=this.offsetTrackers;for(var t in e)e[t].destroy();this.offsetTrackers={}},e.prototype.queryHitForOffset=function(e,n){var r=this.droppableStore,i=this.offsetTrackers,o=null;for(var a in r){var l=r[a].component,s=i[a];if(s.isWithinClipping(e,n)){var c=s.computeLeft(),d=s.computeTop(),g=e-c,u=n-d,h=s.origRect,p=h.right-h.left,v=h.bottom-h.top;if(g>=0&&g<p&&u>=0&&u<v){var f=l.queryHit(g,u,p,v);!f||l.props.dateProfile&&!t.rangeContainsRange(l.props.dateProfile.activeRange,f.dateSpan.range)||o&&!(f.layer>o.layer)||(f.rect.left+=c,f.rect.right+=c,f.rect.top+=d,f.rect.bottom+=d,o=f)}}}return o},e}();function S(e,n){return!e&&!n||Boolean(e)===Boolean(n)&&t.isDateSpansEqual(e.dateSpan,n.dateSpan)}var y=function(e){function n(n){var r=e.call(this,n)||this;r.handlePointerDown=function(e){var t=r.dragging;t.setIgnoreMove(!r.component.isValidDateDownEl(t.pointer.downEl))},r.handleDragEnd=function(e){var t=r.component;if(!r.dragging.pointer.wasTouchScroll){var n=r.hitDragging,i=n.initialHit,o=n.finalHit;i&&o&&S(i,o)&&t.calendar.triggerDateClick(i.dateSpan,i.dayEl,t.view,e.origEvent)}};var i=n.component;r.dragging=new f(i.el),r.dragging.autoScroller.isEnabled=!1;var o=r.hitDragging=new m(r.dragging,t.interactionSettingsToStore(n));return o.emitter.on("pointerdown",r.handlePointerDown),o.emitter.on("dragend",r.handleDragEnd),r}return r(n,e),n.prototype.destroy=function(){this.dragging.destroy()},n}(t.Interaction),D=function(e){function n(n){var r=e.call(this,n)||this;r.dragSelection=null,r.handlePointerDown=function(e){var t=r,n=t.component,i=t.dragging,o=n.opt("selectable")&&n.isValidDateDownEl(e.origEvent.target);i.setIgnoreMove(!o),i.delay=e.isTouch?function(e){var t=e.opt("selectLongPressDelay");null==t&&(t=e.opt("longPressDelay"));return t}(n):null},r.handleDragStart=function(e){r.component.calendar.unselect(e)},r.handleHitUpdate=function(e,n){var o=r.component.calendar,a=null,l=!1;e&&((a=function(e,n,r){var o=e.dateSpan,a=n.dateSpan,l=[o.range.start,o.range.end,a.range.start,a.range.end];l.sort(t.compareNumbers);for(var s={},c=0,d=r;c<d.length;c++){var g=d[c],u=g(e,n);if(!1===u)return null;u&&i(s,u)}return s.range={start:l[0],end:l[3]},s.allDay=o.allDay,s}(r.hitDragging.initialHit,e,o.pluginSystem.hooks.dateSelectionTransformers))&&r.component.isDateSelectionValid(a)||(l=!0,a=null)),a?o.dispatch({type:"SELECT_DATES",selection:a}):n||o.dispatch({type:"UNSELECT_DATES"}),l?t.disableCursor():t.enableCursor(),n||(r.dragSelection=a)},r.handlePointerUp=function(e){r.dragSelection&&(r.component.calendar.triggerDateSelect(r.dragSelection,e),r.dragSelection=null)};var o=n.component,a=r.dragging=new f(o.el);a.touchScrollAllowed=!1,a.minDistance=o.opt("selectMinDistance")||0,a.autoScroller.isEnabled=o.opt("dragScroll");var l=r.hitDragging=new m(r.dragging,t.interactionSettingsToStore(n));return l.emitter.on("pointerdown",r.handlePointerDown),l.emitter.on("dragstart",r.handleDragStart),l.emitter.on("hitupdate",r.handleHitUpdate),l.emitter.on("pointerup",r.handlePointerUp),r}return r(n,e),n.prototype.destroy=function(){this.dragging.destroy()},n}(t.Interaction);var w=function(e){function n(r){var o=e.call(this,r)||this;o.subjectSeg=null,o.isDragging=!1,o.eventRange=null,o.relevantEvents=null,o.receivingCalendar=null,o.validMutation=null,o.mutatedRelevantEvents=null,o.handlePointerDown=function(e){var n=e.origEvent.target,r=o,i=r.component,a=r.dragging,l=a.mirror,s=i.calendar,c=o.subjectSeg=t.getElSeg(e.subjectEl),d=(o.eventRange=c.eventRange).instance.instanceId;o.relevantEvents=t.getRelevantEvents(s.state.eventStore,d),a.minDistance=e.isTouch?0:i.opt("eventDragMinDistance"),a.delay=e.isTouch&&d!==i.props.eventSelection?function(e){var t=e.opt("eventLongPressDelay");null==t&&(t=e.opt("longPressDelay"));return t}(i):null,l.parentNode=s.el,l.revertDuration=i.opt("dragRevertDuration");var g=i.isValidSegDownEl(n)&&!t.elementClosest(n,".fc-resizer");a.setIgnoreMove(!g),o.isDragging=g&&e.subjectEl.classList.contains("fc-draggable")},o.handleDragStart=function(e){var n=o.component.calendar,r=o.eventRange,i=r.instance.instanceId;e.isTouch?i!==o.component.props.eventSelection&&n.dispatch({type:"SELECT_EVENT",eventInstanceId:i}):n.dispatch({type:"UNSELECT_EVENT"}),o.isDragging&&(n.unselect(e),n.publiclyTrigger("eventDragStart",[{el:o.subjectSeg.el,event:new t.EventApi(n,r.def,r.instance),jsEvent:e.origEvent,view:o.component.view}]))},o.handleHitUpdate=function(e,n){if(o.isDragging){var r=o.relevantEvents,i=o.hitDragging.initialHit,a=o.component.calendar,l=null,s=null,c=null,d=!1,g={affectedEvents:r,mutatedEvents:t.createEmptyEventStore(),isEvent:!0,origSeg:o.subjectSeg};if(e){var u=e.component;a===(l=u.calendar)||u.opt("editable")&&u.opt("droppable")?(s=function(e,n,r){var i=e.dateSpan,o=n.dateSpan,a=i.range.start,l=o.range.start,s={};i.allDay!==o.allDay&&(s.allDay=o.allDay,s.hasEnd=n.component.opt("allDayMaintainDuration"),o.allDay&&(a=t.startOfDay(a)));var c=t.diffDates(a,l,e.component.dateEnv,e.component===n.component?e.component.largeUnit:null);c.milliseconds&&(s.allDay=!1);for(var d={datesDelta:c,standardProps:s},g=0,u=r;g<u.length;g++){var h=u[g];h(d,e,n)}return d}(i,e,l.pluginSystem.hooks.eventDragMutationMassagers))&&(c=t.applyMutationToEventStore(r,l.eventUiBases,s,l),g.mutatedEvents=c,u.isInteractionValid(g)||(d=!0,s=null,c=null,g.mutatedEvents=t.createEmptyEventStore())):l=null}o.displayDrag(l,g),d?t.disableCursor():t.enableCursor(),n||(a===l&&S(i,e)&&(s=null),o.dragging.setMirrorNeedsRevert(!s),o.dragging.setMirrorIsVisible(!e||!document.querySelector(".fc-mirror")),o.receivingCalendar=l,o.validMutation=s,o.mutatedRelevantEvents=c)}},o.handlePointerUp=function(){o.isDragging||o.cleanup()},o.handleDragEnd=function(e){if(o.isDragging){var n=o.component.calendar,r=o.component.view,a=o,l=a.receivingCalendar,s=a.validMutation,c=o.eventRange.def,d=o.eventRange.instance,g=new t.EventApi(n,c,d),u=o.relevantEvents,h=o.mutatedRelevantEvents,p=o.hitDragging.finalHit;if(o.clearDrag(),n.publiclyTrigger("eventDragStop",[{el:o.subjectSeg.el,event:g,jsEvent:e.origEvent,view:r}]),s){if(l===n){n.dispatch({type:"MERGE_EVENTS",eventStore:h});for(var v={},f=0,E=n.pluginSystem.hooks.eventDropTransformers;f<E.length;f++){var m=E[f];i(v,m(s,n))}var S=i({},v,{el:e.subjectEl,delta:s.datesDelta,oldEvent:g,event:new t.EventApi(n,h.defs[c.defId],d?h.instances[d.instanceId]:null),revert:function(){n.dispatch({type:"MERGE_EVENTS",eventStore:u})},jsEvent:e.origEvent,view:r});n.publiclyTrigger("eventDrop",[S])}else if(l){n.publiclyTrigger("eventLeave",[{draggedEl:e.subjectEl,event:g,view:r}]),n.dispatch({type:"REMOVE_EVENT_INSTANCES",instances:o.mutatedRelevantEvents.instances}),l.dispatch({type:"MERGE_EVENTS",eventStore:o.mutatedRelevantEvents}),e.isTouch&&l.dispatch({type:"SELECT_EVENT",eventInstanceId:d.instanceId});var y=i({},l.buildDatePointApi(p.dateSpan),{draggedEl:e.subjectEl,jsEvent:e.origEvent,view:p.component});l.publiclyTrigger("drop",[y]),l.publiclyTrigger("eventReceive",[{draggedEl:e.subjectEl,event:new t.EventApi(l,h.defs[c.defId],h.instances[d.instanceId]),view:p.component}])}}else n.publiclyTrigger("_noEventDrop")}o.cleanup()};var a=o.component,l=o.dragging=new f(a.el);l.pointer.selector=n.SELECTOR,l.touchScrollAllowed=!1,l.autoScroller.isEnabled=a.opt("dragScroll");var s=o.hitDragging=new m(o.dragging,t.interactionSettingsStore);return s.useSubjectCenter=r.useEventCenter,s.emitter.on("pointerdown",o.handlePointerDown),s.emitter.on("dragstart",o.handleDragStart),s.emitter.on("hitupdate",o.handleHitUpdate),s.emitter.on("pointerup",o.handlePointerUp),s.emitter.on("dragend",o.handleDragEnd),o}return r(n,e),n.prototype.destroy=function(){this.dragging.destroy()},n.prototype.displayDrag=function(e,n){var r=this.component.calendar,i=this.receivingCalendar;i&&i!==e&&(i===r?i.dispatch({type:"SET_EVENT_DRAG",state:{affectedEvents:n.affectedEvents,mutatedEvents:t.createEmptyEventStore(),isEvent:!0,origSeg:n.origSeg}}):i.dispatch({type:"UNSET_EVENT_DRAG"})),e&&e.dispatch({type:"SET_EVENT_DRAG",state:n})},n.prototype.clearDrag=function(){var e=this.component.calendar,t=this.receivingCalendar;t&&t.dispatch({type:"UNSET_EVENT_DRAG"}),e!==t&&e.dispatch({type:"UNSET_EVENT_DRAG"})},n.prototype.cleanup=function(){this.subjectSeg=null,this.isDragging=!1,this.eventRange=null,this.relevantEvents=null,this.receivingCalendar=null,this.validMutation=null,this.mutatedRelevantEvents=null},n.SELECTOR=".fc-draggable, .fc-resizable",n}(t.Interaction);var T=function(e){function n(n){var r=e.call(this,n)||this;r.draggingSeg=null,r.eventRange=null,r.relevantEvents=null,r.validMutation=null,r.mutatedRelevantEvents=null,r.handlePointerDown=function(e){var t=r.component,n=r.querySeg(e),i=r.eventRange=n.eventRange;r.dragging.minDistance=t.opt("eventDragMinDistance"),r.dragging.setIgnoreMove(!r.component.isValidSegDownEl(e.origEvent.target)||e.isTouch&&r.component.props.eventSelection!==i.instance.instanceId)},r.handleDragStart=function(e){var n=r.component.calendar,i=r.eventRange;r.relevantEvents=t.getRelevantEvents(n.state.eventStore,r.eventRange.instance.instanceId),r.draggingSeg=r.querySeg(e),n.unselect(),n.publiclyTrigger("eventResizeStart",[{el:r.draggingSeg.el,event:new t.EventApi(n,i.def,i.instance),jsEvent:e.origEvent,view:r.component.view}])},r.handleHitUpdate=function(e,n,o){var a=r.component.calendar,l=r.relevantEvents,s=r.hitDragging.initialHit,c=r.eventRange.instance,d=null,g=null,u=!1,h={affectedEvents:l,mutatedEvents:t.createEmptyEventStore(),isEvent:!0,origSeg:r.draggingSeg};e&&(d=function(e,n,r,o,a){for(var l=e.component.dateEnv,s=e.dateSpan.range.start,c=n.dateSpan.range.start,d=t.diffDates(s,c,l,e.component.largeUnit),g={},u=0,h=a;u<h.length;u++){var p=h[u],v=p(e,n);if(!1===v)return null;v&&i(g,v)}if(r){if(l.add(o.start,d)<o.end)return g.startDelta=d,g}else if(l.add(o.end,d)>o.start)return g.endDelta=d,g;return null}(s,e,o.subjectEl.classList.contains("fc-start-resizer"),c.range,a.pluginSystem.hooks.eventResizeJoinTransforms)),d&&(g=t.applyMutationToEventStore(l,a.eventUiBases,d,a),h.mutatedEvents=g,r.component.isInteractionValid(h)||(u=!0,d=null,g=null,h.mutatedEvents=null)),g?a.dispatch({type:"SET_EVENT_RESIZE",state:h}):a.dispatch({type:"UNSET_EVENT_RESIZE"}),u?t.disableCursor():t.enableCursor(),n||(d&&S(s,e)&&(d=null),r.validMutation=d,r.mutatedRelevantEvents=g)},r.handleDragEnd=function(e){var n=r.component.calendar,i=r.component.view,o=r.eventRange.def,a=r.eventRange.instance,l=new t.EventApi(n,o,a),s=r.relevantEvents,c=r.mutatedRelevantEvents;n.publiclyTrigger("eventResizeStop",[{el:r.draggingSeg.el,event:l,jsEvent:e.origEvent,view:i}]),r.validMutation?(n.dispatch({type:"MERGE_EVENTS",eventStore:c}),n.publiclyTrigger("eventResize",[{el:r.draggingSeg.el,startDelta:r.validMutation.startDelta||t.createDuration(0),endDelta:r.validMutation.endDelta||t.createDuration(0),prevEvent:l,event:new t.EventApi(n,c.defs[o.defId],a?c.instances[a.instanceId]:null),revert:function(){n.dispatch({type:"MERGE_EVENTS",eventStore:s})},jsEvent:e.origEvent,view:i}])):n.publiclyTrigger("_noEventResize"),r.draggingSeg=null,r.relevantEvents=null,r.validMutation=null};var o=n.component,a=r.dragging=new f(o.el);a.pointer.selector=".fc-resizer",a.touchScrollAllowed=!1,a.autoScroller.isEnabled=o.opt("dragScroll");var l=r.hitDragging=new m(r.dragging,t.interactionSettingsToStore(n));return l.emitter.on("pointerdown",r.handlePointerDown),l.emitter.on("dragstart",r.handleDragStart),l.emitter.on("hitupdate",r.handleHitUpdate),l.emitter.on("dragend",r.handleDragEnd),r}return r(n,e),n.prototype.destroy=function(){this.dragging.destroy()},n.prototype.querySeg=function(e){return t.getElSeg(t.elementClosest(e.subjectEl,this.component.fgSegSelector))},n}(t.Interaction);var M=function(){function e(e){var n=this;this.isRecentPointerDateSelect=!1,this.onSelect=function(e){e.jsEvent&&(n.isRecentPointerDateSelect=!0)},this.onDocumentPointerUp=function(e){var r=n,i=r.calendar,o=r.documentPointer,a=i.state;if(!o.wasTouchScroll){if(a.dateSelection&&!n.isRecentPointerDateSelect){var l=i.viewOpt("unselectAuto"),s=i.viewOpt("unselectCancel");!l||l&&t.elementClosest(o.downEl,s)||i.unselect(e)}a.eventSelection&&!t.elementClosest(o.downEl,w.SELECTOR)&&i.dispatch({type:"UNSELECT_EVENT"})}n.isRecentPointerDateSelect=!1},this.calendar=e;var r=this.documentPointer=new s(document);r.shouldIgnoreMove=!0,r.shouldWatchScroll=!1,r.emitter.on("pointerup",this.onDocumentPointerUp),e.on("select",this.onSelect)}return e.prototype.destroy=function(){this.calendar.off("select",this.onSelect),this.documentPointer.destroy()},e}(),b=function(){function e(e,n){var r=this;this.receivingCalendar=null,this.droppableEvent=null,this.suppliedDragMeta=null,this.dragMeta=null,this.handleDragStart=function(e){r.dragMeta=r.buildDragMeta(e.subjectEl)},this.handleHitUpdate=function(e,n,o){var a=r.hitDragging.dragging,l=null,s=null,c=!1,d={affectedEvents:t.createEmptyEventStore(),mutatedEvents:t.createEmptyEventStore(),isEvent:r.dragMeta.create,origSeg:null};e&&(l=e.component.calendar,r.canDropElOnCalendar(o.subjectEl,l)&&(s=function(e,n,r){for(var o=i({},n.leftoverProps),a=0,l=r.pluginSystem.hooks.externalDefTransforms;a<l.length;a++){var s=l[a];i(o,s(e,n))}var c=t.parseEventDef(o,n.sourceId,e.allDay,r.opt("forceEventDuration")||Boolean(n.duration),r),d=e.range.start;e.allDay&&n.startTime&&(d=r.dateEnv.add(d,n.startTime));var g=n.duration?r.dateEnv.add(d,n.duration):r.getDefaultEventEnd(e.allDay,d),u=t.createEventInstance(c.defId,{start:d,end:g});return{def:c,instance:u}}(e.dateSpan,r.dragMeta,l),d.mutatedEvents=t.eventTupleToStore(s),(c=!t.isInteractionValid(d,l))&&(d.mutatedEvents=t.createEmptyEventStore(),s=null))),r.displayDrag(l,d),a.setMirrorIsVisible(n||!s||!document.querySelector(".fc-mirror")),c?t.disableCursor():t.enableCursor(),n||(a.setMirrorNeedsRevert(!s),r.receivingCalendar=l,r.droppableEvent=s)},this.handleDragEnd=function(e){var n=r,o=n.receivingCalendar,a=n.droppableEvent;if(r.clearDrag(),o&&a){var l=r.hitDragging.finalHit,s=l.component.view,c=r.dragMeta,d=i({},o.buildDatePointApi(l.dateSpan),{draggedEl:e.subjectEl,jsEvent:e.origEvent,view:s});o.publiclyTrigger("drop",[d]),c.create&&(o.dispatch({type:"MERGE_EVENTS",eventStore:t.eventTupleToStore(a)}),e.isTouch&&o.dispatch({type:"SELECT_EVENT",eventInstanceId:a.instance.instanceId}),o.publiclyTrigger("eventReceive",[{draggedEl:e.subjectEl,event:new t.EventApi(o,a.def,a.instance),view:s}]))}r.receivingCalendar=null,r.droppableEvent=null};var o=this.hitDragging=new m(e,t.interactionSettingsStore);o.requireInitial=!1,o.emitter.on("dragstart",this.handleDragStart),o.emitter.on("hitupdate",this.handleHitUpdate),o.emitter.on("dragend",this.handleDragEnd),this.suppliedDragMeta=n}return e.prototype.buildDragMeta=function(e){return"object"==typeof this.suppliedDragMeta?t.parseDragMeta(this.suppliedDragMeta):"function"==typeof this.suppliedDragMeta?t.parseDragMeta(this.suppliedDragMeta(e)):(n=function(e,n){var r=t.config.dataAttrPrefix,i=(r?r+"-":"")+n;return e.getAttribute("data-"+i)||""}(e,"event"),r=n?JSON.parse(n):{create:!1},t.parseDragMeta(r));var n,r},e.prototype.displayDrag=function(e,t){var n=this.receivingCalendar;n&&n!==e&&n.dispatch({type:"UNSET_EVENT_DRAG"}),e&&e.dispatch({type:"SET_EVENT_DRAG",state:t})},e.prototype.clearDrag=function(){this.receivingCalendar&&this.receivingCalendar.dispatch({type:"UNSET_EVENT_DRAG"})},e.prototype.canDropElOnCalendar=function(e,n){var r=n.opt("dropAccept");return"function"==typeof r?r(e):"string"!=typeof r||!r||Boolean(t.elementMatches(e,r))},e}();t.config.dataAttrPrefix="";var C=function(){function e(e,n){var r=this;void 0===n&&(n={}),this.handlePointerDown=function(e){var n=r.dragging,i=r.settings,o=i.minDistance,a=i.longPressDelay;n.minDistance=null!=o?o:e.isTouch?0:t.globalDefaults.eventDragMinDistance,n.delay=e.isTouch?null!=a?a:t.globalDefaults.longPressDelay:0},this.handleDragStart=function(e){e.isTouch&&r.dragging.delay&&e.subjectEl.classList.contains("fc-event")&&r.dragging.mirror.getMirrorEl().classList.add("fc-selected")},this.settings=n;var i=this.dragging=new f(e);i.touchScrollAllowed=!1,null!=n.itemSelector&&(i.pointer.selector=n.itemSelector),null!=n.appendTo&&(i.mirror.parentNode=n.appendTo),i.emitter.on("pointerdown",this.handlePointerDown),i.emitter.on("dragstart",this.handleDragStart),new b(i,n.eventData)}return e.prototype.destroy=function(){this.dragging.destroy()},e}(),R=function(e){function t(t){var n=e.call(this,t)||this;n.shouldIgnoreMove=!1,n.mirrorSelector="",n.currentMirrorEl=null,n.handlePointerDown=function(e){n.emitter.trigger("pointerdown",e),n.shouldIgnoreMove||n.emitter.trigger("dragstart",e)},n.handlePointerMove=function(e){n.shouldIgnoreMove||n.emitter.trigger("dragmove",e)},n.handlePointerUp=function(e){n.emitter.trigger("pointerup",e),n.shouldIgnoreMove||n.emitter.trigger("dragend",e)};var r=n.pointer=new s(t);return r.emitter.on("pointerdown",n.handlePointerDown),r.emitter.on("pointermove",n.handlePointerMove),r.emitter.on("pointerup",n.handlePointerUp),n}return r(t,e),t.prototype.destroy=function(){this.pointer.destroy()},t.prototype.setIgnoreMove=function(e){this.shouldIgnoreMove=e},t.prototype.setMirrorIsVisible=function(e){if(e)this.currentMirrorEl&&(this.currentMirrorEl.style.visibility="",this.currentMirrorEl=null);else{var t=this.mirrorSelector?document.querySelector(this.mirrorSelector):null;t&&(this.currentMirrorEl=t,t.style.visibility="hidden")}},t}(t.ElementDragging),I=function(){function e(e,t){var n=document;e===document||e instanceof Element?(n=e,t=t||{}):t=e||{};var r=this.dragging=new R(n);"string"==typeof t.itemSelector?r.pointer.selector=t.itemSelector:n===document&&(r.pointer.selector="[data-event]"),"string"==typeof t.mirrorSelector&&(r.mirrorSelector=t.mirrorSelector),new b(r,t.eventData)}return e.prototype.destroy=function(){this.dragging.destroy()},e}(),P=t.createPlugin({componentInteractions:[y,D,w,T],calendarInteractions:[M],elementDraggingImpl:f});e.Draggable=C,e.FeaturefulElementDragging=f,e.PointerDragging=s,e.ThirdPartyDraggable=I,e.default=P,Object.defineProperty(e,"__esModule",{value:!0})}); \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/interaction/package.json b/AKPlan/static/AKPlan/fullcalendar/interaction/package.json new file mode 100644 index 00000000..812a7b4e --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/interaction/package.json @@ -0,0 +1,33 @@ +{ + "name": "@fullcalendar/interaction", + "version": "4.3.0", + "title": "FullCalendar Interaction Plugin", + "description": "Provides functionality for event drag-n-drop, resizing, dateClick, and selectable actions", + "keywords": [ + "calendar", + "event", + "full-sized" + ], + "homepage": "https://fullcalendar.io/", + "docs": "https://fullcalendar.io/docs/editable", + "bugs": "https://fullcalendar.io/reporting-bugs", + "repository": { + "type": "git", + "url": "https://github.com/fullcalendar/fullcalendar.git", + "homepage": "https://github.com/fullcalendar/fullcalendar" + }, + "license": "MIT", + "author": { + "name": "Adam Shaw", + "email": "arshaw@arshaw.com", + "url": "http://arshaw.com/" + }, + "copyright": "2019 Adam Shaw", + "peerDependencies": { + "@fullcalendar/core": "~4.3.0" + }, + "main": "main.js", + "module": "main.esm.js", + "unpkg": "main.min.js", + "types": "main.d.ts" +} diff --git a/AKPlan/static/AKPlan/fullcalendar/list/LICENSE.txt b/AKPlan/static/AKPlan/fullcalendar/list/LICENSE.txt new file mode 100644 index 00000000..2149cfbe --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/list/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2019 Adam Shaw + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/AKPlan/static/AKPlan/fullcalendar/list/README.md b/AKPlan/static/AKPlan/fullcalendar/list/README.md new file mode 100644 index 00000000..1122d7f9 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/list/README.md @@ -0,0 +1,8 @@ + +# FullCalendar List View Plugin + +View your events as a bulleted list + +[View the docs »](https://fullcalendar.io/docs/list-view) + +This package was created from the [FullCalendar monorepo »](https://github.com/fullcalendar/fullcalendar) diff --git a/AKPlan/static/AKPlan/fullcalendar/list/main.css b/AKPlan/static/AKPlan/fullcalendar/list/main.css new file mode 100644 index 00000000..6af9bb70 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/list/main.css @@ -0,0 +1,118 @@ +/* List View +--------------------------------------------------------------------------------------------------*/ +/* possibly reusable */ +.fc-event-dot { + display: inline-block; + width: 10px; + height: 10px; + border-radius: 5px; +} + +/* view wrapper */ +.fc-rtl .fc-list-view { + direction: rtl; + /* unlike core views, leverage browser RTL */ +} + +.fc-list-view { + border-width: 1px; + border-style: solid; +} + +/* table resets */ +.fc .fc-list-table { + table-layout: auto; + /* for shrinkwrapping cell content */ +} + +.fc-list-table td { + border-width: 1px 0 0; + padding: 8px 14px; +} + +.fc-list-table tr:first-child td { + border-top-width: 0; +} + +/* day headings with the list */ +.fc-list-heading { + border-bottom-width: 1px; +} + +.fc-list-heading td { + font-weight: bold; +} + +.fc-ltr .fc-list-heading-main { + float: left; +} + +.fc-ltr .fc-list-heading-alt { + float: right; +} + +.fc-rtl .fc-list-heading-main { + float: right; +} + +.fc-rtl .fc-list-heading-alt { + float: left; +} + +/* event list items */ +.fc-list-item.fc-has-url { + cursor: pointer; + /* whole row will be clickable */ +} + +.fc-list-item-marker, +.fc-list-item-time { + white-space: nowrap; + width: 1px; +} + +/* make the dot closer to the event title */ +.fc-ltr .fc-list-item-marker { + padding-right: 0; +} + +.fc-rtl .fc-list-item-marker { + padding-left: 0; +} + +.fc-list-item-title a { + /* every event title cell has an <a> tag */ + text-decoration: none; + color: inherit; +} + +.fc-list-item-title a[href]:hover { + /* hover effect only on titles with hrefs */ + text-decoration: underline; +} + +/* message when no events */ +.fc-list-empty-wrap2 { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; +} + +.fc-list-empty-wrap1 { + width: 100%; + height: 100%; + display: table; +} + +.fc-list-empty { + display: table-cell; + vertical-align: middle; + text-align: center; +} + +.fc-unthemed .fc-list-empty { + /* theme will provide own background */ + background-color: #eee; +} diff --git a/AKPlan/static/AKPlan/fullcalendar/list/main.d.ts b/AKPlan/static/AKPlan/fullcalendar/list/main.d.ts new file mode 100644 index 00000000..78aeb2e1 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/list/main.d.ts @@ -0,0 +1,33 @@ +// Generated by dts-bundle v0.7.3-fork.1 +// Dependencies for this module: +// ../../../../../@fullcalendar/core + +declare module '@fullcalendar/list' { + import ListView from '@fullcalendar/list/ListView'; + export { ListView }; + const _default: import("@fullcalendar/core").PluginDef; + export default _default; +} + +declare module '@fullcalendar/list/ListView' { + import { View, ViewProps, ScrollComponent, DateMarker, DateRange, DateProfileGenerator, ComponentContext, ViewSpec, EventUiHash, EventRenderRange, EventStore, Seg } from '@fullcalendar/core'; + export { ListView as default, ListView }; + class ListView extends View { + scroller: ScrollComponent; + contentEl: HTMLElement; + dayDates: DateMarker[]; + constructor(context: ComponentContext, viewSpec: ViewSpec, dateProfileGenerator: DateProfileGenerator, parentEl: HTMLElement); + render(props: ViewProps): void; + destroy(): void; + updateSize(isResize: any, viewHeight: any, isAuto: any): void; + computeScrollerHeight(viewHeight: any): number; + _eventStoreToSegs(eventStore: EventStore, eventUiBases: EventUiHash, dayRanges: DateRange[]): Seg[]; + eventRangesToSegs(eventRanges: EventRenderRange[], dayRanges: DateRange[]): any[]; + eventRangeToSegs(eventRange: EventRenderRange, dayRanges: DateRange[]): any[]; + renderEmptyMessage(): void; + renderSegList(allSegs: any): void; + groupSegsByDay(segs: any): any[]; + buildDayHeaderRow(dayDate: any): HTMLTableRowElement; + } +} + diff --git a/AKPlan/static/AKPlan/fullcalendar/list/main.esm.js b/AKPlan/static/AKPlan/fullcalendar/list/main.esm.js new file mode 100644 index 00000000..87b9eb2e --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/list/main.esm.js @@ -0,0 +1,335 @@ +/*! +FullCalendar List View Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +import { getAllDayHtml, isMultiDayRange, htmlEscape, FgEventRenderer, memoize, memoizeRendering, ScrollComponent, subtractInnerElHeight, sliceEventStore, intersectRanges, htmlToElement, createFormatter, createElement, buildGotoAnchorHtml, View, startOfDay, addDays, createPlugin } from '@fullcalendar/core'; + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} + +var ListEventRenderer = /** @class */ (function (_super) { + __extends(ListEventRenderer, _super); + function ListEventRenderer(listView) { + var _this = _super.call(this, listView.context) || this; + _this.listView = listView; + return _this; + } + ListEventRenderer.prototype.attachSegs = function (segs) { + if (!segs.length) { + this.listView.renderEmptyMessage(); + } + else { + this.listView.renderSegList(segs); + } + }; + ListEventRenderer.prototype.detachSegs = function () { + }; + // generates the HTML for a single event row + ListEventRenderer.prototype.renderSegHtml = function (seg) { + var _a = this.context, view = _a.view, theme = _a.theme; + var eventRange = seg.eventRange; + var eventDef = eventRange.def; + var eventInstance = eventRange.instance; + var eventUi = eventRange.ui; + var url = eventDef.url; + var classes = ['fc-list-item'].concat(eventUi.classNames); + var bgColor = eventUi.backgroundColor; + var timeHtml; + if (eventDef.allDay) { + timeHtml = getAllDayHtml(view); + } + else if (isMultiDayRange(eventRange.range)) { + if (seg.isStart) { + timeHtml = htmlEscape(this._getTimeText(eventInstance.range.start, seg.end, false // allDay + )); + } + else if (seg.isEnd) { + timeHtml = htmlEscape(this._getTimeText(seg.start, eventInstance.range.end, false // allDay + )); + } + else { // inner segment that lasts the whole day + timeHtml = getAllDayHtml(view); + } + } + else { + // Display the normal time text for the *event's* times + timeHtml = htmlEscape(this.getTimeText(eventRange)); + } + if (url) { + classes.push('fc-has-url'); + } + return '<tr class="' + classes.join(' ') + '">' + + (this.displayEventTime ? + '<td class="fc-list-item-time ' + theme.getClass('widgetContent') + '">' + + (timeHtml || '') + + '</td>' : + '') + + '<td class="fc-list-item-marker ' + theme.getClass('widgetContent') + '">' + + '<span class="fc-event-dot"' + + (bgColor ? + ' style="background-color:' + bgColor + '"' : + '') + + '></span>' + + '</td>' + + '<td class="fc-list-item-title ' + theme.getClass('widgetContent') + '">' + + '<a' + (url ? ' href="' + htmlEscape(url) + '"' : '') + '>' + + htmlEscape(eventDef.title || '') + + '</a>' + + '</td>' + + '</tr>'; + }; + // like "4:00am" + ListEventRenderer.prototype.computeEventTimeFormat = function () { + return { + hour: 'numeric', + minute: '2-digit', + meridiem: 'short' + }; + }; + return ListEventRenderer; +}(FgEventRenderer)); + +/* +Responsible for the scroller, and forwarding event-related actions into the "grid". +*/ +var ListView = /** @class */ (function (_super) { + __extends(ListView, _super); + function ListView(context, viewSpec, dateProfileGenerator, parentEl) { + var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this; + _this.computeDateVars = memoize(computeDateVars); + _this.eventStoreToSegs = memoize(_this._eventStoreToSegs); + var eventRenderer = _this.eventRenderer = new ListEventRenderer(_this); + _this.renderContent = memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer)); + _this.el.classList.add('fc-list-view'); + var listViewClassNames = (_this.theme.getClass('listView') || '').split(' '); // wish we didn't have to do this + for (var _i = 0, listViewClassNames_1 = listViewClassNames; _i < listViewClassNames_1.length; _i++) { + var listViewClassName = listViewClassNames_1[_i]; + if (listViewClassName) { // in case input was empty string + _this.el.classList.add(listViewClassName); + } + } + _this.scroller = new ScrollComponent('hidden', // overflow x + 'auto' // overflow y + ); + _this.el.appendChild(_this.scroller.el); + _this.contentEl = _this.scroller.el; // shortcut + context.calendar.registerInteractiveComponent(_this, { + el: _this.el + // TODO: make aware that it doesn't do Hits + }); + return _this; + } + ListView.prototype.render = function (props) { + var _a = this.computeDateVars(props.dateProfile), dayDates = _a.dayDates, dayRanges = _a.dayRanges; + this.dayDates = dayDates; + this.renderContent(this.eventStoreToSegs(props.eventStore, props.eventUiBases, dayRanges)); + }; + ListView.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.renderContent.unrender(); + this.scroller.destroy(); // will remove the Grid too + this.calendar.unregisterInteractiveComponent(this); + }; + ListView.prototype.updateSize = function (isResize, viewHeight, isAuto) { + _super.prototype.updateSize.call(this, isResize, viewHeight, isAuto); + this.eventRenderer.computeSizes(isResize); + this.eventRenderer.assignSizes(isResize); + this.scroller.clear(); // sets height to 'auto' and clears overflow + if (!isAuto) { + this.scroller.setHeight(this.computeScrollerHeight(viewHeight)); + } + }; + ListView.prototype.computeScrollerHeight = function (viewHeight) { + return viewHeight - + subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller + }; + ListView.prototype._eventStoreToSegs = function (eventStore, eventUiBases, dayRanges) { + return this.eventRangesToSegs(sliceEventStore(eventStore, eventUiBases, this.props.dateProfile.activeRange, this.nextDayThreshold).fg, dayRanges); + }; + ListView.prototype.eventRangesToSegs = function (eventRanges, dayRanges) { + var segs = []; + for (var _i = 0, eventRanges_1 = eventRanges; _i < eventRanges_1.length; _i++) { + var eventRange = eventRanges_1[_i]; + segs.push.apply(segs, this.eventRangeToSegs(eventRange, dayRanges)); + } + return segs; + }; + ListView.prototype.eventRangeToSegs = function (eventRange, dayRanges) { + var _a = this, dateEnv = _a.dateEnv, nextDayThreshold = _a.nextDayThreshold; + var range = eventRange.range; + var allDay = eventRange.def.allDay; + var dayIndex; + var segRange; + var seg; + var segs = []; + for (dayIndex = 0; dayIndex < dayRanges.length; dayIndex++) { + segRange = intersectRanges(range, dayRanges[dayIndex]); + if (segRange) { + seg = { + component: this, + eventRange: eventRange, + start: segRange.start, + end: segRange.end, + isStart: eventRange.isStart && segRange.start.valueOf() === range.start.valueOf(), + isEnd: eventRange.isEnd && segRange.end.valueOf() === range.end.valueOf(), + dayIndex: dayIndex + }; + segs.push(seg); + // detect when range won't go fully into the next day, + // and mutate the latest seg to the be the end. + if (!seg.isEnd && !allDay && + dayIndex + 1 < dayRanges.length && + range.end < + dateEnv.add(dayRanges[dayIndex + 1].start, nextDayThreshold)) { + seg.end = range.end; + seg.isEnd = true; + break; + } + } + } + return segs; + }; + ListView.prototype.renderEmptyMessage = function () { + this.contentEl.innerHTML = + '<div class="fc-list-empty-wrap2">' + // TODO: try less wraps + '<div class="fc-list-empty-wrap1">' + + '<div class="fc-list-empty">' + + htmlEscape(this.opt('noEventsMessage')) + + '</div>' + + '</div>' + + '</div>'; + }; + // called by ListEventRenderer + ListView.prototype.renderSegList = function (allSegs) { + var segsByDay = this.groupSegsByDay(allSegs); // sparse array + var dayIndex; + var daySegs; + var i; + var tableEl = htmlToElement('<table class="fc-list-table ' + this.calendar.theme.getClass('tableList') + '"><tbody></tbody></table>'); + var tbodyEl = tableEl.querySelector('tbody'); + for (dayIndex = 0; dayIndex < segsByDay.length; dayIndex++) { + daySegs = segsByDay[dayIndex]; + if (daySegs) { // sparse array, so might be undefined + // append a day header + tbodyEl.appendChild(this.buildDayHeaderRow(this.dayDates[dayIndex])); + daySegs = this.eventRenderer.sortEventSegs(daySegs); + for (i = 0; i < daySegs.length; i++) { + tbodyEl.appendChild(daySegs[i].el); // append event row + } + } + } + this.contentEl.innerHTML = ''; + this.contentEl.appendChild(tableEl); + }; + // Returns a sparse array of arrays, segs grouped by their dayIndex + ListView.prototype.groupSegsByDay = function (segs) { + var segsByDay = []; // sparse array + var i; + var seg; + for (i = 0; i < segs.length; i++) { + seg = segs[i]; + (segsByDay[seg.dayIndex] || (segsByDay[seg.dayIndex] = [])) + .push(seg); + } + return segsByDay; + }; + // generates the HTML for the day headers that live amongst the event rows + ListView.prototype.buildDayHeaderRow = function (dayDate) { + var dateEnv = this.dateEnv; + var mainFormat = createFormatter(this.opt('listDayFormat')); // TODO: cache + var altFormat = createFormatter(this.opt('listDayAltFormat')); // TODO: cache + return createElement('tr', { + className: 'fc-list-heading', + 'data-date': dateEnv.formatIso(dayDate, { omitTime: true }) + }, '<td class="' + (this.calendar.theme.getClass('tableListHeading') || + this.calendar.theme.getClass('widgetHeader')) + '" colspan="3">' + + (mainFormat ? + buildGotoAnchorHtml(this, dayDate, { 'class': 'fc-list-heading-main' }, htmlEscape(dateEnv.format(dayDate, mainFormat)) // inner HTML + ) : + '') + + (altFormat ? + buildGotoAnchorHtml(this, dayDate, { 'class': 'fc-list-heading-alt' }, htmlEscape(dateEnv.format(dayDate, altFormat)) // inner HTML + ) : + '') + + '</td>'); + }; + return ListView; +}(View)); +ListView.prototype.fgSegSelector = '.fc-list-item'; // which elements accept event actions +function computeDateVars(dateProfile) { + var dayStart = startOfDay(dateProfile.renderRange.start); + var viewEnd = dateProfile.renderRange.end; + var dayDates = []; + var dayRanges = []; + while (dayStart < viewEnd) { + dayDates.push(dayStart); + dayRanges.push({ + start: dayStart, + end: addDays(dayStart, 1) + }); + dayStart = addDays(dayStart, 1); + } + return { dayDates: dayDates, dayRanges: dayRanges }; +} + +var main = createPlugin({ + views: { + list: { + class: ListView, + buttonTextKey: 'list', + listDayFormat: { month: 'long', day: 'numeric', year: 'numeric' } // like "January 1, 2016" + }, + listDay: { + type: 'list', + duration: { days: 1 }, + listDayFormat: { weekday: 'long' } // day-of-week is all we need. full date is probably in header + }, + listWeek: { + type: 'list', + duration: { weeks: 1 }, + listDayFormat: { weekday: 'long' }, + listDayAltFormat: { month: 'long', day: 'numeric', year: 'numeric' } + }, + listMonth: { + type: 'list', + duration: { month: 1 }, + listDayAltFormat: { weekday: 'long' } // day-of-week is nice-to-have + }, + listYear: { + type: 'list', + duration: { year: 1 }, + listDayAltFormat: { weekday: 'long' } // day-of-week is nice-to-have + } + } +}); + +export default main; +export { ListView }; diff --git a/AKPlan/static/AKPlan/fullcalendar/list/main.js b/AKPlan/static/AKPlan/fullcalendar/list/main.js new file mode 100644 index 00000000..b855e4e0 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/list/main.js @@ -0,0 +1,343 @@ +/*! +FullCalendar List View Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) : + typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) : + (global = global || self, factory(global.FullCalendarList = {}, global.FullCalendar)); +}(this, function (exports, core) { 'use strict'; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + var ListEventRenderer = /** @class */ (function (_super) { + __extends(ListEventRenderer, _super); + function ListEventRenderer(listView) { + var _this = _super.call(this, listView.context) || this; + _this.listView = listView; + return _this; + } + ListEventRenderer.prototype.attachSegs = function (segs) { + if (!segs.length) { + this.listView.renderEmptyMessage(); + } + else { + this.listView.renderSegList(segs); + } + }; + ListEventRenderer.prototype.detachSegs = function () { + }; + // generates the HTML for a single event row + ListEventRenderer.prototype.renderSegHtml = function (seg) { + var _a = this.context, view = _a.view, theme = _a.theme; + var eventRange = seg.eventRange; + var eventDef = eventRange.def; + var eventInstance = eventRange.instance; + var eventUi = eventRange.ui; + var url = eventDef.url; + var classes = ['fc-list-item'].concat(eventUi.classNames); + var bgColor = eventUi.backgroundColor; + var timeHtml; + if (eventDef.allDay) { + timeHtml = core.getAllDayHtml(view); + } + else if (core.isMultiDayRange(eventRange.range)) { + if (seg.isStart) { + timeHtml = core.htmlEscape(this._getTimeText(eventInstance.range.start, seg.end, false // allDay + )); + } + else if (seg.isEnd) { + timeHtml = core.htmlEscape(this._getTimeText(seg.start, eventInstance.range.end, false // allDay + )); + } + else { // inner segment that lasts the whole day + timeHtml = core.getAllDayHtml(view); + } + } + else { + // Display the normal time text for the *event's* times + timeHtml = core.htmlEscape(this.getTimeText(eventRange)); + } + if (url) { + classes.push('fc-has-url'); + } + return '<tr class="' + classes.join(' ') + '">' + + (this.displayEventTime ? + '<td class="fc-list-item-time ' + theme.getClass('widgetContent') + '">' + + (timeHtml || '') + + '</td>' : + '') + + '<td class="fc-list-item-marker ' + theme.getClass('widgetContent') + '">' + + '<span class="fc-event-dot"' + + (bgColor ? + ' style="background-color:' + bgColor + '"' : + '') + + '></span>' + + '</td>' + + '<td class="fc-list-item-title ' + theme.getClass('widgetContent') + '">' + + '<a' + (url ? ' href="' + core.htmlEscape(url) + '"' : '') + '>' + + core.htmlEscape(eventDef.title || '') + + '</a>' + + '</td>' + + '</tr>'; + }; + // like "4:00am" + ListEventRenderer.prototype.computeEventTimeFormat = function () { + return { + hour: 'numeric', + minute: '2-digit', + meridiem: 'short' + }; + }; + return ListEventRenderer; + }(core.FgEventRenderer)); + + /* + Responsible for the scroller, and forwarding event-related actions into the "grid". + */ + var ListView = /** @class */ (function (_super) { + __extends(ListView, _super); + function ListView(context, viewSpec, dateProfileGenerator, parentEl) { + var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this; + _this.computeDateVars = core.memoize(computeDateVars); + _this.eventStoreToSegs = core.memoize(_this._eventStoreToSegs); + var eventRenderer = _this.eventRenderer = new ListEventRenderer(_this); + _this.renderContent = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer)); + _this.el.classList.add('fc-list-view'); + var listViewClassNames = (_this.theme.getClass('listView') || '').split(' '); // wish we didn't have to do this + for (var _i = 0, listViewClassNames_1 = listViewClassNames; _i < listViewClassNames_1.length; _i++) { + var listViewClassName = listViewClassNames_1[_i]; + if (listViewClassName) { // in case input was empty string + _this.el.classList.add(listViewClassName); + } + } + _this.scroller = new core.ScrollComponent('hidden', // overflow x + 'auto' // overflow y + ); + _this.el.appendChild(_this.scroller.el); + _this.contentEl = _this.scroller.el; // shortcut + context.calendar.registerInteractiveComponent(_this, { + el: _this.el + // TODO: make aware that it doesn't do Hits + }); + return _this; + } + ListView.prototype.render = function (props) { + var _a = this.computeDateVars(props.dateProfile), dayDates = _a.dayDates, dayRanges = _a.dayRanges; + this.dayDates = dayDates; + this.renderContent(this.eventStoreToSegs(props.eventStore, props.eventUiBases, dayRanges)); + }; + ListView.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.renderContent.unrender(); + this.scroller.destroy(); // will remove the Grid too + this.calendar.unregisterInteractiveComponent(this); + }; + ListView.prototype.updateSize = function (isResize, viewHeight, isAuto) { + _super.prototype.updateSize.call(this, isResize, viewHeight, isAuto); + this.eventRenderer.computeSizes(isResize); + this.eventRenderer.assignSizes(isResize); + this.scroller.clear(); // sets height to 'auto' and clears overflow + if (!isAuto) { + this.scroller.setHeight(this.computeScrollerHeight(viewHeight)); + } + }; + ListView.prototype.computeScrollerHeight = function (viewHeight) { + return viewHeight - + core.subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller + }; + ListView.prototype._eventStoreToSegs = function (eventStore, eventUiBases, dayRanges) { + return this.eventRangesToSegs(core.sliceEventStore(eventStore, eventUiBases, this.props.dateProfile.activeRange, this.nextDayThreshold).fg, dayRanges); + }; + ListView.prototype.eventRangesToSegs = function (eventRanges, dayRanges) { + var segs = []; + for (var _i = 0, eventRanges_1 = eventRanges; _i < eventRanges_1.length; _i++) { + var eventRange = eventRanges_1[_i]; + segs.push.apply(segs, this.eventRangeToSegs(eventRange, dayRanges)); + } + return segs; + }; + ListView.prototype.eventRangeToSegs = function (eventRange, dayRanges) { + var _a = this, dateEnv = _a.dateEnv, nextDayThreshold = _a.nextDayThreshold; + var range = eventRange.range; + var allDay = eventRange.def.allDay; + var dayIndex; + var segRange; + var seg; + var segs = []; + for (dayIndex = 0; dayIndex < dayRanges.length; dayIndex++) { + segRange = core.intersectRanges(range, dayRanges[dayIndex]); + if (segRange) { + seg = { + component: this, + eventRange: eventRange, + start: segRange.start, + end: segRange.end, + isStart: eventRange.isStart && segRange.start.valueOf() === range.start.valueOf(), + isEnd: eventRange.isEnd && segRange.end.valueOf() === range.end.valueOf(), + dayIndex: dayIndex + }; + segs.push(seg); + // detect when range won't go fully into the next day, + // and mutate the latest seg to the be the end. + if (!seg.isEnd && !allDay && + dayIndex + 1 < dayRanges.length && + range.end < + dateEnv.add(dayRanges[dayIndex + 1].start, nextDayThreshold)) { + seg.end = range.end; + seg.isEnd = true; + break; + } + } + } + return segs; + }; + ListView.prototype.renderEmptyMessage = function () { + this.contentEl.innerHTML = + '<div class="fc-list-empty-wrap2">' + // TODO: try less wraps + '<div class="fc-list-empty-wrap1">' + + '<div class="fc-list-empty">' + + core.htmlEscape(this.opt('noEventsMessage')) + + '</div>' + + '</div>' + + '</div>'; + }; + // called by ListEventRenderer + ListView.prototype.renderSegList = function (allSegs) { + var segsByDay = this.groupSegsByDay(allSegs); // sparse array + var dayIndex; + var daySegs; + var i; + var tableEl = core.htmlToElement('<table class="fc-list-table ' + this.calendar.theme.getClass('tableList') + '"><tbody></tbody></table>'); + var tbodyEl = tableEl.querySelector('tbody'); + for (dayIndex = 0; dayIndex < segsByDay.length; dayIndex++) { + daySegs = segsByDay[dayIndex]; + if (daySegs) { // sparse array, so might be undefined + // append a day header + tbodyEl.appendChild(this.buildDayHeaderRow(this.dayDates[dayIndex])); + daySegs = this.eventRenderer.sortEventSegs(daySegs); + for (i = 0; i < daySegs.length; i++) { + tbodyEl.appendChild(daySegs[i].el); // append event row + } + } + } + this.contentEl.innerHTML = ''; + this.contentEl.appendChild(tableEl); + }; + // Returns a sparse array of arrays, segs grouped by their dayIndex + ListView.prototype.groupSegsByDay = function (segs) { + var segsByDay = []; // sparse array + var i; + var seg; + for (i = 0; i < segs.length; i++) { + seg = segs[i]; + (segsByDay[seg.dayIndex] || (segsByDay[seg.dayIndex] = [])) + .push(seg); + } + return segsByDay; + }; + // generates the HTML for the day headers that live amongst the event rows + ListView.prototype.buildDayHeaderRow = function (dayDate) { + var dateEnv = this.dateEnv; + var mainFormat = core.createFormatter(this.opt('listDayFormat')); // TODO: cache + var altFormat = core.createFormatter(this.opt('listDayAltFormat')); // TODO: cache + return core.createElement('tr', { + className: 'fc-list-heading', + 'data-date': dateEnv.formatIso(dayDate, { omitTime: true }) + }, '<td class="' + (this.calendar.theme.getClass('tableListHeading') || + this.calendar.theme.getClass('widgetHeader')) + '" colspan="3">' + + (mainFormat ? + core.buildGotoAnchorHtml(this, dayDate, { 'class': 'fc-list-heading-main' }, core.htmlEscape(dateEnv.format(dayDate, mainFormat)) // inner HTML + ) : + '') + + (altFormat ? + core.buildGotoAnchorHtml(this, dayDate, { 'class': 'fc-list-heading-alt' }, core.htmlEscape(dateEnv.format(dayDate, altFormat)) // inner HTML + ) : + '') + + '</td>'); + }; + return ListView; + }(core.View)); + ListView.prototype.fgSegSelector = '.fc-list-item'; // which elements accept event actions + function computeDateVars(dateProfile) { + var dayStart = core.startOfDay(dateProfile.renderRange.start); + var viewEnd = dateProfile.renderRange.end; + var dayDates = []; + var dayRanges = []; + while (dayStart < viewEnd) { + dayDates.push(dayStart); + dayRanges.push({ + start: dayStart, + end: core.addDays(dayStart, 1) + }); + dayStart = core.addDays(dayStart, 1); + } + return { dayDates: dayDates, dayRanges: dayRanges }; + } + + var main = core.createPlugin({ + views: { + list: { + class: ListView, + buttonTextKey: 'list', + listDayFormat: { month: 'long', day: 'numeric', year: 'numeric' } // like "January 1, 2016" + }, + listDay: { + type: 'list', + duration: { days: 1 }, + listDayFormat: { weekday: 'long' } // day-of-week is all we need. full date is probably in header + }, + listWeek: { + type: 'list', + duration: { weeks: 1 }, + listDayFormat: { weekday: 'long' }, + listDayAltFormat: { month: 'long', day: 'numeric', year: 'numeric' } + }, + listMonth: { + type: 'list', + duration: { month: 1 }, + listDayAltFormat: { weekday: 'long' } // day-of-week is nice-to-have + }, + listYear: { + type: 'list', + duration: { year: 1 }, + listDayAltFormat: { weekday: 'long' } // day-of-week is nice-to-have + } + } + }); + + exports.ListView = ListView; + exports.default = main; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/list/main.min.css b/AKPlan/static/AKPlan/fullcalendar/list/main.min.css new file mode 100644 index 00000000..18446f44 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/list/main.min.css @@ -0,0 +1 @@ +.fc-event-dot{display:inline-block;width:10px;height:10px;border-radius:5px}.fc-rtl .fc-list-view{direction:rtl}.fc-list-view{border-width:1px;border-style:solid}.fc .fc-list-table{table-layout:auto}.fc-list-table td{border-width:1px 0 0;padding:8px 14px}.fc-list-table tr:first-child td{border-top-width:0}.fc-list-heading{border-bottom-width:1px}.fc-list-heading td{font-weight:700}.fc-ltr .fc-list-heading-main{float:left}.fc-ltr .fc-list-heading-alt,.fc-rtl .fc-list-heading-main{float:right}.fc-rtl .fc-list-heading-alt{float:left}.fc-list-item.fc-has-url{cursor:pointer}.fc-list-item-marker,.fc-list-item-time{white-space:nowrap;width:1px}.fc-ltr .fc-list-item-marker{padding-right:0}.fc-rtl .fc-list-item-marker{padding-left:0}.fc-list-item-title a{text-decoration:none;color:inherit}.fc-list-item-title a[href]:hover{text-decoration:underline}.fc-list-empty-wrap2{position:absolute;top:0;left:0;right:0;bottom:0}.fc-list-empty-wrap1{width:100%;height:100%;display:table}.fc-list-empty{display:table-cell;vertical-align:middle;text-align:center}.fc-unthemed .fc-list-empty{background-color:#eee} \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/list/main.min.js b/AKPlan/static/AKPlan/fullcalendar/list/main.min.js new file mode 100644 index 00000000..f954aac8 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/list/main.min.js @@ -0,0 +1,6 @@ +/*! +FullCalendar List View Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@fullcalendar/core")):"function"==typeof define&&define.amd?define(["exports","@fullcalendar/core"],t):t((e=e||self).FullCalendarList={},e.FullCalendar)}(this,function(e,t){"use strict";var n=function(e,t){return(n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)};function r(e,t){function r(){this.constructor=e}n(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}var s=function(e){function n(t){var n=e.call(this,t.context)||this;return n.listView=t,n}return r(n,e),n.prototype.attachSegs=function(e){e.length?this.listView.renderSegList(e):this.listView.renderEmptyMessage()},n.prototype.detachSegs=function(){},n.prototype.renderSegHtml=function(e){var n,r=this.context,s=r.view,a=r.theme,i=e.eventRange,o=i.def,l=i.instance,d=i.ui,c=o.url,p=["fc-list-item"].concat(d.classNames),h=d.backgroundColor;return n=o.allDay?t.getAllDayHtml(s):t.isMultiDayRange(i.range)?e.isStart?t.htmlEscape(this._getTimeText(l.range.start,e.end,!1)):e.isEnd?t.htmlEscape(this._getTimeText(e.start,l.range.end,!1)):t.getAllDayHtml(s):t.htmlEscape(this.getTimeText(i)),c&&p.push("fc-has-url"),'<tr class="'+p.join(" ")+'">'+(this.displayEventTime?'<td class="fc-list-item-time '+a.getClass("widgetContent")+'">'+(n||"")+"</td>":"")+'<td class="fc-list-item-marker '+a.getClass("widgetContent")+'"><span class="fc-event-dot"'+(h?' style="background-color:'+h+'"':"")+'></span></td><td class="fc-list-item-title '+a.getClass("widgetContent")+'"><a'+(c?' href="'+t.htmlEscape(c)+'"':"")+">"+t.htmlEscape(o.title||"")+"</a></td></tr>"},n.prototype.computeEventTimeFormat=function(){return{hour:"numeric",minute:"2-digit",meridiem:"short"}},n}(t.FgEventRenderer),a=function(e){function n(n,r,a,o){var l=e.call(this,n,r,a,o)||this;l.computeDateVars=t.memoize(i),l.eventStoreToSegs=t.memoize(l._eventStoreToSegs);var d=l.eventRenderer=new s(l);l.renderContent=t.memoizeRendering(d.renderSegs.bind(d),d.unrender.bind(d)),l.el.classList.add("fc-list-view");for(var c=0,p=(l.theme.getClass("listView")||"").split(" ");c<p.length;c++){var h=p[c];h&&l.el.classList.add(h)}return l.scroller=new t.ScrollComponent("hidden","auto"),l.el.appendChild(l.scroller.el),l.contentEl=l.scroller.el,n.calendar.registerInteractiveComponent(l,{el:l.el}),l}return r(n,e),n.prototype.render=function(e){var t=this.computeDateVars(e.dateProfile),n=t.dayDates,r=t.dayRanges;this.dayDates=n,this.renderContent(this.eventStoreToSegs(e.eventStore,e.eventUiBases,r))},n.prototype.destroy=function(){e.prototype.destroy.call(this),this.renderContent.unrender(),this.scroller.destroy(),this.calendar.unregisterInteractiveComponent(this)},n.prototype.updateSize=function(t,n,r){e.prototype.updateSize.call(this,t,n,r),this.eventRenderer.computeSizes(t),this.eventRenderer.assignSizes(t),this.scroller.clear(),r||this.scroller.setHeight(this.computeScrollerHeight(n))},n.prototype.computeScrollerHeight=function(e){return e-t.subtractInnerElHeight(this.el,this.scroller.el)},n.prototype._eventStoreToSegs=function(e,n,r){return this.eventRangesToSegs(t.sliceEventStore(e,n,this.props.dateProfile.activeRange,this.nextDayThreshold).fg,r)},n.prototype.eventRangesToSegs=function(e,t){for(var n=[],r=0,s=e;r<s.length;r++){var a=s[r];n.push.apply(n,this.eventRangeToSegs(a,t))}return n},n.prototype.eventRangeToSegs=function(e,n){var r,s,a,i=this.dateEnv,o=this.nextDayThreshold,l=e.range,d=e.def.allDay,c=[];for(r=0;r<n.length;r++)if((s=t.intersectRanges(l,n[r]))&&(a={component:this,eventRange:e,start:s.start,end:s.end,isStart:e.isStart&&s.start.valueOf()===l.start.valueOf(),isEnd:e.isEnd&&s.end.valueOf()===l.end.valueOf(),dayIndex:r},c.push(a),!a.isEnd&&!d&&r+1<n.length&&l.end<i.add(n[r+1].start,o))){a.end=l.end,a.isEnd=!0;break}return c},n.prototype.renderEmptyMessage=function(){this.contentEl.innerHTML='<div class="fc-list-empty-wrap2"><div class="fc-list-empty-wrap1"><div class="fc-list-empty">'+t.htmlEscape(this.opt("noEventsMessage"))+"</div></div></div>"},n.prototype.renderSegList=function(e){var n,r,s,a=this.groupSegsByDay(e),i=t.htmlToElement('<table class="fc-list-table '+this.calendar.theme.getClass("tableList")+'"><tbody></tbody></table>'),o=i.querySelector("tbody");for(n=0;n<a.length;n++)if(r=a[n])for(o.appendChild(this.buildDayHeaderRow(this.dayDates[n])),r=this.eventRenderer.sortEventSegs(r),s=0;s<r.length;s++)o.appendChild(r[s].el);this.contentEl.innerHTML="",this.contentEl.appendChild(i)},n.prototype.groupSegsByDay=function(e){var t,n,r=[];for(t=0;t<e.length;t++)(r[(n=e[t]).dayIndex]||(r[n.dayIndex]=[])).push(n);return r},n.prototype.buildDayHeaderRow=function(e){var n=this.dateEnv,r=t.createFormatter(this.opt("listDayFormat")),s=t.createFormatter(this.opt("listDayAltFormat"));return t.createElement("tr",{className:"fc-list-heading","data-date":n.formatIso(e,{omitTime:!0})},'<td class="'+(this.calendar.theme.getClass("tableListHeading")||this.calendar.theme.getClass("widgetHeader"))+'" colspan="3">'+(r?t.buildGotoAnchorHtml(this,e,{class:"fc-list-heading-main"},t.htmlEscape(n.format(e,r))):"")+(s?t.buildGotoAnchorHtml(this,e,{class:"fc-list-heading-alt"},t.htmlEscape(n.format(e,s))):"")+"</td>")},n}(t.View);function i(e){for(var n=t.startOfDay(e.renderRange.start),r=e.renderRange.end,s=[],a=[];n<r;)s.push(n),a.push({start:n,end:t.addDays(n,1)}),n=t.addDays(n,1);return{dayDates:s,dayRanges:a}}a.prototype.fgSegSelector=".fc-list-item";var o=t.createPlugin({views:{list:{class:a,buttonTextKey:"list",listDayFormat:{month:"long",day:"numeric",year:"numeric"}},listDay:{type:"list",duration:{days:1},listDayFormat:{weekday:"long"}},listWeek:{type:"list",duration:{weeks:1},listDayFormat:{weekday:"long"},listDayAltFormat:{month:"long",day:"numeric",year:"numeric"}},listMonth:{type:"list",duration:{month:1},listDayAltFormat:{weekday:"long"}},listYear:{type:"list",duration:{year:1},listDayAltFormat:{weekday:"long"}}}});e.ListView=a,e.default=o,Object.defineProperty(e,"__esModule",{value:!0})}); \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/list/package.json b/AKPlan/static/AKPlan/fullcalendar/list/package.json new file mode 100644 index 00000000..83cc13e4 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/list/package.json @@ -0,0 +1,33 @@ +{ + "name": "@fullcalendar/list", + "version": "4.3.0", + "title": "FullCalendar List View Plugin", + "description": "View your events as a bulleted list", + "keywords": [ + "calendar", + "event", + "full-sized" + ], + "homepage": "https://fullcalendar.io/", + "docs": "https://fullcalendar.io/docs/list-view", + "bugs": "https://fullcalendar.io/reporting-bugs", + "repository": { + "type": "git", + "url": "https://github.com/fullcalendar/fullcalendar.git", + "homepage": "https://github.com/fullcalendar/fullcalendar" + }, + "license": "MIT", + "author": { + "name": "Adam Shaw", + "email": "arshaw@arshaw.com", + "url": "http://arshaw.com/" + }, + "copyright": "2019 Adam Shaw", + "peerDependencies": { + "@fullcalendar/core": "~4.3.0" + }, + "main": "main.js", + "module": "main.esm.js", + "unpkg": "main.min.js", + "types": "main.d.ts" +} diff --git a/AKPlan/static/AKPlan/fullcalendar/luxon/LICENSE.txt b/AKPlan/static/AKPlan/fullcalendar/luxon/LICENSE.txt new file mode 100644 index 00000000..2149cfbe --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/luxon/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2019 Adam Shaw + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/AKPlan/static/AKPlan/fullcalendar/luxon/README.md b/AKPlan/static/AKPlan/fullcalendar/luxon/README.md new file mode 100644 index 00000000..4c42b505 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/luxon/README.md @@ -0,0 +1,8 @@ + +# FullCalendar Luxon Plugin + +A connector to the Luxon date library + +[View the docs »](https://fullcalendar.io/docs/luxon-plugin) + +This package was created from the [FullCalendar monorepo »](https://github.com/fullcalendar/fullcalendar) diff --git a/AKPlan/static/AKPlan/fullcalendar/luxon/main.d.ts b/AKPlan/static/AKPlan/fullcalendar/luxon/main.d.ts new file mode 100644 index 00000000..54f016dd --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/luxon/main.d.ts @@ -0,0 +1,14 @@ +// Generated by dts-bundle v0.7.3-fork.1 +// Dependencies for this module: +// ../../../../../luxon +// ../../../../../@fullcalendar/core + +declare module '@fullcalendar/luxon' { + import { DateTime as LuxonDateTime, Duration as LuxonDuration } from 'luxon'; + import { Calendar, Duration } from '@fullcalendar/core'; + export function toDateTime(date: Date, calendar: Calendar): LuxonDateTime; + export function toDuration(duration: Duration, calendar: Calendar): LuxonDuration; + const _default: import("@fullcalendar/core").PluginDef; + export default _default; +} + diff --git a/AKPlan/static/AKPlan/fullcalendar/luxon/main.esm.js b/AKPlan/static/AKPlan/fullcalendar/luxon/main.esm.js new file mode 100644 index 00000000..f41c464f --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/luxon/main.esm.js @@ -0,0 +1,162 @@ +/*! +FullCalendar Luxon Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +import { DateTime, Duration } from 'luxon'; +import { createPlugin, Calendar, NamedTimeZoneImpl } from '@fullcalendar/core'; + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} + +var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; + +function toDateTime(date, calendar) { + if (!(calendar instanceof Calendar)) { + throw new Error('must supply a Calendar instance'); + } + return DateTime.fromJSDate(date, { + zone: calendar.dateEnv.timeZone, + locale: calendar.dateEnv.locale.codes[0] + }); +} +function toDuration(duration, calendar) { + if (!(calendar instanceof Calendar)) { + throw new Error('must supply a Calendar instance'); + } + return Duration.fromObject(__assign({}, duration, { locale: calendar.dateEnv.locale.codes[0] })); +} +var LuxonNamedTimeZone = /** @class */ (function (_super) { + __extends(LuxonNamedTimeZone, _super); + function LuxonNamedTimeZone() { + return _super !== null && _super.apply(this, arguments) || this; + } + LuxonNamedTimeZone.prototype.offsetForArray = function (a) { + return arrayToLuxon(a, this.timeZoneName).offset; + }; + LuxonNamedTimeZone.prototype.timestampToArray = function (ms) { + return luxonToArray(DateTime.fromMillis(ms, { + zone: this.timeZoneName + })); + }; + return LuxonNamedTimeZone; +}(NamedTimeZoneImpl)); +function formatWithCmdStr(cmdStr, arg) { + var cmd = parseCmdStr(cmdStr); + if (arg.end) { + var start = arrayToLuxon(arg.start.array, arg.timeZone, arg.localeCodes[0]); + var end = arrayToLuxon(arg.end.array, arg.timeZone, arg.localeCodes[0]); + return formatRange(cmd, start.toFormat.bind(start), end.toFormat.bind(end), arg.separator); + } + return arrayToLuxon(arg.date.array, arg.timeZone, arg.localeCodes[0]).toFormat(cmd.whole); +} +var main = createPlugin({ + cmdFormatter: formatWithCmdStr, + namedTimeZonedImpl: LuxonNamedTimeZone +}); +function luxonToArray(datetime) { + return [ + datetime.year, + datetime.month - 1, + datetime.day, + datetime.hour, + datetime.minute, + datetime.second, + datetime.millisecond + ]; +} +function arrayToLuxon(arr, timeZone, locale) { + return DateTime.fromObject({ + zone: timeZone, + locale: locale, + year: arr[0], + month: arr[1] + 1, + day: arr[2], + hour: arr[3], + minute: arr[4], + second: arr[5], + millisecond: arr[6] + }); +} +function parseCmdStr(cmdStr) { + var parts = cmdStr.match(/^(.*?)\{(.*)\}(.*)$/); // TODO: lookbehinds for escape characters + if (parts) { + var middle = parseCmdStr(parts[2]); + return { + head: parts[1], + middle: middle, + tail: parts[3], + whole: parts[1] + middle.whole + parts[3] + }; + } + else { + return { + head: null, + middle: null, + tail: null, + whole: cmdStr + }; + } +} +function formatRange(cmd, formatStart, formatEnd, separator) { + if (cmd.middle) { + var startHead = formatStart(cmd.head); + var startMiddle = formatRange(cmd.middle, formatStart, formatEnd, separator); + var startTail = formatStart(cmd.tail); + var endHead = formatEnd(cmd.head); + var endMiddle = formatRange(cmd.middle, formatStart, formatEnd, separator); + var endTail = formatEnd(cmd.tail); + if (startHead === endHead && startTail === endTail) { + return startHead + + (startMiddle === endMiddle ? startMiddle : startMiddle + separator + endMiddle) + + startTail; + } + } + var startWhole = formatStart(cmd.whole); + var endWhole = formatEnd(cmd.whole); + if (startWhole === endWhole) { + return startWhole; + } + else { + return startWhole + separator + endWhole; + } +} + +export default main; +export { toDateTime, toDuration }; diff --git a/AKPlan/static/AKPlan/fullcalendar/luxon/main.js b/AKPlan/static/AKPlan/fullcalendar/luxon/main.js new file mode 100644 index 00000000..000c7721 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/luxon/main.js @@ -0,0 +1,170 @@ +/*! +FullCalendar Luxon Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('luxon'), require('@fullcalendar/core')) : + typeof define === 'function' && define.amd ? define(['exports', 'luxon', '@fullcalendar/core'], factory) : + (global = global || self, factory(global.FullCalendarLuxon = {}, global.luxon, global.FullCalendar)); +}(this, function (exports, luxon, core) { 'use strict'; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + function toDateTime(date, calendar) { + if (!(calendar instanceof core.Calendar)) { + throw new Error('must supply a Calendar instance'); + } + return luxon.DateTime.fromJSDate(date, { + zone: calendar.dateEnv.timeZone, + locale: calendar.dateEnv.locale.codes[0] + }); + } + function toDuration(duration, calendar) { + if (!(calendar instanceof core.Calendar)) { + throw new Error('must supply a Calendar instance'); + } + return luxon.Duration.fromObject(__assign({}, duration, { locale: calendar.dateEnv.locale.codes[0] })); + } + var LuxonNamedTimeZone = /** @class */ (function (_super) { + __extends(LuxonNamedTimeZone, _super); + function LuxonNamedTimeZone() { + return _super !== null && _super.apply(this, arguments) || this; + } + LuxonNamedTimeZone.prototype.offsetForArray = function (a) { + return arrayToLuxon(a, this.timeZoneName).offset; + }; + LuxonNamedTimeZone.prototype.timestampToArray = function (ms) { + return luxonToArray(luxon.DateTime.fromMillis(ms, { + zone: this.timeZoneName + })); + }; + return LuxonNamedTimeZone; + }(core.NamedTimeZoneImpl)); + function formatWithCmdStr(cmdStr, arg) { + var cmd = parseCmdStr(cmdStr); + if (arg.end) { + var start = arrayToLuxon(arg.start.array, arg.timeZone, arg.localeCodes[0]); + var end = arrayToLuxon(arg.end.array, arg.timeZone, arg.localeCodes[0]); + return formatRange(cmd, start.toFormat.bind(start), end.toFormat.bind(end), arg.separator); + } + return arrayToLuxon(arg.date.array, arg.timeZone, arg.localeCodes[0]).toFormat(cmd.whole); + } + var main = core.createPlugin({ + cmdFormatter: formatWithCmdStr, + namedTimeZonedImpl: LuxonNamedTimeZone + }); + function luxonToArray(datetime) { + return [ + datetime.year, + datetime.month - 1, + datetime.day, + datetime.hour, + datetime.minute, + datetime.second, + datetime.millisecond + ]; + } + function arrayToLuxon(arr, timeZone, locale) { + return luxon.DateTime.fromObject({ + zone: timeZone, + locale: locale, + year: arr[0], + month: arr[1] + 1, + day: arr[2], + hour: arr[3], + minute: arr[4], + second: arr[5], + millisecond: arr[6] + }); + } + function parseCmdStr(cmdStr) { + var parts = cmdStr.match(/^(.*?)\{(.*)\}(.*)$/); // TODO: lookbehinds for escape characters + if (parts) { + var middle = parseCmdStr(parts[2]); + return { + head: parts[1], + middle: middle, + tail: parts[3], + whole: parts[1] + middle.whole + parts[3] + }; + } + else { + return { + head: null, + middle: null, + tail: null, + whole: cmdStr + }; + } + } + function formatRange(cmd, formatStart, formatEnd, separator) { + if (cmd.middle) { + var startHead = formatStart(cmd.head); + var startMiddle = formatRange(cmd.middle, formatStart, formatEnd, separator); + var startTail = formatStart(cmd.tail); + var endHead = formatEnd(cmd.head); + var endMiddle = formatRange(cmd.middle, formatStart, formatEnd, separator); + var endTail = formatEnd(cmd.tail); + if (startHead === endHead && startTail === endTail) { + return startHead + + (startMiddle === endMiddle ? startMiddle : startMiddle + separator + endMiddle) + + startTail; + } + } + var startWhole = formatStart(cmd.whole); + var endWhole = formatEnd(cmd.whole); + if (startWhole === endWhole) { + return startWhole; + } + else { + return startWhole + separator + endWhole; + } + } + + exports.default = main; + exports.toDateTime = toDateTime; + exports.toDuration = toDuration; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/luxon/main.min.js b/AKPlan/static/AKPlan/fullcalendar/luxon/main.min.js new file mode 100644 index 00000000..bc8b9f7c --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/luxon/main.min.js @@ -0,0 +1,6 @@ +/*! +FullCalendar Luxon Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("luxon"),require("@fullcalendar/core")):"function"==typeof define&&define.amd?define(["exports","luxon","@fullcalendar/core"],t):t((e=e||self).FullCalendarLuxon={},e.luxon,e.FullCalendar)}(this,function(e,t,n){"use strict";var o=function(e,t){return(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)};var r=function(){return(r=Object.assign||function(e){for(var t,n=1,o=arguments.length;n<o;n++)for(var r in t=arguments[n])Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e}).apply(this,arguments)};var a=function(e){function n(){return null!==e&&e.apply(this,arguments)||this}return function(e,t){function n(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}(n,e),n.prototype.offsetForArray=function(e){return l(e,this.timeZoneName).offset},n.prototype.timestampToArray=function(e){return[(n=t.DateTime.fromMillis(e,{zone:this.timeZoneName})).year,n.month-1,n.day,n.hour,n.minute,n.second,n.millisecond];var n},n}(n.NamedTimeZoneImpl);var i=n.createPlugin({cmdFormatter:function(e,t){var n=function e(t){var n=t.match(/^(.*?)\{(.*)\}(.*)$/);if(n){var o=e(n[2]);return{head:n[1],middle:o,tail:n[3],whole:n[1]+o.whole+n[3]}}return{head:null,middle:null,tail:null,whole:t}}(e);if(t.end){var o=l(t.start.array,t.timeZone,t.localeCodes[0]),r=l(t.end.array,t.timeZone,t.localeCodes[0]);return function e(t,n,o,r){if(t.middle){var a=n(t.head),i=e(t.middle,n,o,r),l=n(t.tail),u=o(t.head),c=e(t.middle,n,o,r),d=o(t.tail);if(a===u&&l===d)return a+(i===c?i:i+r+c)+l}var f=n(t.whole),m=o(t.whole);return f===m?f:f+r+m}(n,o.toFormat.bind(o),r.toFormat.bind(r),t.separator)}return l(t.date.array,t.timeZone,t.localeCodes[0]).toFormat(n.whole)},namedTimeZonedImpl:a});function l(e,n,o){return t.DateTime.fromObject({zone:n,locale:o,year:e[0],month:e[1]+1,day:e[2],hour:e[3],minute:e[4],second:e[5],millisecond:e[6]})}e.default=i,e.toDateTime=function(e,o){if(!(o instanceof n.Calendar))throw new Error("must supply a Calendar instance");return t.DateTime.fromJSDate(e,{zone:o.dateEnv.timeZone,locale:o.dateEnv.locale.codes[0]})},e.toDuration=function(e,o){if(!(o instanceof n.Calendar))throw new Error("must supply a Calendar instance");return t.Duration.fromObject(r({},e,{locale:o.dateEnv.locale.codes[0]}))},Object.defineProperty(e,"__esModule",{value:!0})}); \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/luxon/package.json b/AKPlan/static/AKPlan/fullcalendar/luxon/package.json new file mode 100644 index 00000000..4cf344fd --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/luxon/package.json @@ -0,0 +1,34 @@ +{ + "name": "@fullcalendar/luxon", + "version": "4.3.0", + "title": "FullCalendar Luxon Plugin", + "description": "A connector to the Luxon date library", + "keywords": [ + "calendar", + "event", + "full-sized" + ], + "homepage": "https://fullcalendar.io/", + "docs": "https://fullcalendar.io/docs/luxon-plugin", + "bugs": "https://fullcalendar.io/reporting-bugs", + "repository": { + "type": "git", + "url": "https://github.com/fullcalendar/fullcalendar.git", + "homepage": "https://github.com/fullcalendar/fullcalendar" + }, + "license": "MIT", + "author": { + "name": "Adam Shaw", + "email": "arshaw@arshaw.com", + "url": "http://arshaw.com/" + }, + "copyright": "2019 Adam Shaw", + "peerDependencies": { + "@fullcalendar/core": "~4.3.0", + "luxon": "^1.12.1" + }, + "main": "main.js", + "module": "main.esm.js", + "unpkg": "main.min.js", + "types": "main.d.ts" +} diff --git a/AKPlan/static/AKPlan/fullcalendar/moment-timezone/LICENSE.txt b/AKPlan/static/AKPlan/fullcalendar/moment-timezone/LICENSE.txt new file mode 100644 index 00000000..2149cfbe --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/moment-timezone/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2019 Adam Shaw + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/AKPlan/static/AKPlan/fullcalendar/moment-timezone/README.md b/AKPlan/static/AKPlan/fullcalendar/moment-timezone/README.md new file mode 100644 index 00000000..e84412a2 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/moment-timezone/README.md @@ -0,0 +1,8 @@ + +# FullCalendar Moment Timezone Plugin + +A connector to the moment-timezone library + +[View the docs »](https://fullcalendar.io/docs/moment-plugins#moment-timezone) + +This package was created from the [FullCalendar monorepo »](https://github.com/fullcalendar/fullcalendar) diff --git a/AKPlan/static/AKPlan/fullcalendar/moment-timezone/main.d.ts b/AKPlan/static/AKPlan/fullcalendar/moment-timezone/main.d.ts new file mode 100644 index 00000000..eb0a165b --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/moment-timezone/main.d.ts @@ -0,0 +1,11 @@ +// Generated by dts-bundle v0.7.3-fork.1 +// Dependencies for this module: +// ../../../../../moment-timezone/builds/moment-timezone-with-data +// ../../../../../@fullcalendar/core + +declare module '@fullcalendar/moment-timezone' { + import 'moment-timezone/builds/moment-timezone-with-data'; + const _default: import("@fullcalendar/core").PluginDef; + export default _default; +} + diff --git a/AKPlan/static/AKPlan/fullcalendar/moment-timezone/main.esm.js b/AKPlan/static/AKPlan/fullcalendar/moment-timezone/main.esm.js new file mode 100644 index 00000000..98e943cb --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/moment-timezone/main.esm.js @@ -0,0 +1,58 @@ +/*! +FullCalendar Moment Timezone Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +import * as momentNs from 'moment'; +import 'moment-timezone/builds/moment-timezone-with-data'; +import { createPlugin, NamedTimeZoneImpl } from '@fullcalendar/core'; + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} + +var moment = momentNs; // the directly callable function +var MomentNamedTimeZone = /** @class */ (function (_super) { + __extends(MomentNamedTimeZone, _super); + function MomentNamedTimeZone() { + return _super !== null && _super.apply(this, arguments) || this; + } + MomentNamedTimeZone.prototype.offsetForArray = function (a) { + return moment.tz(a, this.timeZoneName).utcOffset(); + }; + MomentNamedTimeZone.prototype.timestampToArray = function (ms) { + return moment.tz(ms, this.timeZoneName).toArray(); + }; + return MomentNamedTimeZone; +}(NamedTimeZoneImpl)); +var main = createPlugin({ + namedTimeZonedImpl: MomentNamedTimeZone +}); + +export default main; diff --git a/AKPlan/static/AKPlan/fullcalendar/moment-timezone/main.js b/AKPlan/static/AKPlan/fullcalendar/moment-timezone/main.js new file mode 100644 index 00000000..b5d2897c --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/moment-timezone/main.js @@ -0,0 +1,64 @@ +/*! +FullCalendar Moment Timezone Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('moment'), require('moment-timezone/builds/moment-timezone-with-data'), require('@fullcalendar/core')) : + typeof define === 'function' && define.amd ? define(['exports', 'moment', 'moment-timezone/builds/moment-timezone-with-data', '@fullcalendar/core'], factory) : + (global = global || self, factory(global.FullCalendarMomentTimezone = {}, global.moment, global.moment, global.FullCalendar)); +}(this, function (exports, momentNs, momentTimezoneWithData, core) { 'use strict'; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + var moment = momentNs; // the directly callable function + var MomentNamedTimeZone = /** @class */ (function (_super) { + __extends(MomentNamedTimeZone, _super); + function MomentNamedTimeZone() { + return _super !== null && _super.apply(this, arguments) || this; + } + MomentNamedTimeZone.prototype.offsetForArray = function (a) { + return moment.tz(a, this.timeZoneName).utcOffset(); + }; + MomentNamedTimeZone.prototype.timestampToArray = function (ms) { + return moment.tz(ms, this.timeZoneName).toArray(); + }; + return MomentNamedTimeZone; + }(core.NamedTimeZoneImpl)); + var main = core.createPlugin({ + namedTimeZonedImpl: MomentNamedTimeZone + }); + + exports.default = main; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/moment-timezone/main.min.js b/AKPlan/static/AKPlan/fullcalendar/moment-timezone/main.min.js new file mode 100644 index 00000000..d9ee66c0 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/moment-timezone/main.min.js @@ -0,0 +1,6 @@ +/*! +FullCalendar Moment Timezone Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("moment"),require("moment-timezone/builds/moment-timezone-with-data"),require("@fullcalendar/core")):"function"==typeof define&&define.amd?define(["exports","moment","moment-timezone/builds/moment-timezone-with-data","@fullcalendar/core"],t):t((e=e||self).FullCalendarMomentTimezone={},e.moment,e.moment,e.FullCalendar)}(this,function(e,t,n,o){"use strict";var r=function(e,t){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)};var i=t,u=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}(t,e),t.prototype.offsetForArray=function(e){return i.tz(e,this.timeZoneName).utcOffset()},t.prototype.timestampToArray=function(e){return i.tz(e,this.timeZoneName).toArray()},t}(o.NamedTimeZoneImpl),m=o.createPlugin({namedTimeZonedImpl:u});e.default=m,Object.defineProperty(e,"__esModule",{value:!0})}); \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/moment-timezone/package.json b/AKPlan/static/AKPlan/fullcalendar/moment-timezone/package.json new file mode 100644 index 00000000..b875029c --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/moment-timezone/package.json @@ -0,0 +1,35 @@ +{ + "name": "@fullcalendar/moment-timezone", + "version": "4.3.0", + "title": "FullCalendar Moment Timezone Plugin", + "description": "A connector to the moment-timezone library", + "keywords": [ + "calendar", + "event", + "full-sized" + ], + "homepage": "https://fullcalendar.io/", + "docs": "https://fullcalendar.io/docs/moment-plugins#moment-timezone", + "bugs": "https://fullcalendar.io/reporting-bugs", + "repository": { + "type": "git", + "url": "https://github.com/fullcalendar/fullcalendar.git", + "homepage": "https://github.com/fullcalendar/fullcalendar" + }, + "license": "MIT", + "author": { + "name": "Adam Shaw", + "email": "arshaw@arshaw.com", + "url": "http://arshaw.com/" + }, + "copyright": "2019 Adam Shaw", + "peerDependencies": { + "@fullcalendar/core": "~4.3.0", + "moment": "^2.24.0", + "moment-timezone": "^0.5.25" + }, + "main": "main.js", + "module": "main.esm.js", + "unpkg": "main.min.js", + "types": "main.d.ts" +} diff --git a/AKPlan/static/AKPlan/fullcalendar/moment/LICENSE.txt b/AKPlan/static/AKPlan/fullcalendar/moment/LICENSE.txt new file mode 100644 index 00000000..2149cfbe --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/moment/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2019 Adam Shaw + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/AKPlan/static/AKPlan/fullcalendar/moment/README.md b/AKPlan/static/AKPlan/fullcalendar/moment/README.md new file mode 100644 index 00000000..854e4367 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/moment/README.md @@ -0,0 +1,8 @@ + +# FullCalendar Moment Plugin + +A connector to the MomentJS date library + +[View the docs »](https://fullcalendar.io/docs/moment-plugins) + +This package was created from the [FullCalendar monorepo »](https://github.com/fullcalendar/fullcalendar) diff --git a/AKPlan/static/AKPlan/fullcalendar/moment/main.d.ts b/AKPlan/static/AKPlan/fullcalendar/moment/main.d.ts new file mode 100644 index 00000000..cc81dab6 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/moment/main.d.ts @@ -0,0 +1,14 @@ +// Generated by dts-bundle v0.7.3-fork.1 +// Dependencies for this module: +// ../../../../../moment +// ../../../../../@fullcalendar/core + +declare module '@fullcalendar/moment' { + import * as momentNs from 'moment'; + import { Calendar, Duration } from '@fullcalendar/core'; + export function toMoment(date: Date, calendar: Calendar): momentNs.Moment; + export function toDuration(fcDuration: Duration): momentNs.Duration; + const _default: import("@fullcalendar/core").PluginDef; + export default _default; +} + diff --git a/AKPlan/static/AKPlan/fullcalendar/moment/main.esm.js b/AKPlan/static/AKPlan/fullcalendar/moment/main.esm.js new file mode 100644 index 00000000..f5addb72 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/moment/main.esm.js @@ -0,0 +1,102 @@ +/*! +FullCalendar Moment Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +import * as momentNs from 'moment'; +import { createPlugin, Calendar } from '@fullcalendar/core'; + +var moment = momentNs; // the directly callable function +function toMoment(date, calendar) { + if (!(calendar instanceof Calendar)) { + throw new Error('must supply a Calendar instance'); + } + return convertToMoment(date, calendar.dateEnv.timeZone, null, calendar.dateEnv.locale.codes[0]); +} +function toDuration(fcDuration) { + return moment.duration(fcDuration); // moment accepts all the props that fc.Duration already has! +} +function formatWithCmdStr(cmdStr, arg) { + var cmd = parseCmdStr(cmdStr); + if (arg.end) { + var startMom = convertToMoment(arg.start.array, arg.timeZone, arg.start.timeZoneOffset, arg.localeCodes[0]); + var endMom = convertToMoment(arg.end.array, arg.timeZone, arg.end.timeZoneOffset, arg.localeCodes[0]); + return formatRange(cmd, createMomentFormatFunc(startMom), createMomentFormatFunc(endMom), arg.separator); + } + return convertToMoment(arg.date.array, arg.timeZone, arg.date.timeZoneOffset, arg.localeCodes[0]).format(cmd.whole); // TODO: test for this +} +var main = createPlugin({ + cmdFormatter: formatWithCmdStr +}); +function createMomentFormatFunc(mom) { + return function (cmdStr) { + return cmdStr ? mom.format(cmdStr) : ''; // because calling with blank string results in ISO8601 :( + }; +} +function convertToMoment(input, timeZone, timeZoneOffset, locale) { + var mom; + if (timeZone === 'local') { + mom = moment(input); + } + else if (timeZone === 'UTC') { + mom = moment.utc(input); + } + else if (moment.tz) { + mom = moment.tz(input, timeZone); + } + else { + mom = moment.utc(input); + if (timeZoneOffset != null) { + mom.utcOffset(timeZoneOffset); + } + } + mom.locale(locale); + return mom; +} +function parseCmdStr(cmdStr) { + var parts = cmdStr.match(/^(.*?)\{(.*)\}(.*)$/); // TODO: lookbehinds for escape characters + if (parts) { + var middle = parseCmdStr(parts[2]); + return { + head: parts[1], + middle: middle, + tail: parts[3], + whole: parts[1] + middle.whole + parts[3] + }; + } + else { + return { + head: null, + middle: null, + tail: null, + whole: cmdStr + }; + } +} +function formatRange(cmd, formatStart, formatEnd, separator) { + if (cmd.middle) { + var startHead = formatStart(cmd.head); + var startMiddle = formatRange(cmd.middle, formatStart, formatEnd, separator); + var startTail = formatStart(cmd.tail); + var endHead = formatEnd(cmd.head); + var endMiddle = formatRange(cmd.middle, formatStart, formatEnd, separator); + var endTail = formatEnd(cmd.tail); + if (startHead === endHead && startTail === endTail) { + return startHead + + (startMiddle === endMiddle ? startMiddle : startMiddle + separator + endMiddle) + + startTail; + } + } + var startWhole = formatStart(cmd.whole); + var endWhole = formatEnd(cmd.whole); + if (startWhole === endWhole) { + return startWhole; + } + else { + return startWhole + separator + endWhole; + } +} + +export default main; +export { toDuration, toMoment }; diff --git a/AKPlan/static/AKPlan/fullcalendar/moment/main.js b/AKPlan/static/AKPlan/fullcalendar/moment/main.js new file mode 100644 index 00000000..aa8677c3 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/moment/main.js @@ -0,0 +1,110 @@ +/*! +FullCalendar Moment Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('moment'), require('@fullcalendar/core')) : + typeof define === 'function' && define.amd ? define(['exports', 'moment', '@fullcalendar/core'], factory) : + (global = global || self, factory(global.FullCalendarMoment = {}, global.moment, global.FullCalendar)); +}(this, function (exports, momentNs, core) { 'use strict'; + + var moment = momentNs; // the directly callable function + function toMoment(date, calendar) { + if (!(calendar instanceof core.Calendar)) { + throw new Error('must supply a Calendar instance'); + } + return convertToMoment(date, calendar.dateEnv.timeZone, null, calendar.dateEnv.locale.codes[0]); + } + function toDuration(fcDuration) { + return moment.duration(fcDuration); // moment accepts all the props that fc.Duration already has! + } + function formatWithCmdStr(cmdStr, arg) { + var cmd = parseCmdStr(cmdStr); + if (arg.end) { + var startMom = convertToMoment(arg.start.array, arg.timeZone, arg.start.timeZoneOffset, arg.localeCodes[0]); + var endMom = convertToMoment(arg.end.array, arg.timeZone, arg.end.timeZoneOffset, arg.localeCodes[0]); + return formatRange(cmd, createMomentFormatFunc(startMom), createMomentFormatFunc(endMom), arg.separator); + } + return convertToMoment(arg.date.array, arg.timeZone, arg.date.timeZoneOffset, arg.localeCodes[0]).format(cmd.whole); // TODO: test for this + } + var main = core.createPlugin({ + cmdFormatter: formatWithCmdStr + }); + function createMomentFormatFunc(mom) { + return function (cmdStr) { + return cmdStr ? mom.format(cmdStr) : ''; // because calling with blank string results in ISO8601 :( + }; + } + function convertToMoment(input, timeZone, timeZoneOffset, locale) { + var mom; + if (timeZone === 'local') { + mom = moment(input); + } + else if (timeZone === 'UTC') { + mom = moment.utc(input); + } + else if (moment.tz) { + mom = moment.tz(input, timeZone); + } + else { + mom = moment.utc(input); + if (timeZoneOffset != null) { + mom.utcOffset(timeZoneOffset); + } + } + mom.locale(locale); + return mom; + } + function parseCmdStr(cmdStr) { + var parts = cmdStr.match(/^(.*?)\{(.*)\}(.*)$/); // TODO: lookbehinds for escape characters + if (parts) { + var middle = parseCmdStr(parts[2]); + return { + head: parts[1], + middle: middle, + tail: parts[3], + whole: parts[1] + middle.whole + parts[3] + }; + } + else { + return { + head: null, + middle: null, + tail: null, + whole: cmdStr + }; + } + } + function formatRange(cmd, formatStart, formatEnd, separator) { + if (cmd.middle) { + var startHead = formatStart(cmd.head); + var startMiddle = formatRange(cmd.middle, formatStart, formatEnd, separator); + var startTail = formatStart(cmd.tail); + var endHead = formatEnd(cmd.head); + var endMiddle = formatRange(cmd.middle, formatStart, formatEnd, separator); + var endTail = formatEnd(cmd.tail); + if (startHead === endHead && startTail === endTail) { + return startHead + + (startMiddle === endMiddle ? startMiddle : startMiddle + separator + endMiddle) + + startTail; + } + } + var startWhole = formatStart(cmd.whole); + var endWhole = formatEnd(cmd.whole); + if (startWhole === endWhole) { + return startWhole; + } + else { + return startWhole + separator + endWhole; + } + } + + exports.default = main; + exports.toDuration = toDuration; + exports.toMoment = toMoment; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/moment/main.min.js b/AKPlan/static/AKPlan/fullcalendar/moment/main.min.js new file mode 100644 index 00000000..4dd2cadb --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/moment/main.min.js @@ -0,0 +1,6 @@ +/*! +FullCalendar Moment Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("moment"),require("@fullcalendar/core")):"function"==typeof define&&define.amd?define(["exports","moment","@fullcalendar/core"],t):t((e=e||self).FullCalendarMoment={},e.moment,e.FullCalendar)}(this,function(e,t,n){"use strict";var r=t;var a=n.createPlugin({cmdFormatter:function(e,t){var n=function e(t){var n=t.match(/^(.*?)\{(.*)\}(.*)$/);if(n){var r=e(n[2]);return{head:n[1],middle:r,tail:n[3],whole:n[1]+r.whole+n[3]}}return{head:null,middle:null,tail:null,whole:t}}(e);if(t.end){var r=l(t.start.array,t.timeZone,t.start.timeZoneOffset,t.localeCodes[0]),a=l(t.end.array,t.timeZone,t.end.timeZoneOffset,t.localeCodes[0]);return function e(t,n,r,a){if(t.middle){var o=n(t.head),l=e(t.middle,n,r,a),u=n(t.tail),i=r(t.head),d=e(t.middle,n,r,a),f=r(t.tail);if(o===i&&u===f)return o+(l===d?l:l+a+d)+u}var c=n(t.whole),m=r(t.whole);return c===m?c:c+a+m}(n,o(r),o(a),t.separator)}return l(t.date.array,t.timeZone,t.date.timeZoneOffset,t.localeCodes[0]).format(n.whole)}});function o(e){return function(t){return t?e.format(t):""}}function l(e,t,n,a){var o;return"local"===t?o=r(e):"UTC"===t?o=r.utc(e):r.tz?o=r.tz(e,t):(o=r.utc(e),null!=n&&o.utcOffset(n)),o.locale(a),o}e.default=a,e.toDuration=function(e){return r.duration(e)},e.toMoment=function(e,t){if(!(t instanceof n.Calendar))throw new Error("must supply a Calendar instance");return l(e,t.dateEnv.timeZone,null,t.dateEnv.locale.codes[0])},Object.defineProperty(e,"__esModule",{value:!0})}); \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/moment/package.json b/AKPlan/static/AKPlan/fullcalendar/moment/package.json new file mode 100644 index 00000000..741d178d --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/moment/package.json @@ -0,0 +1,34 @@ +{ + "name": "@fullcalendar/moment", + "version": "4.3.0", + "title": "FullCalendar Moment Plugin", + "description": "A connector to the MomentJS date library", + "keywords": [ + "calendar", + "event", + "full-sized" + ], + "homepage": "https://fullcalendar.io/", + "docs": "https://fullcalendar.io/docs/moment-plugins", + "bugs": "https://fullcalendar.io/reporting-bugs", + "repository": { + "type": "git", + "url": "https://github.com/fullcalendar/fullcalendar.git", + "homepage": "https://github.com/fullcalendar/fullcalendar" + }, + "license": "MIT", + "author": { + "name": "Adam Shaw", + "email": "arshaw@arshaw.com", + "url": "http://arshaw.com/" + }, + "copyright": "2019 Adam Shaw", + "peerDependencies": { + "@fullcalendar/core": "~4.3.0", + "moment": "^2.24.0" + }, + "main": "main.js", + "module": "main.esm.js", + "unpkg": "main.min.js", + "types": "main.d.ts" +} diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-common/LICENSE.md b/AKPlan/static/AKPlan/fullcalendar/resource-common/LICENSE.md new file mode 100644 index 00000000..52296639 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-common/LICENSE.md @@ -0,0 +1,18 @@ + +For complete licensing information, visit: +http://fullcalendar.io/scheduler/license + +FullCalendar Scheduler is tri-licensed, meaning you must choose +one of three licenses to use. Here is a summary of those licenses: + +- Commercial License + (a paid license, meant for commercial use) + http://fullcalendar.io/scheduler/license-details + +- Creative Commons Non-Commercial No-Derivatives + (meant for trial and non-commercial use) + https://creativecommons.org/licenses/by-nc-nd/4.0/ + +- GPLv3 License + (meant for open-source projects) + http://www.gnu.org/licenses/gpl-3.0.en.html diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-common/README.md b/AKPlan/static/AKPlan/fullcalendar/resource-common/README.md new file mode 100644 index 00000000..ddc4db04 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-common/README.md @@ -0,0 +1,8 @@ + +# FullCalendar Resources Common Plugin + +Offers base support for resources. Required for all resource-related plugins. + +[View the docs »](https://fullcalendar.io/docs/scheduler) + +This package was created from the [FullCalendar monorepo »](https://github.com/fullcalendar/fullcalendar-scheduler) diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-common/main.d.ts b/AKPlan/static/AKPlan/fullcalendar/resource-common/main.d.ts new file mode 100644 index 00000000..14ed2f1d --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-common/main.d.ts @@ -0,0 +1,487 @@ +// Generated by dts-bundle v0.7.3-fork.1 +// Dependencies for this module: +// ambient.d.ts + +declare module '@fullcalendar/resource-common' { + import '@fullcalendar/resource-common/ambient'; + import '@fullcalendar/resource-common/api/EventApi'; + import '@fullcalendar/resource-common/resource-sources/resource-array'; + import '@fullcalendar/resource-common/resource-sources/resource-func'; + import '@fullcalendar/resource-common/resource-sources/resource-json-feed'; + const _default: import("@fullcalendar/core").PluginDef; + export default _default; + export { default as ResourceDayHeader } from '@fullcalendar/resource-common/common/ResourceDayHeader'; + export { VResourceJoiner, AbstractResourceDayTable, ResourceDayTable, DayResourceTable, VResourceSplitter } from '@fullcalendar/resource-common/common/resource-day-table'; + export { Resource, ResourceHash } from '@fullcalendar/resource-common/structs/resource'; + export { ResourceViewProps } from '@fullcalendar/resource-common/View'; + export { flattenResources, Group, isGroupsEqual, GroupNode, ResourceNode, buildRowNodes, buildResourceFields } from '@fullcalendar/resource-common/common/resource-hierarchy'; + export { buildResourceTextFunc } from '@fullcalendar/resource-common/common/resource-rendering'; + export { default as ResourceApi } from '@fullcalendar/resource-common/api/ResourceApi'; + export { default as ResourceSplitter } from '@fullcalendar/resource-common/common/ResourceSplitter'; +} + +declare module '@fullcalendar/resource-common/ambient' { + import ResourceApi from '@fullcalendar/resource-common/api/ResourceApi'; + import { ResourceSourceInput, ResourceSource } from '@fullcalendar/resource-common/structs/resource-source'; + import { View } from '@fullcalendar/core'; + import { ResourceHash } from '@fullcalendar/resource-common/structs/resource'; + import { ResourceEntityExpansions } from '@fullcalendar/resource-common/reducers/resourceEntityExpansions'; + import { ResourceAction } from '@fullcalendar/resource-common/reducers/resources'; + module '@fullcalendar/core' { + interface Calendar { + addResource(input: ResourceSourceInput): ResourceApi; + getResourceById(id: string): ResourceApi | null; + getResources(): ResourceApi[]; + getTopLevelResources(): ResourceApi[]; + rerenderResources(): void; + refetchResources(): void; + } + interface Calendar { + dispatch(action: ResourceAction): any; + } + interface CalendarState { + resourceSource?: ResourceSource | null; + resourceStore?: ResourceHash; + resourceEntityExpansions?: ResourceEntityExpansions; + } + interface OptionsInput { + schedulerLicenseKey?: string; + resources?: ResourceSourceInput; + resourceLabelText?: string; + resourceOrder?: any; + filterResourcesWithEvents?: any; + resourceText?: any; + resourceGroupField?: any; + resourceGroupText?: any; + resourceAreaWidth?: any; + resourceColumns?: any; + resourcesInitiallyExpanded?: any; + slotWidth?: any; + datesAboveResources?: any; + eventResourceEditable?: boolean; + refetchResourcesOnNavigate?: boolean; + resourceRender?(arg: { + resource: ResourceApi; + el: HTMLElement; + view: View; + }): void; + } + interface DatePointApi { + resource?: ResourceApi; + } + interface DateSpanApi { + resource?: ResourceApi; + } + interface EventMutation { + resourceMutation?: { + matchResourceId: string; + setResourceId: string; + }; + } + interface EventApi { + getResources: () => ResourceApi[]; + setResources: (resources: (string | ResourceApi)[]) => void; + } + interface EventDef { + resourceIds: string[]; + resourceEditable: boolean; + } + } +} + +declare module '@fullcalendar/resource-common/api/EventApi' { + import '@fullcalendar/resource-common/ambient'; +} + +declare module '@fullcalendar/resource-common/resource-sources/resource-array' { + export {}; +} + +declare module '@fullcalendar/resource-common/resource-sources/resource-func' { + import { ResourceSourceError } from '@fullcalendar/resource-common/structs/resource-source'; + import { ResourceInput } from '@fullcalendar/resource-common/structs/resource'; + export type ResourceFunc = (arg: { + start: Date; + end: Date; + timeZone: string; + }, successCallback: (events: ResourceInput[]) => void, failureCallback: (errorObj: ResourceSourceError) => void) => any; +} + +declare module '@fullcalendar/resource-common/resource-sources/resource-json-feed' { + export {}; +} + +declare module '@fullcalendar/resource-common/common/ResourceDayHeader' { + import { Component, ComponentContext, DateMarker, DateProfile, DateFormatter } from '@fullcalendar/core'; + import { Resource } from '@fullcalendar/resource-common/structs/resource'; + export interface ResourceDayHeaderProps { + dates: DateMarker[]; + dateProfile: DateProfile; + datesRepDistinctDays: boolean; + resources: Resource[]; + renderIntroHtml?: () => string; + } + export { ResourceDayHeader as default, ResourceDayHeader }; + class ResourceDayHeader extends Component<ResourceDayHeaderProps> { + datesAboveResources: boolean; + resourceTextFunc: (resource: Resource) => string; + dateFormat: DateFormatter; + el: HTMLElement; + thead: HTMLElement; + constructor(context: ComponentContext, parentEl: HTMLElement); + destroy(): void; + render(props: ResourceDayHeaderProps): void; + renderResourceRow(resources: Resource[]): string; + renderDayAndResourceRows(dates: DateMarker[], resources: Resource[]): string; + renderResourceAndDayRows(resources: Resource[], dates: DateMarker[]): string; + renderResourceCell(resource: Resource, colspan: number, date?: DateMarker): string; + renderDateCell(date: DateMarker, colspan: number, resource?: Resource): string; + buildTr(cellHtmls: string[]): string; + processResourceEls(resources: Resource[]): void; + } +} + +declare module '@fullcalendar/resource-common/common/resource-day-table' { + import { SlicedProps, EventDef, Splitter, DayTable, DayTableCell, SplittableProps, DateSpan, Seg, EventSegUiInteractionState } from '@fullcalendar/core'; + import { Resource } from '@fullcalendar/resource-common/structs/resource'; + export interface ResourceDayTableCell extends DayTableCell { + resource: Resource; + } + export abstract class AbstractResourceDayTable { + cells: ResourceDayTableCell[][]; + rowCnt: number; + colCnt: number; + dayTable: DayTable; + resources: Resource[]; + resourceIndex: ResourceIndex; + constructor(dayTable: DayTable, resources: Resource[]); + abstract computeCol(dateI: any, resourceI: any): number; + abstract computeColRanges(dateStartI: any, dateEndI: any, resourceI: any): { + firstCol: number; + lastCol: number; + isStart: boolean; + isEnd: boolean; + }[]; + buildCells(): ResourceDayTableCell[][]; + } + export class ResourceDayTable extends AbstractResourceDayTable { + computeCol(dateI: any, resourceI: any): any; + computeColRanges(dateStartI: any, dateEndI: any, resourceI: any): { + firstCol: any; + lastCol: any; + isStart: boolean; + isEnd: boolean; + }[]; + } + export class DayResourceTable extends AbstractResourceDayTable { + computeCol(dateI: any, resourceI: any): any; + computeColRanges(dateStartI: any, dateEndI: any, resourceI: any): any[]; + } + export class ResourceIndex { + indicesById: { + [resourceId: string]: number; + }; + ids: string[]; + length: number; + constructor(resources: Resource[]); + } + export interface VResourceProps extends SplittableProps { + resourceDayTable: AbstractResourceDayTable; + } + export class VResourceSplitter extends Splitter<VResourceProps> { + getKeyInfo(props: VResourceProps): any; + getKeysForDateSpan(dateSpan: DateSpan): string[]; + getKeysForEventDef(eventDef: EventDef): string[]; + } + export abstract class VResourceJoiner<SegType extends Seg> { + joinProps(propSets: { + [resourceId: string]: SlicedProps<SegType>; + }, resourceDayTable: AbstractResourceDayTable): SlicedProps<SegType>; + joinSegs(resourceDayTable: AbstractResourceDayTable, ...segGroups: SegType[][]): SegType[]; + expandSegs(resourceDayTable: AbstractResourceDayTable, segs: SegType[]): any[]; + joinInteractions(resourceDayTable: AbstractResourceDayTable, ...interactions: EventSegUiInteractionState[]): EventSegUiInteractionState; + abstract transformSeg(seg: SegType, resourceDayTable: AbstractResourceDayTable, resourceI: number): SegType[]; + } +} + +declare module '@fullcalendar/resource-common/structs/resource' { + import { ConstraintInput, AllowFunc, EventStore, Calendar, EventUi, BusinessHoursInput } from '@fullcalendar/core'; + export interface ResourceInput { + id?: string; + parentId?: string; + children?: ResourceInput[]; + title?: string; + businessHours?: BusinessHoursInput; + eventEditable?: boolean; + eventStartEditable?: boolean; + eventDurationEditable?: boolean; + eventConstraint?: ConstraintInput; + eventOverlap?: boolean; + eventAllow?: AllowFunc; + eventClassName?: string[] | string; + eventClassNames?: string[] | string; + eventBackgroundColor?: string; + eventBorderColor?: string; + eventTextColor?: string; + eventColor?: string; + extendedProps?: { + [extendedProp: string]: any; + }; + [otherProp: string]: any; + } + export interface Resource { + id: string; + parentId: string; + title: string; + businessHours: EventStore | null; + ui: EventUi; + extendedProps: { + [extendedProp: string]: any; + }; + } + export type ResourceHash = { + [resourceId: string]: Resource; + }; + export function parseResource(input: ResourceInput, parentId: string, store: ResourceHash, calendar: Calendar): Resource; + export function getPublicId(id: string): string; +} + +declare module '@fullcalendar/resource-common/View' { + import { View, ViewProps, ViewSpec, ViewPropsTransformer, CalendarComponentProps, EventUi, EventUiHash, EventDefHash, EventDef, EventStore, DateRange } from '@fullcalendar/core'; + import { ResourceHash } from '@fullcalendar/resource-common/structs/resource'; + import { ResourceEntityExpansions } from '@fullcalendar/resource-common/reducers/resourceEntityExpansions'; + export interface ResourceViewProps extends ViewProps { + resourceStore: ResourceHash; + resourceEntityExpansions: ResourceEntityExpansions; + } + export class ResourceDataAdder implements ViewPropsTransformer { + filterResources: typeof filterResources; + transform(viewProps: ViewProps, viewSpec: ViewSpec, calendarProps: CalendarComponentProps, view: View): { + resourceStore: ResourceHash; + resourceEntityExpansions: ResourceEntityExpansions; + }; + } + function filterResources(resourceStore: ResourceHash, doFilterResourcesWithEvents: boolean, eventStore: EventStore, activeRange: DateRange): ResourceHash; + export class ResourceEventConfigAdder implements ViewPropsTransformer { + buildResourceEventUis: typeof buildResourceEventUis; + injectResourceEventUis: typeof injectResourceEventUis; + transform(viewProps: ViewProps, viewSpec: ViewSpec, calendarProps: CalendarComponentProps): { + eventUiBases: { + [key: string]: EventUi; + }; + }; + } + function buildResourceEventUis(resourceStore: ResourceHash): { + [key: string]: EventUi; + }; + function injectResourceEventUis(eventUiBases: EventUiHash, eventDefs: EventDefHash, resourceEventUis: EventUiHash): { + [key: string]: EventUi; + }; + export function transformIsDraggable(val: boolean, eventDef: EventDef, eventUi: EventUi, view: View): boolean; + export {}; +} + +declare module '@fullcalendar/resource-common/common/resource-hierarchy' { + import { ResourceHash, Resource } from '@fullcalendar/resource-common/structs/resource'; + import { ResourceEntityExpansions } from '@fullcalendar/resource-common/reducers/resourceEntityExpansions'; + export interface Group { + value: any; + spec: any; + } + export interface GroupNode { + id: string; + isExpanded: boolean; + group: Group; + } + export interface ResourceNode { + id: string; + rowSpans: number[]; + depth: number; + isExpanded: boolean; + hasChildren: boolean; + resource: Resource; + resourceFields: any; + } + export function flattenResources(resourceStore: ResourceHash, orderSpecs: any): Resource[]; + export function buildRowNodes(resourceStore: ResourceHash, groupSpecs: any, orderSpecs: any, isVGrouping: boolean, expansions: ResourceEntityExpansions, expansionDefault: boolean): (GroupNode | ResourceNode)[]; + export function buildResourceFields(resource: Resource): { + id: string; + parentId: string; + title: string; + businessHours: import("@fullcalendar/core").EventStore; + ui: import("@fullcalendar/core").EventUi; + extendedProps: { + [extendedProp: string]: any; + }; + startEditable: boolean; + durationEditable: boolean; + constraints: import("@fullcalendar/core").Constraint[]; + overlap: boolean; + allows: import("@fullcalendar/core").AllowFunc[]; + backgroundColor: string; + borderColor: string; + textColor: string; + classNames: string[]; + }; + export function isGroupsEqual(group0: Group, group1: Group): boolean; +} + +declare module '@fullcalendar/resource-common/common/resource-rendering' { + import { Resource } from '@fullcalendar/resource-common/structs/resource'; + export function buildResourceTextFunc(resourceTextSetting: any, calendar: any): (resource: Resource) => any; +} + +declare module '@fullcalendar/resource-common/api/ResourceApi' { + import { Calendar, EventApi } from '@fullcalendar/core'; + import { Resource } from '@fullcalendar/resource-common/structs/resource'; + export { ResourceApi as default, ResourceApi }; + class ResourceApi { + _calendar: Calendar; + _resource: Resource; + constructor(calendar: Calendar, rawResource: Resource); + setProp(name: string, value: any): void; + remove(): void; + getParent(): ResourceApi | null; + getChildren(): ResourceApi[]; + getEvents(): EventApi[]; + readonly id: string; + readonly title: string; + readonly eventConstraint: any; + readonly eventOverlap: any; + readonly eventAllow: any; + readonly eventBackgroundColor: string; + readonly eventBorderColor: string; + readonly eventTextColor: string; + readonly eventClassNames: string[]; + readonly extendedProps: any; + } +} + +declare module '@fullcalendar/resource-common/common/ResourceSplitter' { + import { Splitter, SplittableProps, DateSpan, EventDef } from '@fullcalendar/core'; + import { ResourceHash } from '@fullcalendar/resource-common/structs/resource'; + export interface SplittableResourceProps extends SplittableProps { + resourceStore: ResourceHash; + } + export { ResourceSplitter as default, ResourceSplitter }; + class ResourceSplitter extends Splitter<SplittableResourceProps> { + getKeyInfo(props: SplittableResourceProps): { + '': {}; + }; + getKeysForDateSpan(dateSpan: DateSpan): string[]; + getKeysForEventDef(eventDef: EventDef): string[]; + } +} + +declare module '@fullcalendar/resource-common/structs/resource-source' { + import { DateRange, Calendar } from '@fullcalendar/core'; + import { ResourceInput } from '@fullcalendar/resource-common/structs/resource'; + import { ResourceFunc } from '@fullcalendar/resource-common/resource-sources/resource-func'; + export type ResourceSourceError = { + message: string; + xhr?: XMLHttpRequest; + [otherProp: string]: any; + }; + export type ResourceFetcher = (arg: { + resourceSource: ResourceSource; + calendar: Calendar; + range: DateRange | null; + }, success: (res: { + rawResources: ResourceInput[]; + xhr?: XMLHttpRequest; + }) => void, failure: (error: ResourceSourceError) => void) => void; + export interface ExtendedResourceSourceInput { + id?: string; + resources?: ResourceInput[]; + url?: string; + method?: string; + extraParams?: object | (() => object); + } + export type ResourceSourceInput = ResourceInput[] | ExtendedResourceSourceInput | ResourceFunc | string; + export interface ResourceSource { + _raw: any; + sourceId: string; + sourceDefId: number; + meta: any; + publicId: string; + isFetching: boolean; + latestFetchId: string; + fetchRange: DateRange | null; + } + export interface ResourceSourceDef { + ignoreRange?: boolean; + parseMeta: (raw: ResourceSourceInput) => object | null; + fetch: ResourceFetcher; + } + export function registerResourceSourceDef(def: ResourceSourceDef): void; + export function getResourceSourceDef(id: number): ResourceSourceDef; + export function doesSourceIgnoreRange(source: ResourceSource): boolean; + export function parseResourceSource(input: ResourceSourceInput): ResourceSource; +} + +declare module '@fullcalendar/resource-common/reducers/resourceEntityExpansions' { + import { ResourceAction } from '@fullcalendar/resource-common/reducers/resources'; + export type ResourceEntityExpansions = { + [id: string]: boolean; + }; + export function reduceResourceEntityExpansions(expansions: ResourceEntityExpansions, action: ResourceAction): ResourceEntityExpansions; +} + +declare module '@fullcalendar/resource-common/reducers/resources' { + import { Calendar, CalendarState, Action, DateRange } from '@fullcalendar/core'; + import { ResourceSourceError } from '@fullcalendar/resource-common/structs/resource-source'; + import { ResourceHash, ResourceInput } from '@fullcalendar/resource-common/structs/resource'; + export type ResourceAction = Action | { + type: 'FETCH_RESOURCE'; + } | { + type: 'RECEIVE_RESOURCES'; + rawResources: ResourceInput[]; + fetchId: string; + fetchRange: DateRange | null; + } | { + type: 'RECEIVE_RESOURCE_ERROR'; + error: ResourceSourceError; + fetchId: string; + fetchRange: DateRange | null; + } | { + type: 'ADD_RESOURCE'; + resourceHash: ResourceHash; + } | // use a hash because needs to accept children + { + type: 'REMOVE_RESOURCE'; + resourceId: string; + } | { + type: 'SET_RESOURCE_PROP'; + resourceId: string; + propName: string; + propValue: any; + } | { + type: 'SET_RESOURCE_ENTITY_EXPANDED'; + id: string; + isExpanded: boolean; + } | { + type: 'RESET_RESOURCES'; + } | { + type: 'RESET_RESOURCE_SOURCE'; + resourceSourceInput: any; + } | { + type: 'REFETCH_RESOURCES'; + }; + export default function (state: CalendarState, action: ResourceAction, calendar: Calendar): { + resourceSource: import("@fullcalendar/resource-common/structs/resource-source").ResourceSource; + resourceStore: ResourceHash; + resourceEntityExpansions: import("@fullcalendar/resource-common/reducers/resourceEntityExpansions").ResourceEntityExpansions; + eventSources: import("@fullcalendar/core").EventSourceHash; + eventSourceLoadingLevel: number; + loadingLevel: number; + viewType: string; + currentDate: Date; + dateProfile: import("@fullcalendar/core").DateProfile; + eventStore: import("@fullcalendar/core").EventStore; + dateSelection: import("@fullcalendar/core").DateSpan; + eventSelection: string; + eventDrag: import("@fullcalendar/core").EventInteractionState; + eventResize: import("@fullcalendar/core").EventInteractionState; + }; +} + diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-common/main.esm.js b/AKPlan/static/AKPlan/fullcalendar/resource-common/main.esm.js new file mode 100644 index 00000000..36f3dede --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-common/main.esm.js @@ -0,0 +1,1562 @@ +/*! +FullCalendar Resources Common Plugin v4.3.1 +Docs & License: https://fullcalendar.io/scheduler +(c) 2019 Adam Shaw +*/ + +import { memoize, filterHash, rangesIntersect, memoizeOutput, isPropsEqual, mapHash, combineEventUis, refineProps, rangesEqual, processScopedUiProps, parseBusinessHours, EventApi, Calendar, Splitter, mergeEventStores, isPropsValid, appendToElement, htmlEscape, cssToStr, config, isValidDate, addDays, unpromisify, requestJson, htmlToElement, removeElement, createFormatter, computeFallbackHeaderFormat, renderDateCell, findElements, Component, flexibleCompare, compareByFieldSpecs, createPlugin } from '@fullcalendar/core'; + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} + +var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; + +function massageEventDragMutation(eventMutation, hit0, hit1) { + var resource0 = hit0.dateSpan.resourceId; + var resource1 = hit1.dateSpan.resourceId; + if (resource0 && resource1 && + resource0 !== resource1) { + eventMutation.resourceMutation = { + matchResourceId: resource0, + setResourceId: resource1 + }; + } +} +/* +TODO: all this would be much easier if we were using a hash! +*/ +function applyEventDefMutation(eventDef, mutation, calendar) { + var resourceMutation = mutation.resourceMutation; + if (resourceMutation && computeResourceEditable(eventDef, calendar)) { + var index = eventDef.resourceIds.indexOf(resourceMutation.matchResourceId); + if (index !== -1) { + var resourceIds = eventDef.resourceIds.slice(); // copy + resourceIds.splice(index, 1); // remove + if (resourceIds.indexOf(resourceMutation.setResourceId) === -1) { // not already in there + resourceIds.push(resourceMutation.setResourceId); // add + } + eventDef.resourceIds = resourceIds; + } + } +} +/* +HACK +TODO: use EventUi system instead of this +*/ +function computeResourceEditable(eventDef, calendar) { + var resourceEditable = eventDef.resourceEditable; + if (resourceEditable == null) { + var source = eventDef.sourceId && calendar.state.eventSources[eventDef.sourceId]; + if (source) { + resourceEditable = source.extendedProps.resourceEditable; // used the Source::extendedProps hack + } + if (resourceEditable == null) { + resourceEditable = calendar.opt('eventResourceEditable'); + if (resourceEditable == null) { + resourceEditable = calendar.opt('editable'); // TODO: use defaults system instead + } + } + } + return resourceEditable; +} +function transformEventDrop(mutation, calendar) { + var resourceMutation = mutation.resourceMutation; + if (resourceMutation) { + return { + oldResource: calendar.getResourceById(resourceMutation.matchResourceId), + newResource: calendar.getResourceById(resourceMutation.setResourceId) + }; + } + else { + return { + oldResource: null, + newResource: null + }; + } +} + +var ResourceDataAdder = /** @class */ (function () { + function ResourceDataAdder() { + this.filterResources = memoize(filterResources); + } + ResourceDataAdder.prototype.transform = function (viewProps, viewSpec, calendarProps, view) { + if (viewSpec.class.needsResourceData) { + return { + resourceStore: this.filterResources(calendarProps.resourceStore, view.opt('filterResourcesWithEvents'), calendarProps.eventStore, calendarProps.dateProfile.activeRange), + resourceEntityExpansions: calendarProps.resourceEntityExpansions + }; + } + }; + return ResourceDataAdder; +}()); +function filterResources(resourceStore, doFilterResourcesWithEvents, eventStore, activeRange) { + if (doFilterResourcesWithEvents) { + var instancesInRange = filterEventInstancesInRange(eventStore.instances, activeRange); + var hasEvents_1 = computeHasEvents(instancesInRange, eventStore.defs); + __assign(hasEvents_1, computeAncestorHasEvents(hasEvents_1, resourceStore)); + return filterHash(resourceStore, function (resource, resourceId) { + return hasEvents_1[resourceId]; + }); + } + else { + return resourceStore; + } +} +function filterEventInstancesInRange(eventInstances, activeRange) { + return filterHash(eventInstances, function (eventInstance) { + return rangesIntersect(eventInstance.range, activeRange); + }); +} +function computeHasEvents(eventInstances, eventDefs) { + var hasEvents = {}; + for (var instanceId in eventInstances) { + var instance = eventInstances[instanceId]; + for (var _i = 0, _a = eventDefs[instance.defId].resourceIds; _i < _a.length; _i++) { + var resourceId = _a[_i]; + hasEvents[resourceId] = true; + } + } + return hasEvents; +} +/* +mark resources as having events if any of their ancestors have them +NOTE: resourceStore might not have all the resources that hasEvents{} has keyed +*/ +function computeAncestorHasEvents(hasEvents, resourceStore) { + var res = {}; + for (var resourceId in hasEvents) { + var resource = void 0; + while ((resource = resourceStore[resourceId])) { + resourceId = resource.parentId; // now functioning as the parentId + if (resourceId) { + res[resourceId] = true; + } + else { + break; + } + } + } + return res; +} +// for when non-resource view should be given EventUi info (for event coloring/constraints based off of resource data) +var ResourceEventConfigAdder = /** @class */ (function () { + function ResourceEventConfigAdder() { + this.buildResourceEventUis = memoizeOutput(buildResourceEventUis, isPropsEqual); + this.injectResourceEventUis = memoize(injectResourceEventUis); + } + ResourceEventConfigAdder.prototype.transform = function (viewProps, viewSpec, calendarProps) { + if (!viewSpec.class.needsResourceData) { // is a non-resource view? + return { + eventUiBases: this.injectResourceEventUis(viewProps.eventUiBases, viewProps.eventStore.defs, this.buildResourceEventUis(calendarProps.resourceStore)) + }; + } + }; + return ResourceEventConfigAdder; +}()); +function buildResourceEventUis(resourceStore) { + return mapHash(resourceStore, function (resource) { + return resource.ui; + }); +} +function injectResourceEventUis(eventUiBases, eventDefs, resourceEventUis) { + return mapHash(eventUiBases, function (eventUi, defId) { + if (defId) { // not the '' key + return injectResourceEventUi(eventUi, eventDefs[defId], resourceEventUis); + } + else { + return eventUi; + } + }); +} +function injectResourceEventUi(origEventUi, eventDef, resourceEventUis) { + var parts = []; + // first resource takes precedence, which fights with the ordering of combineEventUis, thus the unshifts + for (var _i = 0, _a = eventDef.resourceIds; _i < _a.length; _i++) { + var resourceId = _a[_i]; + if (resourceEventUis[resourceId]) { + parts.unshift(resourceEventUis[resourceId]); + } + } + parts.unshift(origEventUi); + return combineEventUis(parts); +} +// for making sure events that have editable resources are always draggable in resource views +function transformIsDraggable(val, eventDef, eventUi, view) { + if (!val) { + if (view.viewSpec.class.needsResourceData) { + if (computeResourceEditable(eventDef, view.calendar)) { + return true; + } + } + } + return val; +} + +var RESOURCE_SOURCE_PROPS = { + id: String +}; +var defs = []; +var uid = 0; +function registerResourceSourceDef(def) { + defs.push(def); +} +function getResourceSourceDef(id) { + return defs[id]; +} +function doesSourceIgnoreRange(source) { + return Boolean(defs[source.sourceDefId].ignoreRange); +} +function parseResourceSource(input) { + for (var i = defs.length - 1; i >= 0; i--) { // later-added plugins take precedence + var def = defs[i]; + var meta = def.parseMeta(input); + if (meta) { + var res = parseResourceSourceProps((typeof input === 'object' && input) ? input : {}, meta, i); + res._raw = input; + return res; + } + } + return null; +} +function parseResourceSourceProps(input, meta, sourceDefId) { + var props = refineProps(input, RESOURCE_SOURCE_PROPS); + props.sourceId = String(uid++); + props.sourceDefId = sourceDefId; + props.meta = meta; + props.publicId = props.id; + props.isFetching = false; + props.latestFetchId = ''; + props.fetchRange = null; + delete props.id; + return props; +} + +function reduceResourceSource (source, action, dateProfile, calendar) { + switch (action.type) { + case 'INIT': + return createSource(calendar.opt('resources'), calendar); + case 'RESET_RESOURCE_SOURCE': + return createSource(action.resourceSourceInput, calendar, true); + case 'PREV': // TODO: how do we track all actions that affect dateProfile :( + case 'NEXT': + case 'SET_DATE': + case 'SET_VIEW_TYPE': + return handleRange(source, dateProfile.activeRange, calendar); + case 'RECEIVE_RESOURCES': + case 'RECEIVE_RESOURCE_ERROR': + return receiveResponse(source, action.fetchId, action.fetchRange); + case 'REFETCH_RESOURCES': + return fetchSource(source, dateProfile.activeRange, calendar); + default: + return source; + } +} +var uid$1 = 0; +function createSource(input, calendar, forceFetch) { + if (input) { + var source = parseResourceSource(input); + if (forceFetch || !calendar.opt('refetchResourcesOnNavigate')) { // because assumes handleRange will do it later + source = fetchSource(source, null, calendar); + } + return source; + } + return null; +} +function handleRange(source, activeRange, calendar) { + if (calendar.opt('refetchResourcesOnNavigate') && + !doesSourceIgnoreRange(source) && + (!source.fetchRange || !rangesEqual(source.fetchRange, activeRange))) { + return fetchSource(source, activeRange, calendar); + } + else { + return source; + } +} +function fetchSource(source, fetchRange, calendar) { + var sourceDef = getResourceSourceDef(source.sourceDefId); + var fetchId = String(uid$1++); + sourceDef.fetch({ + resourceSource: source, + calendar: calendar, + range: fetchRange + }, function (res) { + // HACK + // do before calling dispatch in case dispatch renders synchronously + calendar.afterSizingTriggers._resourcesRendered = [null]; // fire once + calendar.dispatch({ + type: 'RECEIVE_RESOURCES', + fetchId: fetchId, + fetchRange: fetchRange, + rawResources: res.rawResources + }); + }, function (error) { + calendar.dispatch({ + type: 'RECEIVE_RESOURCE_ERROR', + fetchId: fetchId, + fetchRange: fetchRange, + error: error + }); + }); + return __assign({}, source, { isFetching: true, latestFetchId: fetchId }); +} +function receiveResponse(source, fetchId, fetchRange) { + if (fetchId === source.latestFetchId) { + return __assign({}, source, { isFetching: false, fetchRange: fetchRange }); + } + return source; +} + +var RESOURCE_PROPS = { + id: String, + title: String, + parentId: String, + businessHours: null, + children: null, + extendedProps: null +}; +var PRIVATE_ID_PREFIX = '_fc:'; +var uid$2 = 0; +/* +needs a full store so that it can populate children too +*/ +function parseResource(input, parentId, store, calendar) { + if (parentId === void 0) { parentId = ''; } + var leftovers0 = {}; + var props = refineProps(input, RESOURCE_PROPS, {}, leftovers0); + var leftovers1 = {}; + var ui = processScopedUiProps('event', leftovers0, calendar, leftovers1); + if (!props.id) { + props.id = PRIVATE_ID_PREFIX + (uid$2++); + } + if (!props.parentId) { // give precedence to the parentId property + props.parentId = parentId; + } + props.businessHours = props.businessHours ? parseBusinessHours(props.businessHours, calendar) : null; + props.ui = ui; + props.extendedProps = __assign({}, leftovers1, props.extendedProps); + // help out ResourceApi from having user modify props + Object.freeze(ui.classNames); + Object.freeze(props.extendedProps); + if (store[props.id]) ; + else { + store[props.id] = props; + if (props.children) { + for (var _i = 0, _a = props.children; _i < _a.length; _i++) { + var childInput = _a[_i]; + parseResource(childInput, props.id, store, calendar); + } + delete props.children; + } + } + return props; +} +/* +TODO: use this in more places +*/ +function getPublicId(id) { + if (id.indexOf(PRIVATE_ID_PREFIX) === 0) { + return ''; + } + return id; +} + +function reduceResourceStore (store, action, source, calendar) { + switch (action.type) { + case 'INIT': + return {}; + case 'RECEIVE_RESOURCES': + return receiveRawResources(store, action.rawResources, action.fetchId, source, calendar); + case 'ADD_RESOURCE': + return addResource(store, action.resourceHash); + case 'REMOVE_RESOURCE': + return removeResource(store, action.resourceId); + case 'SET_RESOURCE_PROP': + return setResourceProp(store, action.resourceId, action.propName, action.propValue); + case 'RESET_RESOURCES': + // must make the calendar think each resource is a new object :/ + return mapHash(store, function (resource) { + return __assign({}, resource); + }); + default: + return store; + } +} +function receiveRawResources(existingStore, inputs, fetchId, source, calendar) { + if (source.latestFetchId === fetchId) { + var nextStore = {}; + for (var _i = 0, inputs_1 = inputs; _i < inputs_1.length; _i++) { + var input = inputs_1[_i]; + parseResource(input, '', nextStore, calendar); + } + return nextStore; + } + else { + return existingStore; + } +} +function addResource(existingStore, additions) { + // TODO: warn about duplicate IDs + return __assign({}, existingStore, additions); +} +function removeResource(existingStore, resourceId) { + var newStore = __assign({}, existingStore); + delete newStore[resourceId]; + // promote children + for (var childResourceId in newStore) { // a child, *maybe* but probably not + if (newStore[childResourceId].parentId === resourceId) { + newStore[childResourceId] = __assign({}, newStore[childResourceId], { parentId: '' }); + } + } + return newStore; +} +function setResourceProp(existingStore, resourceId, name, value) { + var _a, _b; + var existingResource = existingStore[resourceId]; + // TODO: sanitization + if (existingResource) { + return __assign({}, existingStore, (_a = {}, _a[resourceId] = __assign({}, existingResource, (_b = {}, _b[name] = value, _b)), _a)); + } + else { + return existingStore; + } +} + +function reduceResourceEntityExpansions(expansions, action) { + var _a; + switch (action.type) { + case 'INIT': + return {}; + case 'SET_RESOURCE_ENTITY_EXPANDED': + return __assign({}, expansions, (_a = {}, _a[action.id] = action.isExpanded, _a)); + default: + return expansions; + } +} + +function resourcesReducers (state, action, calendar) { + var resourceSource = reduceResourceSource(state.resourceSource, action, state.dateProfile, calendar); + var resourceStore = reduceResourceStore(state.resourceStore, action, resourceSource, calendar); + var resourceEntityExpansions = reduceResourceEntityExpansions(state.resourceEntityExpansions, action); + return __assign({}, state, { resourceSource: resourceSource, + resourceStore: resourceStore, + resourceEntityExpansions: resourceEntityExpansions }); +} + +var RESOURCE_RELATED_PROPS = { + resourceId: String, + resourceIds: function (items) { + return (items || []).map(function (item) { + return String(item); + }); + }, + resourceEditable: Boolean +}; +function parseEventDef(def, props, leftovers) { + var resourceRelatedProps = refineProps(props, RESOURCE_RELATED_PROPS, {}, leftovers); + var resourceIds = resourceRelatedProps.resourceIds; + if (resourceRelatedProps.resourceId) { + resourceIds.push(resourceRelatedProps.resourceId); + } + def.resourceIds = resourceIds; + def.resourceEditable = resourceRelatedProps.resourceEditable; +} + +function transformDateSelectionJoin(hit0, hit1) { + var resourceId0 = hit0.dateSpan.resourceId; + var resourceId1 = hit1.dateSpan.resourceId; + if (resourceId0 && resourceId1) { + if (hit0.component.allowAcrossResources === false && + resourceId0 !== resourceId1) { + return false; + } + else { + return { resourceId: resourceId0 }; + } + } +} + +var ResourceApi = /** @class */ (function () { + function ResourceApi(calendar, rawResource) { + this._calendar = calendar; + this._resource = rawResource; + } + ResourceApi.prototype.setProp = function (name, value) { + this._calendar.dispatch({ + type: 'SET_RESOURCE_PROP', + resourceId: this._resource.id, + propName: name, + propValue: value + }); + }; + ResourceApi.prototype.remove = function () { + this._calendar.dispatch({ + type: 'REMOVE_RESOURCE', + resourceId: this._resource.id + }); + }; + ResourceApi.prototype.getParent = function () { + var calendar = this._calendar; + var parentId = this._resource.parentId; + if (parentId) { + return new ResourceApi(calendar, calendar.state.resourceSource[parentId]); + } + else { + return null; + } + }; + ResourceApi.prototype.getChildren = function () { + var thisResourceId = this._resource.id; + var calendar = this._calendar; + var resourceStore = calendar.state.resourceStore; + var childApis = []; + for (var resourceId in resourceStore) { + if (resourceStore[resourceId].parentId === thisResourceId) { + childApis.push(new ResourceApi(calendar, resourceStore[resourceId])); + } + } + return childApis; + }; + /* + this is really inefficient! + TODO: make EventApi::resourceIds a hash or keep an index in the Calendar's state + */ + ResourceApi.prototype.getEvents = function () { + var thisResourceId = this._resource.id; + var calendar = this._calendar; + var _a = calendar.state.eventStore, defs = _a.defs, instances = _a.instances; + var eventApis = []; + for (var instanceId in instances) { + var instance = instances[instanceId]; + var def = defs[instance.defId]; + if (def.resourceIds.indexOf(thisResourceId) !== -1) { // inefficient!!! + eventApis.push(new EventApi(calendar, def, instance)); + } + } + return eventApis; + }; + Object.defineProperty(ResourceApi.prototype, "id", { + get: function () { return this._resource.id; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ResourceApi.prototype, "title", { + get: function () { return this._resource.title; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ResourceApi.prototype, "eventConstraint", { + get: function () { return this._resource.ui.constraints[0] || null; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ResourceApi.prototype, "eventOverlap", { + get: function () { return this._resource.ui.overlap; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ResourceApi.prototype, "eventAllow", { + get: function () { return this._resource.ui.allows[0] || null; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ResourceApi.prototype, "eventBackgroundColor", { + get: function () { return this._resource.ui.backgroundColor; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ResourceApi.prototype, "eventBorderColor", { + get: function () { return this._resource.ui.borderColor; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ResourceApi.prototype, "eventTextColor", { + get: function () { return this._resource.ui.textColor; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ResourceApi.prototype, "eventClassNames", { + // NOTE: user can't modify these because Object.freeze was called in event-def parsing + get: function () { return this._resource.ui.classNames; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ResourceApi.prototype, "extendedProps", { + get: function () { return this._resource.extendedProps; }, + enumerable: true, + configurable: true + }); + return ResourceApi; +}()); + +Calendar.prototype.addResource = function (input, scrollTo) { + var _a; + if (scrollTo === void 0) { scrollTo = true; } + var resourceHash; + var resource; + if (input instanceof ResourceApi) { + resource = input._resource; + resourceHash = (_a = {}, _a[resource.id] = resource, _a); + } + else { + resourceHash = {}; + resource = parseResource(input, '', resourceHash, this); + } + // HACK + if (scrollTo) { + this.component.view.addScroll({ forcedRowId: resource.id }); + } + this.dispatch({ + type: 'ADD_RESOURCE', + resourceHash: resourceHash + }); + return new ResourceApi(this, resource); +}; +Calendar.prototype.getResourceById = function (id) { + id = String(id); + if (this.state.resourceStore) { // guard against calendar with no resource functionality + var rawResource = this.state.resourceStore[id]; + if (rawResource) { + return new ResourceApi(this, rawResource); + } + } + return null; +}; +Calendar.prototype.getResources = function () { + var resourceStore = this.state.resourceStore; + var resourceApis = []; + if (resourceStore) { // guard against calendar with no resource functionality + for (var resourceId in resourceStore) { + resourceApis.push(new ResourceApi(this, resourceStore[resourceId])); + } + } + return resourceApis; +}; +Calendar.prototype.getTopLevelResources = function () { + var resourceStore = this.state.resourceStore; + var resourceApis = []; + if (resourceStore) { // guard against calendar with no resource functionality + for (var resourceId in resourceStore) { + if (!resourceStore[resourceId].parentId) { + resourceApis.push(new ResourceApi(this, resourceStore[resourceId])); + } + } + } + return resourceApis; +}; +Calendar.prototype.rerenderResources = function () { + this.dispatch({ + type: 'RESET_RESOURCES' + }); +}; +Calendar.prototype.refetchResources = function () { + this.dispatch({ + type: 'REFETCH_RESOURCES' + }); +}; +function transformDatePoint(dateSpan, calendar) { + return dateSpan.resourceId ? + { resource: calendar.getResourceById(dateSpan.resourceId) } : + {}; +} +function transformDateSpan(dateSpan, calendar) { + return dateSpan.resourceId ? + { resource: calendar.getResourceById(dateSpan.resourceId) } : + {}; +} + +/* +splits things BASED OFF OF which resources they are associated with. +creates a '' entry which is when something has NO resource. +*/ +var ResourceSplitter = /** @class */ (function (_super) { + __extends(ResourceSplitter, _super); + function ResourceSplitter() { + return _super !== null && _super.apply(this, arguments) || this; + } + ResourceSplitter.prototype.getKeyInfo = function (props) { + return __assign({ '': {} }, props.resourceStore // already has `ui` and `businessHours` keys! + ); + }; + ResourceSplitter.prototype.getKeysForDateSpan = function (dateSpan) { + return [dateSpan.resourceId || '']; + }; + ResourceSplitter.prototype.getKeysForEventDef = function (eventDef) { + var resourceIds = eventDef.resourceIds; + if (!resourceIds.length) { + return ['']; + } + return resourceIds; + }; + return ResourceSplitter; +}(Splitter)); + +function isPropsValidWithResources(props, calendar) { + var splitter = new ResourceSplitter(); + var sets = splitter.splitProps(__assign({}, props, { resourceStore: calendar.state.resourceStore })); + for (var resourceId in sets) { + var props_1 = sets[resourceId]; + // merge in event data from the non-resource segment + if (resourceId && sets['']) { // current segment is not the non-resource one, and there IS a non-resource one + props_1 = __assign({}, props_1, { eventStore: mergeEventStores(sets[''].eventStore, props_1.eventStore), eventUiBases: __assign({}, sets[''].eventUiBases, props_1.eventUiBases) }); + } + if (!isPropsValid(props_1, calendar, { resourceId: resourceId }, filterConfig.bind(null, resourceId))) { + return false; + } + } + return true; +} +function filterConfig(resourceId, config) { + return __assign({}, config, { constraints: filterConstraints(resourceId, config.constraints) }); +} +function filterConstraints(resourceId, constraints) { + return constraints.map(function (constraint) { + var defs = constraint.defs; + if (defs) { // we are dealing with an EventStore + // if any of the events define constraints to resources that are NOT this resource, + // then this resource is unconditionally prohibited, which is what a `false` value does. + for (var defId in defs) { + var resourceIds = defs[defId].resourceIds; + if (resourceIds.length && resourceIds.indexOf(resourceId) === -1) { // TODO: use a hash?!!! (for other reasons too) + return false; + } + } + } + return constraint; + }); +} + +function transformExternalDef(dateSpan) { + return dateSpan.resourceId ? + { resourceId: dateSpan.resourceId } : + {}; +} + +function transformEventResizeJoin(hit0, hit1) { + var component = hit0.component; + if (component.allowAcrossResources === false && + hit0.dateSpan.resourceId !== hit1.dateSpan.resourceId) { + return false; + } +} + +EventApi.prototype.getResources = function () { + var calendar = this._calendar; + return this._def.resourceIds.map(function (resourceId) { + return calendar.getResourceById(resourceId); + }); +}; +EventApi.prototype.setResources = function (resources) { + var resourceIds = []; + // massage resources -> resourceIds + for (var _i = 0, resources_1 = resources; _i < resources_1.length; _i++) { + var resource = resources_1[_i]; + var resourceId = null; + if (typeof resource === 'string') { + resourceId = resource; + } + else if (typeof resource === 'number') { + resourceId = String(resource); + } + else if (resource instanceof ResourceApi) { + resourceId = resource.id; // guaranteed to always have an ID. hmmm + } + else { + console.warn('unknown resource type: ' + resource); + } + if (resourceId) { + resourceIds.push(resourceId); + } + } + this.mutate({ + standardProps: { + resourceIds: resourceIds + } + }); +}; + +var RELEASE_DATE = '2019-08-10'; // for Scheduler +var UPGRADE_WINDOW = 365 + 7; // days. 1 week leeway, for tz shift reasons too +var LICENSE_INFO_URL = 'http://fullcalendar.io/scheduler/license/'; +var PRESET_LICENSE_KEYS = [ + 'GPL-My-Project-Is-Open-Source', + 'CC-Attribution-NonCommercial-NoDerivatives' +]; +var CSS = { + position: 'absolute', + 'z-index': 99999, + bottom: '1px', + left: '1px', + background: '#eee', + 'border-color': '#ddd', + 'border-style': 'solid', + 'border-width': '1px 1px 0 0', + padding: '2px 4px', + 'font-size': '12px', + 'border-top-right-radius': '3px' +}; +function injectLicenseWarning(containerEl, calendar) { + var key = calendar.opt('schedulerLicenseKey'); + if (!isImmuneUrl(window.location.href) && !isValidKey(key)) { + appendToElement(containerEl, '<div class="fc-license-message" style="' + htmlEscape(cssToStr(CSS)) + '">' + + 'Please use a valid license key. <a href="' + LICENSE_INFO_URL + '">More Info</a>' + + '</div>'); + } +} +/* +This decryption is not meant to be bulletproof. Just a way to remind about an upgrade. +*/ +function isValidKey(key) { + if (PRESET_LICENSE_KEYS.indexOf(key) !== -1) { + return true; + } + var parts = (key || '').match(/^(\d+)\-fcs\-(\d+)$/); + if (parts && (parts[1].length === 10)) { + var purchaseDate = new Date(parseInt(parts[2], 10) * 1000); + var releaseDate = new Date(config.mockSchedulerReleaseDate || RELEASE_DATE); + if (isValidDate(releaseDate)) { // token won't be replaced in dev mode + var minPurchaseDate = addDays(releaseDate, -UPGRADE_WINDOW); + if (minPurchaseDate < purchaseDate) { + return true; + } + } + } + return false; +} +function isImmuneUrl(url) { + return /\w+\:\/\/fullcalendar\.io\/|\/examples\/[\w-]+\.html$/.test(url); +} + +var optionChangeHandlers = { + resources: handleResources +}; +function handleResources(newSourceInput, calendar, deepEqual) { + var oldSourceInput = calendar.state.resourceSource._raw; + if (!deepEqual(oldSourceInput, newSourceInput)) { + calendar.dispatch({ + type: 'RESET_RESOURCE_SOURCE', + resourceSourceInput: newSourceInput + }); + } +} + +registerResourceSourceDef({ + ignoreRange: true, + parseMeta: function (raw) { + if (Array.isArray(raw)) { + return raw; + } + else if (Array.isArray(raw.resources)) { + return raw.resources; + } + return null; + }, + fetch: function (arg, successCallback) { + successCallback({ + rawResources: arg.resourceSource.meta + }); + } +}); + +registerResourceSourceDef({ + parseMeta: function (raw) { + if (typeof raw === 'function') { + return raw; + } + else if (typeof raw.resources === 'function') { + return raw.resources; + } + return null; + }, + fetch: function (arg, success, failure) { + var dateEnv = arg.calendar.dateEnv; + var func = arg.resourceSource.meta; + var publicArg = {}; + if (arg.range) { + publicArg = { + start: dateEnv.toDate(arg.range.start), + end: dateEnv.toDate(arg.range.end), + startStr: dateEnv.formatIso(arg.range.start), + endStr: dateEnv.formatIso(arg.range.end), + timeZone: dateEnv.timeZone + }; + } + // TODO: make more dry with EventSourceFunc + // TODO: accept a response? + unpromisify(func.bind(null, publicArg), function (rawResources) { + success({ rawResources: rawResources }); // needs an object response + }, failure // send errorObj directly to failure callback + ); + } +}); + +registerResourceSourceDef({ + parseMeta: function (raw) { + if (typeof raw === 'string') { + raw = { url: raw }; + } + else if (!raw || typeof raw !== 'object' || !raw.url) { + return null; + } + return { + url: raw.url, + method: (raw.method || 'GET').toUpperCase(), + extraParams: raw.extraParams + }; + }, + fetch: function (arg, successCallback, failureCallback) { + var meta = arg.resourceSource.meta; + var requestParams = buildRequestParams(meta, arg.range, arg.calendar); + requestJson(meta.method, meta.url, requestParams, function (rawResources, xhr) { + successCallback({ rawResources: rawResources, xhr: xhr }); + }, function (message, xhr) { + failureCallback({ message: message, xhr: xhr }); + }); + } +}); +// TODO: somehow consolidate with event json feed +function buildRequestParams(meta, range, calendar) { + var dateEnv = calendar.dateEnv; + var startParam; + var endParam; + var timeZoneParam; + var customRequestParams; + var params = {}; + if (range) { + // startParam = meta.startParam + // if (startParam == null) { + startParam = calendar.opt('startParam'); + // } + // endParam = meta.endParam + // if (endParam == null) { + endParam = calendar.opt('endParam'); + // } + // timeZoneParam = meta.timeZoneParam + // if (timeZoneParam == null) { + timeZoneParam = calendar.opt('timeZoneParam'); + // } + params[startParam] = dateEnv.formatIso(range.start); + params[endParam] = dateEnv.formatIso(range.end); + if (dateEnv.timeZone !== 'local') { + params[timeZoneParam] = dateEnv.timeZone; + } + } + // retrieve any outbound GET/POST data from the options + if (typeof meta.extraParams === 'function') { + // supplied as a function that returns a key/value object + customRequestParams = meta.extraParams(); + } + else { + // probably supplied as a straight key/value object + customRequestParams = meta.extraParams || {}; + } + __assign(params, customRequestParams); + return params; +} + +function buildResourceTextFunc(resourceTextSetting, calendar) { + if (typeof resourceTextSetting === 'function') { + return function (resource) { + return resourceTextSetting(new ResourceApi(calendar, resource)); + }; + } + else { + return function (resource) { + return resource.title || getPublicId(resource.id); + }; + } +} + +var ResourceDayHeader = /** @class */ (function (_super) { + __extends(ResourceDayHeader, _super); + function ResourceDayHeader(context, parentEl) { + var _this = _super.call(this, context) || this; + _this.datesAboveResources = _this.opt('datesAboveResources'); + _this.resourceTextFunc = buildResourceTextFunc(_this.opt('resourceText'), _this.calendar); + parentEl.innerHTML = ''; // because might be nbsp + parentEl.appendChild(_this.el = htmlToElement('<div class="fc-row ' + _this.theme.getClass('headerRow') + '">' + + '<table class="' + _this.theme.getClass('tableGrid') + '">' + + '<thead></thead>' + + '</table>' + + '</div>')); + _this.thead = _this.el.querySelector('thead'); + return _this; + } + ResourceDayHeader.prototype.destroy = function () { + removeElement(this.el); + }; + ResourceDayHeader.prototype.render = function (props) { + var html; + this.dateFormat = createFormatter(this.opt('columnHeaderFormat') || + computeFallbackHeaderFormat(props.datesRepDistinctDays, props.dates.length)); + if (props.dates.length === 1) { + html = this.renderResourceRow(props.resources); + } + else { + if (this.datesAboveResources) { + html = this.renderDayAndResourceRows(props.dates, props.resources); + } + else { + html = this.renderResourceAndDayRows(props.resources, props.dates); + } + } + this.thead.innerHTML = html; + this.processResourceEls(props.resources); + }; + ResourceDayHeader.prototype.renderResourceRow = function (resources) { + var _this = this; + var cellHtmls = resources.map(function (resource) { + return _this.renderResourceCell(resource, 1); + }); + return this.buildTr(cellHtmls); + }; + ResourceDayHeader.prototype.renderDayAndResourceRows = function (dates, resources) { + var dateHtmls = []; + var resourceHtmls = []; + for (var _i = 0, dates_1 = dates; _i < dates_1.length; _i++) { + var date = dates_1[_i]; + dateHtmls.push(this.renderDateCell(date, resources.length)); + for (var _a = 0, resources_1 = resources; _a < resources_1.length; _a++) { + var resource = resources_1[_a]; + resourceHtmls.push(this.renderResourceCell(resource, 1, date)); + } + } + return this.buildTr(dateHtmls) + + this.buildTr(resourceHtmls); + }; + ResourceDayHeader.prototype.renderResourceAndDayRows = function (resources, dates) { + var resourceHtmls = []; + var dateHtmls = []; + for (var _i = 0, resources_2 = resources; _i < resources_2.length; _i++) { + var resource = resources_2[_i]; + resourceHtmls.push(this.renderResourceCell(resource, dates.length)); + for (var _a = 0, dates_2 = dates; _a < dates_2.length; _a++) { + var date = dates_2[_a]; + dateHtmls.push(this.renderDateCell(date, 1, resource)); + } + } + return this.buildTr(resourceHtmls) + + this.buildTr(dateHtmls); + }; + // Cell Rendering Utils + // ---------------------------------------------------------------------------------------------- + // a cell with the resource name. might be associated with a specific day + ResourceDayHeader.prototype.renderResourceCell = function (resource, colspan, date) { + var dateEnv = this.dateEnv; + return '<th class="fc-resource-cell"' + + ' data-resource-id="' + resource.id + '"' + + (date ? + ' data-date="' + dateEnv.formatIso(date, { omitTime: true }) + '"' : + '') + + (colspan > 1 ? + ' colspan="' + colspan + '"' : + '') + + '>' + + htmlEscape(this.resourceTextFunc(resource)) + + '</th>'; + }; + // a cell with date text. might have a resource associated with it + ResourceDayHeader.prototype.renderDateCell = function (date, colspan, resource) { + var props = this.props; + return renderDateCell(date, props.dateProfile, props.datesRepDistinctDays, props.dates.length * props.resources.length, this.dateFormat, this.context, colspan, resource ? 'data-resource-id="' + resource.id + '"' : ''); + }; + ResourceDayHeader.prototype.buildTr = function (cellHtmls) { + if (!cellHtmls.length) { + cellHtmls = ['<td> </td>']; + } + if (this.props.renderIntroHtml) { + cellHtmls = [this.props.renderIntroHtml()].concat(cellHtmls); + } + if (this.isRtl) { + cellHtmls.reverse(); + } + return '<tr>' + + cellHtmls.join('') + + '</tr>'; + }; + // Post-rendering + // ---------------------------------------------------------------------------------------------- + // given a container with already rendered resource cells + ResourceDayHeader.prototype.processResourceEls = function (resources) { + var _this = this; + var view = this.view; + findElements(this.thead, '.fc-resource-cell').forEach(function (node, col) { + col = col % resources.length; + if (_this.isRtl) { + col = resources.length - 1 - col; + } + var resource = resources[col]; + view.publiclyTrigger('resourceRender', [ + { + resource: new ResourceApi(_this.calendar, resource), + el: node, + view: view + } + ]); + }); + }; + return ResourceDayHeader; +}(Component)); + +var AbstractResourceDayTable = /** @class */ (function () { + function AbstractResourceDayTable(dayTable, resources) { + this.dayTable = dayTable; + this.resources = resources; + this.resourceIndex = new ResourceIndex(resources); + this.rowCnt = dayTable.rowCnt; + this.colCnt = dayTable.colCnt * resources.length; + this.cells = this.buildCells(); + } + AbstractResourceDayTable.prototype.buildCells = function () { + var _a = this, rowCnt = _a.rowCnt, dayTable = _a.dayTable, resources = _a.resources; + var rows = []; + for (var row = 0; row < rowCnt; row++) { + var rowCells = []; + for (var dateCol = 0; dateCol < dayTable.colCnt; dateCol++) { + for (var resourceCol = 0; resourceCol < resources.length; resourceCol++) { + var resource = resources[resourceCol]; + var htmlAttrs = 'data-resource-id="' + resource.id + '"'; + rowCells[this.computeCol(dateCol, resourceCol)] = { + date: dayTable.cells[row][dateCol].date, + resource: resource, + htmlAttrs: htmlAttrs + }; + } + } + rows.push(rowCells); + } + return rows; + }; + return AbstractResourceDayTable; +}()); +/* +resources over dates +*/ +var ResourceDayTable = /** @class */ (function (_super) { + __extends(ResourceDayTable, _super); + function ResourceDayTable() { + return _super !== null && _super.apply(this, arguments) || this; + } + ResourceDayTable.prototype.computeCol = function (dateI, resourceI) { + return resourceI * this.dayTable.colCnt + dateI; + }; + /* + all date ranges are intact + */ + ResourceDayTable.prototype.computeColRanges = function (dateStartI, dateEndI, resourceI) { + return [ + { + firstCol: this.computeCol(dateStartI, resourceI), + lastCol: this.computeCol(dateEndI, resourceI), + isStart: true, + isEnd: true + } + ]; + }; + return ResourceDayTable; +}(AbstractResourceDayTable)); +/* +dates over resources +*/ +var DayResourceTable = /** @class */ (function (_super) { + __extends(DayResourceTable, _super); + function DayResourceTable() { + return _super !== null && _super.apply(this, arguments) || this; + } + DayResourceTable.prototype.computeCol = function (dateI, resourceI) { + return dateI * this.resources.length + resourceI; + }; + /* + every single day is broken up + */ + DayResourceTable.prototype.computeColRanges = function (dateStartI, dateEndI, resourceI) { + var segs = []; + for (var i = dateStartI; i <= dateEndI; i++) { + var col = this.computeCol(i, resourceI); + segs.push({ + firstCol: col, + lastCol: col, + isStart: i === dateStartI, + isEnd: i === dateEndI + }); + } + return segs; + }; + return DayResourceTable; +}(AbstractResourceDayTable)); +var ResourceIndex = /** @class */ (function () { + function ResourceIndex(resources) { + var indicesById = {}; + var ids = []; + for (var i = 0; i < resources.length; i++) { + var id = resources[i].id; + ids.push(id); + indicesById[id] = i; + } + this.ids = ids; + this.indicesById = indicesById; + this.length = resources.length; + } + return ResourceIndex; +}()); +/* +TODO: just use ResourceHash somehow? could then use the generic ResourceSplitter +*/ +var VResourceSplitter = /** @class */ (function (_super) { + __extends(VResourceSplitter, _super); + function VResourceSplitter() { + return _super !== null && _super.apply(this, arguments) || this; + } + VResourceSplitter.prototype.getKeyInfo = function (props) { + var resourceDayTable = props.resourceDayTable; + var hash = mapHash(resourceDayTable.resourceIndex.indicesById, function (i) { + return resourceDayTable.resources[i]; // has `ui` AND `businessHours` keys! + }); // :( + hash[''] = {}; + return hash; + }; + VResourceSplitter.prototype.getKeysForDateSpan = function (dateSpan) { + return [dateSpan.resourceId || '']; + }; + VResourceSplitter.prototype.getKeysForEventDef = function (eventDef) { + var resourceIds = eventDef.resourceIds; + if (!resourceIds.length) { + return ['']; + } + return resourceIds; + }; + return VResourceSplitter; +}(Splitter)); +// joiner +var NO_SEGS = []; // for memoizing +var VResourceJoiner = /** @class */ (function () { + function VResourceJoiner() { + this.joinDateSelection = memoize(this.joinSegs); + this.joinBusinessHours = memoize(this.joinSegs); + this.joinFgEvents = memoize(this.joinSegs); + this.joinBgEvents = memoize(this.joinSegs); + this.joinEventDrags = memoize(this.joinInteractions); + this.joinEventResizes = memoize(this.joinInteractions); + } + /* + propSets also has a '' key for things with no resource + */ + VResourceJoiner.prototype.joinProps = function (propSets, resourceDayTable) { + var dateSelectionSets = []; + var businessHoursSets = []; + var fgEventSets = []; + var bgEventSets = []; + var eventDrags = []; + var eventResizes = []; + var eventSelection = ''; + var keys = resourceDayTable.resourceIndex.ids.concat(['']); // add in the all-resource key + for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { + var key = keys_1[_i]; + var props = propSets[key]; + dateSelectionSets.push(props.dateSelectionSegs); + businessHoursSets.push(key ? props.businessHourSegs : NO_SEGS); // don't include redundant all-resource businesshours + fgEventSets.push(key ? props.fgEventSegs : NO_SEGS); // don't include fg all-resource segs + bgEventSets.push(props.bgEventSegs); + eventDrags.push(props.eventDrag); + eventResizes.push(props.eventResize); + eventSelection = eventSelection || props.eventSelection; + } + return { + dateSelectionSegs: this.joinDateSelection.apply(this, [resourceDayTable].concat(dateSelectionSets)), + businessHourSegs: this.joinBusinessHours.apply(this, [resourceDayTable].concat(businessHoursSets)), + fgEventSegs: this.joinFgEvents.apply(this, [resourceDayTable].concat(fgEventSets)), + bgEventSegs: this.joinBgEvents.apply(this, [resourceDayTable].concat(bgEventSets)), + eventDrag: this.joinEventDrags.apply(this, [resourceDayTable].concat(eventDrags)), + eventResize: this.joinEventResizes.apply(this, [resourceDayTable].concat(eventResizes)), + eventSelection: eventSelection + }; + }; + VResourceJoiner.prototype.joinSegs = function (resourceDayTable) { + var segGroups = []; + for (var _i = 1; _i < arguments.length; _i++) { + segGroups[_i - 1] = arguments[_i]; + } + var resourceCnt = resourceDayTable.resources.length; + var transformedSegs = []; + for (var i = 0; i < resourceCnt; i++) { + for (var _a = 0, _b = segGroups[i]; _a < _b.length; _a++) { + var seg = _b[_a]; + transformedSegs.push.apply(transformedSegs, this.transformSeg(seg, resourceDayTable, i)); + } + for (var _c = 0, _d = segGroups[resourceCnt]; _c < _d.length; _c++) { // one beyond. the all-resource + var seg = _d[_c]; + transformedSegs.push.apply(// one beyond. the all-resource + transformedSegs, this.transformSeg(seg, resourceDayTable, i)); + } + } + return transformedSegs; + }; + /* + for expanding non-resource segs to all resources. + only for public use. + no memoizing. + */ + VResourceJoiner.prototype.expandSegs = function (resourceDayTable, segs) { + var resourceCnt = resourceDayTable.resources.length; + var transformedSegs = []; + for (var i = 0; i < resourceCnt; i++) { + for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { + var seg = segs_1[_i]; + transformedSegs.push.apply(transformedSegs, this.transformSeg(seg, resourceDayTable, i)); + } + } + return transformedSegs; + }; + VResourceJoiner.prototype.joinInteractions = function (resourceDayTable) { + var interactions = []; + for (var _i = 1; _i < arguments.length; _i++) { + interactions[_i - 1] = arguments[_i]; + } + var resourceCnt = resourceDayTable.resources.length; + var affectedInstances = {}; + var transformedSegs = []; + var isEvent = false; + var sourceSeg = null; + for (var i = 0; i < resourceCnt; i++) { + var interaction = interactions[i]; + if (interaction) { + for (var _a = 0, _b = interaction.segs; _a < _b.length; _a++) { + var seg = _b[_a]; + transformedSegs.push.apply(transformedSegs, this.transformSeg(seg, resourceDayTable, i) // TODO: templateify Interaction::segs + ); + } + __assign(affectedInstances, interaction.affectedInstances); + isEvent = isEvent || interaction.isEvent; + sourceSeg = sourceSeg || interaction.sourceSeg; + } + if (interactions[resourceCnt]) { // one beyond. the all-resource + for (var _c = 0, _d = interactions[resourceCnt].segs; _c < _d.length; _c++) { + var seg = _d[_c]; + transformedSegs.push.apply(transformedSegs, this.transformSeg(seg, resourceDayTable, i) // TODO: templateify Interaction::segs + ); + } + } + } + return { + affectedInstances: affectedInstances, + segs: transformedSegs, + isEvent: isEvent, + sourceSeg: sourceSeg + }; + }; + return VResourceJoiner; +}()); + +/* +doesn't accept grouping +*/ +function flattenResources(resourceStore, orderSpecs) { + return buildRowNodes(resourceStore, [], orderSpecs, false, {}, true) + .map(function (node) { + return node.resource; + }); +} +function buildRowNodes(resourceStore, groupSpecs, orderSpecs, isVGrouping, expansions, expansionDefault) { + var complexNodes = buildHierarchy(resourceStore, isVGrouping ? -1 : 1, groupSpecs, orderSpecs); + var flatNodes = []; + flattenNodes(complexNodes, flatNodes, isVGrouping, [], 0, expansions, expansionDefault); + return flatNodes; +} +function flattenNodes(complexNodes, res, isVGrouping, rowSpans, depth, expansions, expansionDefault) { + for (var i = 0; i < complexNodes.length; i++) { + var complexNode = complexNodes[i]; + var group = complexNode.group; + if (group) { + if (isVGrouping) { + var firstRowIndex = res.length; + var rowSpanIndex = rowSpans.length; + flattenNodes(complexNode.children, res, isVGrouping, rowSpans.concat(0), depth, expansions, expansionDefault); + if (firstRowIndex < res.length) { + var firstRow = res[firstRowIndex]; + var firstRowSpans = firstRow.rowSpans = firstRow.rowSpans.slice(); + firstRowSpans[rowSpanIndex] = res.length - firstRowIndex; + } + } + else { + var id = group.spec.field + ':' + group.value; + var isExpanded = expansions[id] != null ? expansions[id] : expansionDefault; + res.push({ id: id, group: group, isExpanded: isExpanded }); + if (isExpanded) { + flattenNodes(complexNode.children, res, isVGrouping, rowSpans, depth + 1, expansions, expansionDefault); + } + } + } + else if (complexNode.resource) { + var id = complexNode.resource.id; + var isExpanded = expansions[id] != null ? expansions[id] : expansionDefault; + res.push({ + id: id, + rowSpans: rowSpans, + depth: depth, + isExpanded: isExpanded, + hasChildren: Boolean(complexNode.children.length), + resource: complexNode.resource, + resourceFields: complexNode.resourceFields + }); + if (isExpanded) { + flattenNodes(complexNode.children, res, isVGrouping, rowSpans, depth + 1, expansions, expansionDefault); + } + } + } +} +function buildHierarchy(resourceStore, maxDepth, groupSpecs, orderSpecs) { + var resourceNodes = buildResourceNodes(resourceStore, orderSpecs); + var builtNodes = []; + for (var resourceId in resourceNodes) { + var resourceNode = resourceNodes[resourceId]; + if (!resourceNode.resource.parentId) { + insertResourceNode(resourceNode, builtNodes, groupSpecs, 0, maxDepth, orderSpecs); + } + } + return builtNodes; +} +function buildResourceNodes(resourceStore, orderSpecs) { + var nodeHash = {}; + for (var resourceId in resourceStore) { + var resource = resourceStore[resourceId]; + nodeHash[resourceId] = { + resource: resource, + resourceFields: buildResourceFields(resource), + children: [] + }; + } + for (var resourceId in resourceStore) { + var resource = resourceStore[resourceId]; + if (resource.parentId) { + var parentNode = nodeHash[resource.parentId]; + if (parentNode) { + insertResourceNodeInSiblings(nodeHash[resourceId], parentNode.children, orderSpecs); + } + } + } + return nodeHash; +} +function insertResourceNode(resourceNode, nodes, groupSpecs, depth, maxDepth, orderSpecs) { + if (groupSpecs.length && (maxDepth === -1 || depth <= maxDepth)) { + var groupNode = ensureGroupNodes(resourceNode, nodes, groupSpecs[0]); + insertResourceNode(resourceNode, groupNode.children, groupSpecs.slice(1), depth + 1, maxDepth, orderSpecs); + } + else { + insertResourceNodeInSiblings(resourceNode, nodes, orderSpecs); + } +} +function ensureGroupNodes(resourceNode, nodes, groupSpec) { + var groupValue = resourceNode.resourceFields[groupSpec.field]; + var groupNode; + var newGroupIndex; + // find an existing group that matches, or determine the position for a new group + if (groupSpec.order) { + for (newGroupIndex = 0; newGroupIndex < nodes.length; newGroupIndex++) { + var node = nodes[newGroupIndex]; + if (node.group) { + var cmp = flexibleCompare(groupValue, node.group.value) * groupSpec.order; + if (cmp === 0) { + groupNode = node; + break; + } + else if (cmp < 0) { + break; + } + } + } + } + else { // the groups are unordered + for (newGroupIndex = 0; newGroupIndex < nodes.length; newGroupIndex++) { + var node = nodes[newGroupIndex]; + if (node.group && groupValue === node.group.value) { + groupNode = node; + break; + } + } + } + if (!groupNode) { + groupNode = { + group: { + value: groupValue, + spec: groupSpec + }, + children: [] + }; + nodes.splice(newGroupIndex, 0, groupNode); + } + return groupNode; +} +function insertResourceNodeInSiblings(resourceNode, siblings, orderSpecs) { + var i; + for (i = 0; i < siblings.length; i++) { + var cmp = compareByFieldSpecs(siblings[i].resourceFields, resourceNode.resourceFields, orderSpecs); + if (cmp > 0) { // went 1 past. insert at i + break; + } + } + siblings.splice(i, 0, resourceNode); +} +function buildResourceFields(resource) { + var obj = __assign({}, resource.extendedProps, resource.ui, resource); + delete obj.ui; + delete obj.extendedProps; + return obj; +} +function isGroupsEqual(group0, group1) { + return group0.spec === group1.spec && group0.value === group1.value; +} + +var main = createPlugin({ + reducers: [resourcesReducers], + eventDefParsers: [parseEventDef], + isDraggableTransformers: [transformIsDraggable], + eventDragMutationMassagers: [massageEventDragMutation], + eventDefMutationAppliers: [applyEventDefMutation], + dateSelectionTransformers: [transformDateSelectionJoin], + datePointTransforms: [transformDatePoint], + dateSpanTransforms: [transformDateSpan], + viewPropsTransformers: [ResourceDataAdder, ResourceEventConfigAdder], + isPropsValid: isPropsValidWithResources, + externalDefTransforms: [transformExternalDef], + eventResizeJoinTransforms: [transformEventResizeJoin], + viewContainerModifiers: [injectLicenseWarning], + eventDropTransformers: [transformEventDrop], + optionChangeHandlers: optionChangeHandlers +}); + +export default main; +export { AbstractResourceDayTable, DayResourceTable, ResourceApi, ResourceDayHeader, ResourceDayTable, ResourceSplitter, VResourceJoiner, VResourceSplitter, buildResourceFields, buildResourceTextFunc, buildRowNodes, flattenResources, isGroupsEqual }; diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-common/main.js b/AKPlan/static/AKPlan/fullcalendar/resource-common/main.js new file mode 100644 index 00000000..eaa626d7 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-common/main.js @@ -0,0 +1,1582 @@ +/*! +FullCalendar Resources Common Plugin v4.3.1 +Docs & License: https://fullcalendar.io/scheduler +(c) 2019 Adam Shaw +*/ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) : + typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) : + (global = global || self, factory(global.FullCalendarResourceCommon = {}, global.FullCalendar)); +}(this, function (exports, core) { 'use strict'; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + function massageEventDragMutation(eventMutation, hit0, hit1) { + var resource0 = hit0.dateSpan.resourceId; + var resource1 = hit1.dateSpan.resourceId; + if (resource0 && resource1 && + resource0 !== resource1) { + eventMutation.resourceMutation = { + matchResourceId: resource0, + setResourceId: resource1 + }; + } + } + /* + TODO: all this would be much easier if we were using a hash! + */ + function applyEventDefMutation(eventDef, mutation, calendar) { + var resourceMutation = mutation.resourceMutation; + if (resourceMutation && computeResourceEditable(eventDef, calendar)) { + var index = eventDef.resourceIds.indexOf(resourceMutation.matchResourceId); + if (index !== -1) { + var resourceIds = eventDef.resourceIds.slice(); // copy + resourceIds.splice(index, 1); // remove + if (resourceIds.indexOf(resourceMutation.setResourceId) === -1) { // not already in there + resourceIds.push(resourceMutation.setResourceId); // add + } + eventDef.resourceIds = resourceIds; + } + } + } + /* + HACK + TODO: use EventUi system instead of this + */ + function computeResourceEditable(eventDef, calendar) { + var resourceEditable = eventDef.resourceEditable; + if (resourceEditable == null) { + var source = eventDef.sourceId && calendar.state.eventSources[eventDef.sourceId]; + if (source) { + resourceEditable = source.extendedProps.resourceEditable; // used the Source::extendedProps hack + } + if (resourceEditable == null) { + resourceEditable = calendar.opt('eventResourceEditable'); + if (resourceEditable == null) { + resourceEditable = calendar.opt('editable'); // TODO: use defaults system instead + } + } + } + return resourceEditable; + } + function transformEventDrop(mutation, calendar) { + var resourceMutation = mutation.resourceMutation; + if (resourceMutation) { + return { + oldResource: calendar.getResourceById(resourceMutation.matchResourceId), + newResource: calendar.getResourceById(resourceMutation.setResourceId) + }; + } + else { + return { + oldResource: null, + newResource: null + }; + } + } + + var ResourceDataAdder = /** @class */ (function () { + function ResourceDataAdder() { + this.filterResources = core.memoize(filterResources); + } + ResourceDataAdder.prototype.transform = function (viewProps, viewSpec, calendarProps, view) { + if (viewSpec.class.needsResourceData) { + return { + resourceStore: this.filterResources(calendarProps.resourceStore, view.opt('filterResourcesWithEvents'), calendarProps.eventStore, calendarProps.dateProfile.activeRange), + resourceEntityExpansions: calendarProps.resourceEntityExpansions + }; + } + }; + return ResourceDataAdder; + }()); + function filterResources(resourceStore, doFilterResourcesWithEvents, eventStore, activeRange) { + if (doFilterResourcesWithEvents) { + var instancesInRange = filterEventInstancesInRange(eventStore.instances, activeRange); + var hasEvents_1 = computeHasEvents(instancesInRange, eventStore.defs); + __assign(hasEvents_1, computeAncestorHasEvents(hasEvents_1, resourceStore)); + return core.filterHash(resourceStore, function (resource, resourceId) { + return hasEvents_1[resourceId]; + }); + } + else { + return resourceStore; + } + } + function filterEventInstancesInRange(eventInstances, activeRange) { + return core.filterHash(eventInstances, function (eventInstance) { + return core.rangesIntersect(eventInstance.range, activeRange); + }); + } + function computeHasEvents(eventInstances, eventDefs) { + var hasEvents = {}; + for (var instanceId in eventInstances) { + var instance = eventInstances[instanceId]; + for (var _i = 0, _a = eventDefs[instance.defId].resourceIds; _i < _a.length; _i++) { + var resourceId = _a[_i]; + hasEvents[resourceId] = true; + } + } + return hasEvents; + } + /* + mark resources as having events if any of their ancestors have them + NOTE: resourceStore might not have all the resources that hasEvents{} has keyed + */ + function computeAncestorHasEvents(hasEvents, resourceStore) { + var res = {}; + for (var resourceId in hasEvents) { + var resource = void 0; + while ((resource = resourceStore[resourceId])) { + resourceId = resource.parentId; // now functioning as the parentId + if (resourceId) { + res[resourceId] = true; + } + else { + break; + } + } + } + return res; + } + // for when non-resource view should be given EventUi info (for event coloring/constraints based off of resource data) + var ResourceEventConfigAdder = /** @class */ (function () { + function ResourceEventConfigAdder() { + this.buildResourceEventUis = core.memoizeOutput(buildResourceEventUis, core.isPropsEqual); + this.injectResourceEventUis = core.memoize(injectResourceEventUis); + } + ResourceEventConfigAdder.prototype.transform = function (viewProps, viewSpec, calendarProps) { + if (!viewSpec.class.needsResourceData) { // is a non-resource view? + return { + eventUiBases: this.injectResourceEventUis(viewProps.eventUiBases, viewProps.eventStore.defs, this.buildResourceEventUis(calendarProps.resourceStore)) + }; + } + }; + return ResourceEventConfigAdder; + }()); + function buildResourceEventUis(resourceStore) { + return core.mapHash(resourceStore, function (resource) { + return resource.ui; + }); + } + function injectResourceEventUis(eventUiBases, eventDefs, resourceEventUis) { + return core.mapHash(eventUiBases, function (eventUi, defId) { + if (defId) { // not the '' key + return injectResourceEventUi(eventUi, eventDefs[defId], resourceEventUis); + } + else { + return eventUi; + } + }); + } + function injectResourceEventUi(origEventUi, eventDef, resourceEventUis) { + var parts = []; + // first resource takes precedence, which fights with the ordering of combineEventUis, thus the unshifts + for (var _i = 0, _a = eventDef.resourceIds; _i < _a.length; _i++) { + var resourceId = _a[_i]; + if (resourceEventUis[resourceId]) { + parts.unshift(resourceEventUis[resourceId]); + } + } + parts.unshift(origEventUi); + return core.combineEventUis(parts); + } + // for making sure events that have editable resources are always draggable in resource views + function transformIsDraggable(val, eventDef, eventUi, view) { + if (!val) { + if (view.viewSpec.class.needsResourceData) { + if (computeResourceEditable(eventDef, view.calendar)) { + return true; + } + } + } + return val; + } + + var RESOURCE_SOURCE_PROPS = { + id: String + }; + var defs = []; + var uid = 0; + function registerResourceSourceDef(def) { + defs.push(def); + } + function getResourceSourceDef(id) { + return defs[id]; + } + function doesSourceIgnoreRange(source) { + return Boolean(defs[source.sourceDefId].ignoreRange); + } + function parseResourceSource(input) { + for (var i = defs.length - 1; i >= 0; i--) { // later-added plugins take precedence + var def = defs[i]; + var meta = def.parseMeta(input); + if (meta) { + var res = parseResourceSourceProps((typeof input === 'object' && input) ? input : {}, meta, i); + res._raw = input; + return res; + } + } + return null; + } + function parseResourceSourceProps(input, meta, sourceDefId) { + var props = core.refineProps(input, RESOURCE_SOURCE_PROPS); + props.sourceId = String(uid++); + props.sourceDefId = sourceDefId; + props.meta = meta; + props.publicId = props.id; + props.isFetching = false; + props.latestFetchId = ''; + props.fetchRange = null; + delete props.id; + return props; + } + + function reduceResourceSource (source, action, dateProfile, calendar) { + switch (action.type) { + case 'INIT': + return createSource(calendar.opt('resources'), calendar); + case 'RESET_RESOURCE_SOURCE': + return createSource(action.resourceSourceInput, calendar, true); + case 'PREV': // TODO: how do we track all actions that affect dateProfile :( + case 'NEXT': + case 'SET_DATE': + case 'SET_VIEW_TYPE': + return handleRange(source, dateProfile.activeRange, calendar); + case 'RECEIVE_RESOURCES': + case 'RECEIVE_RESOURCE_ERROR': + return receiveResponse(source, action.fetchId, action.fetchRange); + case 'REFETCH_RESOURCES': + return fetchSource(source, dateProfile.activeRange, calendar); + default: + return source; + } + } + var uid$1 = 0; + function createSource(input, calendar, forceFetch) { + if (input) { + var source = parseResourceSource(input); + if (forceFetch || !calendar.opt('refetchResourcesOnNavigate')) { // because assumes handleRange will do it later + source = fetchSource(source, null, calendar); + } + return source; + } + return null; + } + function handleRange(source, activeRange, calendar) { + if (calendar.opt('refetchResourcesOnNavigate') && + !doesSourceIgnoreRange(source) && + (!source.fetchRange || !core.rangesEqual(source.fetchRange, activeRange))) { + return fetchSource(source, activeRange, calendar); + } + else { + return source; + } + } + function fetchSource(source, fetchRange, calendar) { + var sourceDef = getResourceSourceDef(source.sourceDefId); + var fetchId = String(uid$1++); + sourceDef.fetch({ + resourceSource: source, + calendar: calendar, + range: fetchRange + }, function (res) { + // HACK + // do before calling dispatch in case dispatch renders synchronously + calendar.afterSizingTriggers._resourcesRendered = [null]; // fire once + calendar.dispatch({ + type: 'RECEIVE_RESOURCES', + fetchId: fetchId, + fetchRange: fetchRange, + rawResources: res.rawResources + }); + }, function (error) { + calendar.dispatch({ + type: 'RECEIVE_RESOURCE_ERROR', + fetchId: fetchId, + fetchRange: fetchRange, + error: error + }); + }); + return __assign({}, source, { isFetching: true, latestFetchId: fetchId }); + } + function receiveResponse(source, fetchId, fetchRange) { + if (fetchId === source.latestFetchId) { + return __assign({}, source, { isFetching: false, fetchRange: fetchRange }); + } + return source; + } + + var RESOURCE_PROPS = { + id: String, + title: String, + parentId: String, + businessHours: null, + children: null, + extendedProps: null + }; + var PRIVATE_ID_PREFIX = '_fc:'; + var uid$2 = 0; + /* + needs a full store so that it can populate children too + */ + function parseResource(input, parentId, store, calendar) { + if (parentId === void 0) { parentId = ''; } + var leftovers0 = {}; + var props = core.refineProps(input, RESOURCE_PROPS, {}, leftovers0); + var leftovers1 = {}; + var ui = core.processScopedUiProps('event', leftovers0, calendar, leftovers1); + if (!props.id) { + props.id = PRIVATE_ID_PREFIX + (uid$2++); + } + if (!props.parentId) { // give precedence to the parentId property + props.parentId = parentId; + } + props.businessHours = props.businessHours ? core.parseBusinessHours(props.businessHours, calendar) : null; + props.ui = ui; + props.extendedProps = __assign({}, leftovers1, props.extendedProps); + // help out ResourceApi from having user modify props + Object.freeze(ui.classNames); + Object.freeze(props.extendedProps); + if (store[props.id]) ; + else { + store[props.id] = props; + if (props.children) { + for (var _i = 0, _a = props.children; _i < _a.length; _i++) { + var childInput = _a[_i]; + parseResource(childInput, props.id, store, calendar); + } + delete props.children; + } + } + return props; + } + /* + TODO: use this in more places + */ + function getPublicId(id) { + if (id.indexOf(PRIVATE_ID_PREFIX) === 0) { + return ''; + } + return id; + } + + function reduceResourceStore (store, action, source, calendar) { + switch (action.type) { + case 'INIT': + return {}; + case 'RECEIVE_RESOURCES': + return receiveRawResources(store, action.rawResources, action.fetchId, source, calendar); + case 'ADD_RESOURCE': + return addResource(store, action.resourceHash); + case 'REMOVE_RESOURCE': + return removeResource(store, action.resourceId); + case 'SET_RESOURCE_PROP': + return setResourceProp(store, action.resourceId, action.propName, action.propValue); + case 'RESET_RESOURCES': + // must make the calendar think each resource is a new object :/ + return core.mapHash(store, function (resource) { + return __assign({}, resource); + }); + default: + return store; + } + } + function receiveRawResources(existingStore, inputs, fetchId, source, calendar) { + if (source.latestFetchId === fetchId) { + var nextStore = {}; + for (var _i = 0, inputs_1 = inputs; _i < inputs_1.length; _i++) { + var input = inputs_1[_i]; + parseResource(input, '', nextStore, calendar); + } + return nextStore; + } + else { + return existingStore; + } + } + function addResource(existingStore, additions) { + // TODO: warn about duplicate IDs + return __assign({}, existingStore, additions); + } + function removeResource(existingStore, resourceId) { + var newStore = __assign({}, existingStore); + delete newStore[resourceId]; + // promote children + for (var childResourceId in newStore) { // a child, *maybe* but probably not + if (newStore[childResourceId].parentId === resourceId) { + newStore[childResourceId] = __assign({}, newStore[childResourceId], { parentId: '' }); + } + } + return newStore; + } + function setResourceProp(existingStore, resourceId, name, value) { + var _a, _b; + var existingResource = existingStore[resourceId]; + // TODO: sanitization + if (existingResource) { + return __assign({}, existingStore, (_a = {}, _a[resourceId] = __assign({}, existingResource, (_b = {}, _b[name] = value, _b)), _a)); + } + else { + return existingStore; + } + } + + function reduceResourceEntityExpansions(expansions, action) { + var _a; + switch (action.type) { + case 'INIT': + return {}; + case 'SET_RESOURCE_ENTITY_EXPANDED': + return __assign({}, expansions, (_a = {}, _a[action.id] = action.isExpanded, _a)); + default: + return expansions; + } + } + + function resourcesReducers (state, action, calendar) { + var resourceSource = reduceResourceSource(state.resourceSource, action, state.dateProfile, calendar); + var resourceStore = reduceResourceStore(state.resourceStore, action, resourceSource, calendar); + var resourceEntityExpansions = reduceResourceEntityExpansions(state.resourceEntityExpansions, action); + return __assign({}, state, { resourceSource: resourceSource, + resourceStore: resourceStore, + resourceEntityExpansions: resourceEntityExpansions }); + } + + var RESOURCE_RELATED_PROPS = { + resourceId: String, + resourceIds: function (items) { + return (items || []).map(function (item) { + return String(item); + }); + }, + resourceEditable: Boolean + }; + function parseEventDef(def, props, leftovers) { + var resourceRelatedProps = core.refineProps(props, RESOURCE_RELATED_PROPS, {}, leftovers); + var resourceIds = resourceRelatedProps.resourceIds; + if (resourceRelatedProps.resourceId) { + resourceIds.push(resourceRelatedProps.resourceId); + } + def.resourceIds = resourceIds; + def.resourceEditable = resourceRelatedProps.resourceEditable; + } + + function transformDateSelectionJoin(hit0, hit1) { + var resourceId0 = hit0.dateSpan.resourceId; + var resourceId1 = hit1.dateSpan.resourceId; + if (resourceId0 && resourceId1) { + if (hit0.component.allowAcrossResources === false && + resourceId0 !== resourceId1) { + return false; + } + else { + return { resourceId: resourceId0 }; + } + } + } + + var ResourceApi = /** @class */ (function () { + function ResourceApi(calendar, rawResource) { + this._calendar = calendar; + this._resource = rawResource; + } + ResourceApi.prototype.setProp = function (name, value) { + this._calendar.dispatch({ + type: 'SET_RESOURCE_PROP', + resourceId: this._resource.id, + propName: name, + propValue: value + }); + }; + ResourceApi.prototype.remove = function () { + this._calendar.dispatch({ + type: 'REMOVE_RESOURCE', + resourceId: this._resource.id + }); + }; + ResourceApi.prototype.getParent = function () { + var calendar = this._calendar; + var parentId = this._resource.parentId; + if (parentId) { + return new ResourceApi(calendar, calendar.state.resourceSource[parentId]); + } + else { + return null; + } + }; + ResourceApi.prototype.getChildren = function () { + var thisResourceId = this._resource.id; + var calendar = this._calendar; + var resourceStore = calendar.state.resourceStore; + var childApis = []; + for (var resourceId in resourceStore) { + if (resourceStore[resourceId].parentId === thisResourceId) { + childApis.push(new ResourceApi(calendar, resourceStore[resourceId])); + } + } + return childApis; + }; + /* + this is really inefficient! + TODO: make EventApi::resourceIds a hash or keep an index in the Calendar's state + */ + ResourceApi.prototype.getEvents = function () { + var thisResourceId = this._resource.id; + var calendar = this._calendar; + var _a = calendar.state.eventStore, defs = _a.defs, instances = _a.instances; + var eventApis = []; + for (var instanceId in instances) { + var instance = instances[instanceId]; + var def = defs[instance.defId]; + if (def.resourceIds.indexOf(thisResourceId) !== -1) { // inefficient!!! + eventApis.push(new core.EventApi(calendar, def, instance)); + } + } + return eventApis; + }; + Object.defineProperty(ResourceApi.prototype, "id", { + get: function () { return this._resource.id; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ResourceApi.prototype, "title", { + get: function () { return this._resource.title; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ResourceApi.prototype, "eventConstraint", { + get: function () { return this._resource.ui.constraints[0] || null; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ResourceApi.prototype, "eventOverlap", { + get: function () { return this._resource.ui.overlap; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ResourceApi.prototype, "eventAllow", { + get: function () { return this._resource.ui.allows[0] || null; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ResourceApi.prototype, "eventBackgroundColor", { + get: function () { return this._resource.ui.backgroundColor; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ResourceApi.prototype, "eventBorderColor", { + get: function () { return this._resource.ui.borderColor; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ResourceApi.prototype, "eventTextColor", { + get: function () { return this._resource.ui.textColor; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ResourceApi.prototype, "eventClassNames", { + // NOTE: user can't modify these because Object.freeze was called in event-def parsing + get: function () { return this._resource.ui.classNames; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ResourceApi.prototype, "extendedProps", { + get: function () { return this._resource.extendedProps; }, + enumerable: true, + configurable: true + }); + return ResourceApi; + }()); + + core.Calendar.prototype.addResource = function (input, scrollTo) { + var _a; + if (scrollTo === void 0) { scrollTo = true; } + var resourceHash; + var resource; + if (input instanceof ResourceApi) { + resource = input._resource; + resourceHash = (_a = {}, _a[resource.id] = resource, _a); + } + else { + resourceHash = {}; + resource = parseResource(input, '', resourceHash, this); + } + // HACK + if (scrollTo) { + this.component.view.addScroll({ forcedRowId: resource.id }); + } + this.dispatch({ + type: 'ADD_RESOURCE', + resourceHash: resourceHash + }); + return new ResourceApi(this, resource); + }; + core.Calendar.prototype.getResourceById = function (id) { + id = String(id); + if (this.state.resourceStore) { // guard against calendar with no resource functionality + var rawResource = this.state.resourceStore[id]; + if (rawResource) { + return new ResourceApi(this, rawResource); + } + } + return null; + }; + core.Calendar.prototype.getResources = function () { + var resourceStore = this.state.resourceStore; + var resourceApis = []; + if (resourceStore) { // guard against calendar with no resource functionality + for (var resourceId in resourceStore) { + resourceApis.push(new ResourceApi(this, resourceStore[resourceId])); + } + } + return resourceApis; + }; + core.Calendar.prototype.getTopLevelResources = function () { + var resourceStore = this.state.resourceStore; + var resourceApis = []; + if (resourceStore) { // guard against calendar with no resource functionality + for (var resourceId in resourceStore) { + if (!resourceStore[resourceId].parentId) { + resourceApis.push(new ResourceApi(this, resourceStore[resourceId])); + } + } + } + return resourceApis; + }; + core.Calendar.prototype.rerenderResources = function () { + this.dispatch({ + type: 'RESET_RESOURCES' + }); + }; + core.Calendar.prototype.refetchResources = function () { + this.dispatch({ + type: 'REFETCH_RESOURCES' + }); + }; + function transformDatePoint(dateSpan, calendar) { + return dateSpan.resourceId ? + { resource: calendar.getResourceById(dateSpan.resourceId) } : + {}; + } + function transformDateSpan(dateSpan, calendar) { + return dateSpan.resourceId ? + { resource: calendar.getResourceById(dateSpan.resourceId) } : + {}; + } + + /* + splits things BASED OFF OF which resources they are associated with. + creates a '' entry which is when something has NO resource. + */ + var ResourceSplitter = /** @class */ (function (_super) { + __extends(ResourceSplitter, _super); + function ResourceSplitter() { + return _super !== null && _super.apply(this, arguments) || this; + } + ResourceSplitter.prototype.getKeyInfo = function (props) { + return __assign({ '': {} }, props.resourceStore // already has `ui` and `businessHours` keys! + ); + }; + ResourceSplitter.prototype.getKeysForDateSpan = function (dateSpan) { + return [dateSpan.resourceId || '']; + }; + ResourceSplitter.prototype.getKeysForEventDef = function (eventDef) { + var resourceIds = eventDef.resourceIds; + if (!resourceIds.length) { + return ['']; + } + return resourceIds; + }; + return ResourceSplitter; + }(core.Splitter)); + + function isPropsValidWithResources(props, calendar) { + var splitter = new ResourceSplitter(); + var sets = splitter.splitProps(__assign({}, props, { resourceStore: calendar.state.resourceStore })); + for (var resourceId in sets) { + var props_1 = sets[resourceId]; + // merge in event data from the non-resource segment + if (resourceId && sets['']) { // current segment is not the non-resource one, and there IS a non-resource one + props_1 = __assign({}, props_1, { eventStore: core.mergeEventStores(sets[''].eventStore, props_1.eventStore), eventUiBases: __assign({}, sets[''].eventUiBases, props_1.eventUiBases) }); + } + if (!core.isPropsValid(props_1, calendar, { resourceId: resourceId }, filterConfig.bind(null, resourceId))) { + return false; + } + } + return true; + } + function filterConfig(resourceId, config) { + return __assign({}, config, { constraints: filterConstraints(resourceId, config.constraints) }); + } + function filterConstraints(resourceId, constraints) { + return constraints.map(function (constraint) { + var defs = constraint.defs; + if (defs) { // we are dealing with an EventStore + // if any of the events define constraints to resources that are NOT this resource, + // then this resource is unconditionally prohibited, which is what a `false` value does. + for (var defId in defs) { + var resourceIds = defs[defId].resourceIds; + if (resourceIds.length && resourceIds.indexOf(resourceId) === -1) { // TODO: use a hash?!!! (for other reasons too) + return false; + } + } + } + return constraint; + }); + } + + function transformExternalDef(dateSpan) { + return dateSpan.resourceId ? + { resourceId: dateSpan.resourceId } : + {}; + } + + function transformEventResizeJoin(hit0, hit1) { + var component = hit0.component; + if (component.allowAcrossResources === false && + hit0.dateSpan.resourceId !== hit1.dateSpan.resourceId) { + return false; + } + } + + core.EventApi.prototype.getResources = function () { + var calendar = this._calendar; + return this._def.resourceIds.map(function (resourceId) { + return calendar.getResourceById(resourceId); + }); + }; + core.EventApi.prototype.setResources = function (resources) { + var resourceIds = []; + // massage resources -> resourceIds + for (var _i = 0, resources_1 = resources; _i < resources_1.length; _i++) { + var resource = resources_1[_i]; + var resourceId = null; + if (typeof resource === 'string') { + resourceId = resource; + } + else if (typeof resource === 'number') { + resourceId = String(resource); + } + else if (resource instanceof ResourceApi) { + resourceId = resource.id; // guaranteed to always have an ID. hmmm + } + else { + console.warn('unknown resource type: ' + resource); + } + if (resourceId) { + resourceIds.push(resourceId); + } + } + this.mutate({ + standardProps: { + resourceIds: resourceIds + } + }); + }; + + var RELEASE_DATE = '2019-08-10'; // for Scheduler + var UPGRADE_WINDOW = 365 + 7; // days. 1 week leeway, for tz shift reasons too + var LICENSE_INFO_URL = 'http://fullcalendar.io/scheduler/license/'; + var PRESET_LICENSE_KEYS = [ + 'GPL-My-Project-Is-Open-Source', + 'CC-Attribution-NonCommercial-NoDerivatives' + ]; + var CSS = { + position: 'absolute', + 'z-index': 99999, + bottom: '1px', + left: '1px', + background: '#eee', + 'border-color': '#ddd', + 'border-style': 'solid', + 'border-width': '1px 1px 0 0', + padding: '2px 4px', + 'font-size': '12px', + 'border-top-right-radius': '3px' + }; + function injectLicenseWarning(containerEl, calendar) { + var key = calendar.opt('schedulerLicenseKey'); + if (!isImmuneUrl(window.location.href) && !isValidKey(key)) { + core.appendToElement(containerEl, '<div class="fc-license-message" style="' + core.htmlEscape(core.cssToStr(CSS)) + '">' + + 'Please use a valid license key. <a href="' + LICENSE_INFO_URL + '">More Info</a>' + + '</div>'); + } + } + /* + This decryption is not meant to be bulletproof. Just a way to remind about an upgrade. + */ + function isValidKey(key) { + if (PRESET_LICENSE_KEYS.indexOf(key) !== -1) { + return true; + } + var parts = (key || '').match(/^(\d+)\-fcs\-(\d+)$/); + if (parts && (parts[1].length === 10)) { + var purchaseDate = new Date(parseInt(parts[2], 10) * 1000); + var releaseDate = new Date(core.config.mockSchedulerReleaseDate || RELEASE_DATE); + if (core.isValidDate(releaseDate)) { // token won't be replaced in dev mode + var minPurchaseDate = core.addDays(releaseDate, -UPGRADE_WINDOW); + if (minPurchaseDate < purchaseDate) { + return true; + } + } + } + return false; + } + function isImmuneUrl(url) { + return /\w+\:\/\/fullcalendar\.io\/|\/examples\/[\w-]+\.html$/.test(url); + } + + var optionChangeHandlers = { + resources: handleResources + }; + function handleResources(newSourceInput, calendar, deepEqual) { + var oldSourceInput = calendar.state.resourceSource._raw; + if (!deepEqual(oldSourceInput, newSourceInput)) { + calendar.dispatch({ + type: 'RESET_RESOURCE_SOURCE', + resourceSourceInput: newSourceInput + }); + } + } + + registerResourceSourceDef({ + ignoreRange: true, + parseMeta: function (raw) { + if (Array.isArray(raw)) { + return raw; + } + else if (Array.isArray(raw.resources)) { + return raw.resources; + } + return null; + }, + fetch: function (arg, successCallback) { + successCallback({ + rawResources: arg.resourceSource.meta + }); + } + }); + + registerResourceSourceDef({ + parseMeta: function (raw) { + if (typeof raw === 'function') { + return raw; + } + else if (typeof raw.resources === 'function') { + return raw.resources; + } + return null; + }, + fetch: function (arg, success, failure) { + var dateEnv = arg.calendar.dateEnv; + var func = arg.resourceSource.meta; + var publicArg = {}; + if (arg.range) { + publicArg = { + start: dateEnv.toDate(arg.range.start), + end: dateEnv.toDate(arg.range.end), + startStr: dateEnv.formatIso(arg.range.start), + endStr: dateEnv.formatIso(arg.range.end), + timeZone: dateEnv.timeZone + }; + } + // TODO: make more dry with EventSourceFunc + // TODO: accept a response? + core.unpromisify(func.bind(null, publicArg), function (rawResources) { + success({ rawResources: rawResources }); // needs an object response + }, failure // send errorObj directly to failure callback + ); + } + }); + + registerResourceSourceDef({ + parseMeta: function (raw) { + if (typeof raw === 'string') { + raw = { url: raw }; + } + else if (!raw || typeof raw !== 'object' || !raw.url) { + return null; + } + return { + url: raw.url, + method: (raw.method || 'GET').toUpperCase(), + extraParams: raw.extraParams + }; + }, + fetch: function (arg, successCallback, failureCallback) { + var meta = arg.resourceSource.meta; + var requestParams = buildRequestParams(meta, arg.range, arg.calendar); + core.requestJson(meta.method, meta.url, requestParams, function (rawResources, xhr) { + successCallback({ rawResources: rawResources, xhr: xhr }); + }, function (message, xhr) { + failureCallback({ message: message, xhr: xhr }); + }); + } + }); + // TODO: somehow consolidate with event json feed + function buildRequestParams(meta, range, calendar) { + var dateEnv = calendar.dateEnv; + var startParam; + var endParam; + var timeZoneParam; + var customRequestParams; + var params = {}; + if (range) { + // startParam = meta.startParam + // if (startParam == null) { + startParam = calendar.opt('startParam'); + // } + // endParam = meta.endParam + // if (endParam == null) { + endParam = calendar.opt('endParam'); + // } + // timeZoneParam = meta.timeZoneParam + // if (timeZoneParam == null) { + timeZoneParam = calendar.opt('timeZoneParam'); + // } + params[startParam] = dateEnv.formatIso(range.start); + params[endParam] = dateEnv.formatIso(range.end); + if (dateEnv.timeZone !== 'local') { + params[timeZoneParam] = dateEnv.timeZone; + } + } + // retrieve any outbound GET/POST data from the options + if (typeof meta.extraParams === 'function') { + // supplied as a function that returns a key/value object + customRequestParams = meta.extraParams(); + } + else { + // probably supplied as a straight key/value object + customRequestParams = meta.extraParams || {}; + } + __assign(params, customRequestParams); + return params; + } + + function buildResourceTextFunc(resourceTextSetting, calendar) { + if (typeof resourceTextSetting === 'function') { + return function (resource) { + return resourceTextSetting(new ResourceApi(calendar, resource)); + }; + } + else { + return function (resource) { + return resource.title || getPublicId(resource.id); + }; + } + } + + var ResourceDayHeader = /** @class */ (function (_super) { + __extends(ResourceDayHeader, _super); + function ResourceDayHeader(context, parentEl) { + var _this = _super.call(this, context) || this; + _this.datesAboveResources = _this.opt('datesAboveResources'); + _this.resourceTextFunc = buildResourceTextFunc(_this.opt('resourceText'), _this.calendar); + parentEl.innerHTML = ''; // because might be nbsp + parentEl.appendChild(_this.el = core.htmlToElement('<div class="fc-row ' + _this.theme.getClass('headerRow') + '">' + + '<table class="' + _this.theme.getClass('tableGrid') + '">' + + '<thead></thead>' + + '</table>' + + '</div>')); + _this.thead = _this.el.querySelector('thead'); + return _this; + } + ResourceDayHeader.prototype.destroy = function () { + core.removeElement(this.el); + }; + ResourceDayHeader.prototype.render = function (props) { + var html; + this.dateFormat = core.createFormatter(this.opt('columnHeaderFormat') || + core.computeFallbackHeaderFormat(props.datesRepDistinctDays, props.dates.length)); + if (props.dates.length === 1) { + html = this.renderResourceRow(props.resources); + } + else { + if (this.datesAboveResources) { + html = this.renderDayAndResourceRows(props.dates, props.resources); + } + else { + html = this.renderResourceAndDayRows(props.resources, props.dates); + } + } + this.thead.innerHTML = html; + this.processResourceEls(props.resources); + }; + ResourceDayHeader.prototype.renderResourceRow = function (resources) { + var _this = this; + var cellHtmls = resources.map(function (resource) { + return _this.renderResourceCell(resource, 1); + }); + return this.buildTr(cellHtmls); + }; + ResourceDayHeader.prototype.renderDayAndResourceRows = function (dates, resources) { + var dateHtmls = []; + var resourceHtmls = []; + for (var _i = 0, dates_1 = dates; _i < dates_1.length; _i++) { + var date = dates_1[_i]; + dateHtmls.push(this.renderDateCell(date, resources.length)); + for (var _a = 0, resources_1 = resources; _a < resources_1.length; _a++) { + var resource = resources_1[_a]; + resourceHtmls.push(this.renderResourceCell(resource, 1, date)); + } + } + return this.buildTr(dateHtmls) + + this.buildTr(resourceHtmls); + }; + ResourceDayHeader.prototype.renderResourceAndDayRows = function (resources, dates) { + var resourceHtmls = []; + var dateHtmls = []; + for (var _i = 0, resources_2 = resources; _i < resources_2.length; _i++) { + var resource = resources_2[_i]; + resourceHtmls.push(this.renderResourceCell(resource, dates.length)); + for (var _a = 0, dates_2 = dates; _a < dates_2.length; _a++) { + var date = dates_2[_a]; + dateHtmls.push(this.renderDateCell(date, 1, resource)); + } + } + return this.buildTr(resourceHtmls) + + this.buildTr(dateHtmls); + }; + // Cell Rendering Utils + // ---------------------------------------------------------------------------------------------- + // a cell with the resource name. might be associated with a specific day + ResourceDayHeader.prototype.renderResourceCell = function (resource, colspan, date) { + var dateEnv = this.dateEnv; + return '<th class="fc-resource-cell"' + + ' data-resource-id="' + resource.id + '"' + + (date ? + ' data-date="' + dateEnv.formatIso(date, { omitTime: true }) + '"' : + '') + + (colspan > 1 ? + ' colspan="' + colspan + '"' : + '') + + '>' + + core.htmlEscape(this.resourceTextFunc(resource)) + + '</th>'; + }; + // a cell with date text. might have a resource associated with it + ResourceDayHeader.prototype.renderDateCell = function (date, colspan, resource) { + var props = this.props; + return core.renderDateCell(date, props.dateProfile, props.datesRepDistinctDays, props.dates.length * props.resources.length, this.dateFormat, this.context, colspan, resource ? 'data-resource-id="' + resource.id + '"' : ''); + }; + ResourceDayHeader.prototype.buildTr = function (cellHtmls) { + if (!cellHtmls.length) { + cellHtmls = ['<td> </td>']; + } + if (this.props.renderIntroHtml) { + cellHtmls = [this.props.renderIntroHtml()].concat(cellHtmls); + } + if (this.isRtl) { + cellHtmls.reverse(); + } + return '<tr>' + + cellHtmls.join('') + + '</tr>'; + }; + // Post-rendering + // ---------------------------------------------------------------------------------------------- + // given a container with already rendered resource cells + ResourceDayHeader.prototype.processResourceEls = function (resources) { + var _this = this; + var view = this.view; + core.findElements(this.thead, '.fc-resource-cell').forEach(function (node, col) { + col = col % resources.length; + if (_this.isRtl) { + col = resources.length - 1 - col; + } + var resource = resources[col]; + view.publiclyTrigger('resourceRender', [ + { + resource: new ResourceApi(_this.calendar, resource), + el: node, + view: view + } + ]); + }); + }; + return ResourceDayHeader; + }(core.Component)); + + var AbstractResourceDayTable = /** @class */ (function () { + function AbstractResourceDayTable(dayTable, resources) { + this.dayTable = dayTable; + this.resources = resources; + this.resourceIndex = new ResourceIndex(resources); + this.rowCnt = dayTable.rowCnt; + this.colCnt = dayTable.colCnt * resources.length; + this.cells = this.buildCells(); + } + AbstractResourceDayTable.prototype.buildCells = function () { + var _a = this, rowCnt = _a.rowCnt, dayTable = _a.dayTable, resources = _a.resources; + var rows = []; + for (var row = 0; row < rowCnt; row++) { + var rowCells = []; + for (var dateCol = 0; dateCol < dayTable.colCnt; dateCol++) { + for (var resourceCol = 0; resourceCol < resources.length; resourceCol++) { + var resource = resources[resourceCol]; + var htmlAttrs = 'data-resource-id="' + resource.id + '"'; + rowCells[this.computeCol(dateCol, resourceCol)] = { + date: dayTable.cells[row][dateCol].date, + resource: resource, + htmlAttrs: htmlAttrs + }; + } + } + rows.push(rowCells); + } + return rows; + }; + return AbstractResourceDayTable; + }()); + /* + resources over dates + */ + var ResourceDayTable = /** @class */ (function (_super) { + __extends(ResourceDayTable, _super); + function ResourceDayTable() { + return _super !== null && _super.apply(this, arguments) || this; + } + ResourceDayTable.prototype.computeCol = function (dateI, resourceI) { + return resourceI * this.dayTable.colCnt + dateI; + }; + /* + all date ranges are intact + */ + ResourceDayTable.prototype.computeColRanges = function (dateStartI, dateEndI, resourceI) { + return [ + { + firstCol: this.computeCol(dateStartI, resourceI), + lastCol: this.computeCol(dateEndI, resourceI), + isStart: true, + isEnd: true + } + ]; + }; + return ResourceDayTable; + }(AbstractResourceDayTable)); + /* + dates over resources + */ + var DayResourceTable = /** @class */ (function (_super) { + __extends(DayResourceTable, _super); + function DayResourceTable() { + return _super !== null && _super.apply(this, arguments) || this; + } + DayResourceTable.prototype.computeCol = function (dateI, resourceI) { + return dateI * this.resources.length + resourceI; + }; + /* + every single day is broken up + */ + DayResourceTable.prototype.computeColRanges = function (dateStartI, dateEndI, resourceI) { + var segs = []; + for (var i = dateStartI; i <= dateEndI; i++) { + var col = this.computeCol(i, resourceI); + segs.push({ + firstCol: col, + lastCol: col, + isStart: i === dateStartI, + isEnd: i === dateEndI + }); + } + return segs; + }; + return DayResourceTable; + }(AbstractResourceDayTable)); + var ResourceIndex = /** @class */ (function () { + function ResourceIndex(resources) { + var indicesById = {}; + var ids = []; + for (var i = 0; i < resources.length; i++) { + var id = resources[i].id; + ids.push(id); + indicesById[id] = i; + } + this.ids = ids; + this.indicesById = indicesById; + this.length = resources.length; + } + return ResourceIndex; + }()); + /* + TODO: just use ResourceHash somehow? could then use the generic ResourceSplitter + */ + var VResourceSplitter = /** @class */ (function (_super) { + __extends(VResourceSplitter, _super); + function VResourceSplitter() { + return _super !== null && _super.apply(this, arguments) || this; + } + VResourceSplitter.prototype.getKeyInfo = function (props) { + var resourceDayTable = props.resourceDayTable; + var hash = core.mapHash(resourceDayTable.resourceIndex.indicesById, function (i) { + return resourceDayTable.resources[i]; // has `ui` AND `businessHours` keys! + }); // :( + hash[''] = {}; + return hash; + }; + VResourceSplitter.prototype.getKeysForDateSpan = function (dateSpan) { + return [dateSpan.resourceId || '']; + }; + VResourceSplitter.prototype.getKeysForEventDef = function (eventDef) { + var resourceIds = eventDef.resourceIds; + if (!resourceIds.length) { + return ['']; + } + return resourceIds; + }; + return VResourceSplitter; + }(core.Splitter)); + // joiner + var NO_SEGS = []; // for memoizing + var VResourceJoiner = /** @class */ (function () { + function VResourceJoiner() { + this.joinDateSelection = core.memoize(this.joinSegs); + this.joinBusinessHours = core.memoize(this.joinSegs); + this.joinFgEvents = core.memoize(this.joinSegs); + this.joinBgEvents = core.memoize(this.joinSegs); + this.joinEventDrags = core.memoize(this.joinInteractions); + this.joinEventResizes = core.memoize(this.joinInteractions); + } + /* + propSets also has a '' key for things with no resource + */ + VResourceJoiner.prototype.joinProps = function (propSets, resourceDayTable) { + var dateSelectionSets = []; + var businessHoursSets = []; + var fgEventSets = []; + var bgEventSets = []; + var eventDrags = []; + var eventResizes = []; + var eventSelection = ''; + var keys = resourceDayTable.resourceIndex.ids.concat(['']); // add in the all-resource key + for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { + var key = keys_1[_i]; + var props = propSets[key]; + dateSelectionSets.push(props.dateSelectionSegs); + businessHoursSets.push(key ? props.businessHourSegs : NO_SEGS); // don't include redundant all-resource businesshours + fgEventSets.push(key ? props.fgEventSegs : NO_SEGS); // don't include fg all-resource segs + bgEventSets.push(props.bgEventSegs); + eventDrags.push(props.eventDrag); + eventResizes.push(props.eventResize); + eventSelection = eventSelection || props.eventSelection; + } + return { + dateSelectionSegs: this.joinDateSelection.apply(this, [resourceDayTable].concat(dateSelectionSets)), + businessHourSegs: this.joinBusinessHours.apply(this, [resourceDayTable].concat(businessHoursSets)), + fgEventSegs: this.joinFgEvents.apply(this, [resourceDayTable].concat(fgEventSets)), + bgEventSegs: this.joinBgEvents.apply(this, [resourceDayTable].concat(bgEventSets)), + eventDrag: this.joinEventDrags.apply(this, [resourceDayTable].concat(eventDrags)), + eventResize: this.joinEventResizes.apply(this, [resourceDayTable].concat(eventResizes)), + eventSelection: eventSelection + }; + }; + VResourceJoiner.prototype.joinSegs = function (resourceDayTable) { + var segGroups = []; + for (var _i = 1; _i < arguments.length; _i++) { + segGroups[_i - 1] = arguments[_i]; + } + var resourceCnt = resourceDayTable.resources.length; + var transformedSegs = []; + for (var i = 0; i < resourceCnt; i++) { + for (var _a = 0, _b = segGroups[i]; _a < _b.length; _a++) { + var seg = _b[_a]; + transformedSegs.push.apply(transformedSegs, this.transformSeg(seg, resourceDayTable, i)); + } + for (var _c = 0, _d = segGroups[resourceCnt]; _c < _d.length; _c++) { // one beyond. the all-resource + var seg = _d[_c]; + transformedSegs.push.apply(// one beyond. the all-resource + transformedSegs, this.transformSeg(seg, resourceDayTable, i)); + } + } + return transformedSegs; + }; + /* + for expanding non-resource segs to all resources. + only for public use. + no memoizing. + */ + VResourceJoiner.prototype.expandSegs = function (resourceDayTable, segs) { + var resourceCnt = resourceDayTable.resources.length; + var transformedSegs = []; + for (var i = 0; i < resourceCnt; i++) { + for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { + var seg = segs_1[_i]; + transformedSegs.push.apply(transformedSegs, this.transformSeg(seg, resourceDayTable, i)); + } + } + return transformedSegs; + }; + VResourceJoiner.prototype.joinInteractions = function (resourceDayTable) { + var interactions = []; + for (var _i = 1; _i < arguments.length; _i++) { + interactions[_i - 1] = arguments[_i]; + } + var resourceCnt = resourceDayTable.resources.length; + var affectedInstances = {}; + var transformedSegs = []; + var isEvent = false; + var sourceSeg = null; + for (var i = 0; i < resourceCnt; i++) { + var interaction = interactions[i]; + if (interaction) { + for (var _a = 0, _b = interaction.segs; _a < _b.length; _a++) { + var seg = _b[_a]; + transformedSegs.push.apply(transformedSegs, this.transformSeg(seg, resourceDayTable, i) // TODO: templateify Interaction::segs + ); + } + __assign(affectedInstances, interaction.affectedInstances); + isEvent = isEvent || interaction.isEvent; + sourceSeg = sourceSeg || interaction.sourceSeg; + } + if (interactions[resourceCnt]) { // one beyond. the all-resource + for (var _c = 0, _d = interactions[resourceCnt].segs; _c < _d.length; _c++) { + var seg = _d[_c]; + transformedSegs.push.apply(transformedSegs, this.transformSeg(seg, resourceDayTable, i) // TODO: templateify Interaction::segs + ); + } + } + } + return { + affectedInstances: affectedInstances, + segs: transformedSegs, + isEvent: isEvent, + sourceSeg: sourceSeg + }; + }; + return VResourceJoiner; + }()); + + /* + doesn't accept grouping + */ + function flattenResources(resourceStore, orderSpecs) { + return buildRowNodes(resourceStore, [], orderSpecs, false, {}, true) + .map(function (node) { + return node.resource; + }); + } + function buildRowNodes(resourceStore, groupSpecs, orderSpecs, isVGrouping, expansions, expansionDefault) { + var complexNodes = buildHierarchy(resourceStore, isVGrouping ? -1 : 1, groupSpecs, orderSpecs); + var flatNodes = []; + flattenNodes(complexNodes, flatNodes, isVGrouping, [], 0, expansions, expansionDefault); + return flatNodes; + } + function flattenNodes(complexNodes, res, isVGrouping, rowSpans, depth, expansions, expansionDefault) { + for (var i = 0; i < complexNodes.length; i++) { + var complexNode = complexNodes[i]; + var group = complexNode.group; + if (group) { + if (isVGrouping) { + var firstRowIndex = res.length; + var rowSpanIndex = rowSpans.length; + flattenNodes(complexNode.children, res, isVGrouping, rowSpans.concat(0), depth, expansions, expansionDefault); + if (firstRowIndex < res.length) { + var firstRow = res[firstRowIndex]; + var firstRowSpans = firstRow.rowSpans = firstRow.rowSpans.slice(); + firstRowSpans[rowSpanIndex] = res.length - firstRowIndex; + } + } + else { + var id = group.spec.field + ':' + group.value; + var isExpanded = expansions[id] != null ? expansions[id] : expansionDefault; + res.push({ id: id, group: group, isExpanded: isExpanded }); + if (isExpanded) { + flattenNodes(complexNode.children, res, isVGrouping, rowSpans, depth + 1, expansions, expansionDefault); + } + } + } + else if (complexNode.resource) { + var id = complexNode.resource.id; + var isExpanded = expansions[id] != null ? expansions[id] : expansionDefault; + res.push({ + id: id, + rowSpans: rowSpans, + depth: depth, + isExpanded: isExpanded, + hasChildren: Boolean(complexNode.children.length), + resource: complexNode.resource, + resourceFields: complexNode.resourceFields + }); + if (isExpanded) { + flattenNodes(complexNode.children, res, isVGrouping, rowSpans, depth + 1, expansions, expansionDefault); + } + } + } + } + function buildHierarchy(resourceStore, maxDepth, groupSpecs, orderSpecs) { + var resourceNodes = buildResourceNodes(resourceStore, orderSpecs); + var builtNodes = []; + for (var resourceId in resourceNodes) { + var resourceNode = resourceNodes[resourceId]; + if (!resourceNode.resource.parentId) { + insertResourceNode(resourceNode, builtNodes, groupSpecs, 0, maxDepth, orderSpecs); + } + } + return builtNodes; + } + function buildResourceNodes(resourceStore, orderSpecs) { + var nodeHash = {}; + for (var resourceId in resourceStore) { + var resource = resourceStore[resourceId]; + nodeHash[resourceId] = { + resource: resource, + resourceFields: buildResourceFields(resource), + children: [] + }; + } + for (var resourceId in resourceStore) { + var resource = resourceStore[resourceId]; + if (resource.parentId) { + var parentNode = nodeHash[resource.parentId]; + if (parentNode) { + insertResourceNodeInSiblings(nodeHash[resourceId], parentNode.children, orderSpecs); + } + } + } + return nodeHash; + } + function insertResourceNode(resourceNode, nodes, groupSpecs, depth, maxDepth, orderSpecs) { + if (groupSpecs.length && (maxDepth === -1 || depth <= maxDepth)) { + var groupNode = ensureGroupNodes(resourceNode, nodes, groupSpecs[0]); + insertResourceNode(resourceNode, groupNode.children, groupSpecs.slice(1), depth + 1, maxDepth, orderSpecs); + } + else { + insertResourceNodeInSiblings(resourceNode, nodes, orderSpecs); + } + } + function ensureGroupNodes(resourceNode, nodes, groupSpec) { + var groupValue = resourceNode.resourceFields[groupSpec.field]; + var groupNode; + var newGroupIndex; + // find an existing group that matches, or determine the position for a new group + if (groupSpec.order) { + for (newGroupIndex = 0; newGroupIndex < nodes.length; newGroupIndex++) { + var node = nodes[newGroupIndex]; + if (node.group) { + var cmp = core.flexibleCompare(groupValue, node.group.value) * groupSpec.order; + if (cmp === 0) { + groupNode = node; + break; + } + else if (cmp < 0) { + break; + } + } + } + } + else { // the groups are unordered + for (newGroupIndex = 0; newGroupIndex < nodes.length; newGroupIndex++) { + var node = nodes[newGroupIndex]; + if (node.group && groupValue === node.group.value) { + groupNode = node; + break; + } + } + } + if (!groupNode) { + groupNode = { + group: { + value: groupValue, + spec: groupSpec + }, + children: [] + }; + nodes.splice(newGroupIndex, 0, groupNode); + } + return groupNode; + } + function insertResourceNodeInSiblings(resourceNode, siblings, orderSpecs) { + var i; + for (i = 0; i < siblings.length; i++) { + var cmp = core.compareByFieldSpecs(siblings[i].resourceFields, resourceNode.resourceFields, orderSpecs); + if (cmp > 0) { // went 1 past. insert at i + break; + } + } + siblings.splice(i, 0, resourceNode); + } + function buildResourceFields(resource) { + var obj = __assign({}, resource.extendedProps, resource.ui, resource); + delete obj.ui; + delete obj.extendedProps; + return obj; + } + function isGroupsEqual(group0, group1) { + return group0.spec === group1.spec && group0.value === group1.value; + } + + var main = core.createPlugin({ + reducers: [resourcesReducers], + eventDefParsers: [parseEventDef], + isDraggableTransformers: [transformIsDraggable], + eventDragMutationMassagers: [massageEventDragMutation], + eventDefMutationAppliers: [applyEventDefMutation], + dateSelectionTransformers: [transformDateSelectionJoin], + datePointTransforms: [transformDatePoint], + dateSpanTransforms: [transformDateSpan], + viewPropsTransformers: [ResourceDataAdder, ResourceEventConfigAdder], + isPropsValid: isPropsValidWithResources, + externalDefTransforms: [transformExternalDef], + eventResizeJoinTransforms: [transformEventResizeJoin], + viewContainerModifiers: [injectLicenseWarning], + eventDropTransformers: [transformEventDrop], + optionChangeHandlers: optionChangeHandlers + }); + + exports.AbstractResourceDayTable = AbstractResourceDayTable; + exports.DayResourceTable = DayResourceTable; + exports.ResourceApi = ResourceApi; + exports.ResourceDayHeader = ResourceDayHeader; + exports.ResourceDayTable = ResourceDayTable; + exports.ResourceSplitter = ResourceSplitter; + exports.VResourceJoiner = VResourceJoiner; + exports.VResourceSplitter = VResourceSplitter; + exports.buildResourceFields = buildResourceFields; + exports.buildResourceTextFunc = buildResourceTextFunc; + exports.buildRowNodes = buildRowNodes; + exports.default = main; + exports.flattenResources = flattenResources; + exports.isGroupsEqual = isGroupsEqual; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-common/main.min.js b/AKPlan/static/AKPlan/fullcalendar/resource-common/main.min.js new file mode 100644 index 00000000..a3a3cb8a --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-common/main.min.js @@ -0,0 +1,6 @@ +/*! +FullCalendar Resources Common Plugin v4.3.1 +Docs & License: https://fullcalendar.io/scheduler +(c) 2019 Adam Shaw +*/ +!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("@fullcalendar/core")):"function"==typeof define&&define.amd?define(["exports","@fullcalendar/core"],r):r((e=e||self).FullCalendarResourceCommon={},e.FullCalendar)}(this,function(e,r){"use strict";var t=function(e,r){return(t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,r){e.__proto__=r}||function(e,r){for(var t in r)r.hasOwnProperty(t)&&(e[t]=r[t])})(e,r)};function n(e,r){function n(){this.constructor=e}t(e,r),e.prototype=null===r?Object.create(r):(n.prototype=r.prototype,new n)}var o=function(){return(o=Object.assign||function(e){for(var r,t=1,n=arguments.length;t<n;t++)for(var o in r=arguments[t])Object.prototype.hasOwnProperty.call(r,o)&&(e[o]=r[o]);return e}).apply(this,arguments)};function s(e,r){var t=e.resourceEditable;if(null==t){var n=e.sourceId&&r.state.eventSources[e.sourceId];n&&(t=n.extendedProps.resourceEditable),null==t&&null==(t=r.opt("eventResourceEditable"))&&(t=r.opt("editable"))}return t}var u=function(){function e(){this.filterResources=r.memoize(i)}return e.prototype.transform=function(e,r,t,n){if(r.class.needsResourceData)return{resourceStore:this.filterResources(t.resourceStore,n.opt("filterResourcesWithEvents"),t.eventStore,t.dateProfile.activeRange),resourceEntityExpansions:t.resourceEntityExpansions}},e}();function i(e,t,n,s){if(t){var u=function(e,r){var t={};for(var n in e)for(var o=e[n],s=0,u=r[o.defId].resourceIds;s<u.length;s++){var i=u[s];t[i]=!0}return t}(function(e,t){return r.filterHash(e,function(e){return r.rangesIntersect(e.range,t)})}(n.instances,s),n.defs);return o(u,function(e,r){var t={};for(var n in e)for(var o=void 0;(o=r[n])&&(n=o.parentId);)t[n]=!0;return t}(u,e)),r.filterHash(e,function(e,r){return u[r]})}return e}var a=function(){function e(){this.buildResourceEventUis=r.memoizeOutput(c,r.isPropsEqual),this.injectResourceEventUis=r.memoize(l)}return e.prototype.transform=function(e,r,t){if(!r.class.needsResourceData)return{eventUiBases:this.injectResourceEventUis(e.eventUiBases,e.eventStore.defs,this.buildResourceEventUis(t.resourceStore))}},e}();function c(e){return r.mapHash(e,function(e){return e.ui})}function l(e,t,n){return r.mapHash(e,function(e,o){return o?function(e,t,n){for(var o=[],s=0,u=t.resourceIds;s<u.length;s++){var i=u[s];n[i]&&o.unshift(n[i])}return o.unshift(e),r.combineEventUis(o)}(e,t[o],n):e})}var d={id:String},f=[],p=0;function h(e){f.push(e)}function v(e,t,n){var o=r.refineProps(e,d);return o.sourceId=String(p++),o.sourceDefId=n,o.meta=t,o.publicId=o.id,o.isFetching=!1,o.latestFetchId="",o.fetchRange=null,delete o.id,o}function g(e,t,n,s){switch(t.type){case"INIT":return y(s.opt("resources"),s);case"RESET_RESOURCE_SOURCE":return y(t.resourceSourceInput,s,!0);case"PREV":case"NEXT":case"SET_DATE":case"SET_VIEW_TYPE":return function(e,t,n){return!n.opt("refetchResourcesOnNavigate")||function(e){return Boolean(f[e.sourceDefId].ignoreRange)}(e)||e.fetchRange&&r.rangesEqual(e.fetchRange,t)?e:E(e,t,n)}(e,n.activeRange,s);case"RECEIVE_RESOURCES":case"RECEIVE_RESOURCE_ERROR":return function(e,r,t){if(r===e.latestFetchId)return o({},e,{isFetching:!1,fetchRange:t});return e}(e,t.fetchId,t.fetchRange);case"REFETCH_RESOURCES":return E(e,n.activeRange,s);default:return e}}var R=0;function y(e,r,t){if(e){var n=function(e){for(var r=f.length-1;r>=0;r--){var t=f[r].parseMeta(e);if(t){var n=v("object"==typeof e&&e?e:{},t,r);return n._raw=e,n}}return null}(e);return!t&&r.opt("refetchResourcesOnNavigate")||(n=E(n,null,r)),n}return null}function E(e,r,t){var n,s=(n=e.sourceDefId,f[n]),u=String(R++);return s.fetch({resourceSource:e,calendar:t,range:r},function(e){t.afterSizingTriggers._resourcesRendered=[null],t.dispatch({type:"RECEIVE_RESOURCES",fetchId:u,fetchRange:r,rawResources:e.rawResources})},function(e){t.dispatch({type:"RECEIVE_RESOURCE_ERROR",fetchId:u,fetchRange:r,error:e})}),o({},e,{isFetching:!0,latestFetchId:u})}var m={id:String,title:String,parentId:String,businessHours:null,children:null,extendedProps:null},S="_fc:",I=0;function b(e,t,n,s){void 0===t&&(t="");var u={},i=r.refineProps(e,m,{},u),a={},c=r.processScopedUiProps("event",u,s,a);if(i.id||(i.id=S+I++),i.parentId||(i.parentId=t),i.businessHours=i.businessHours?r.parseBusinessHours(i.businessHours,s):null,i.ui=c,i.extendedProps=o({},a,i.extendedProps),Object.freeze(c.classNames),Object.freeze(i.extendedProps),n[i.id]);else if(n[i.id]=i,i.children){for(var l=0,d=i.children;l<d.length;l++){b(d[l],i.id,n,s)}delete i.children}return i}function C(e,t,n,s){switch(t.type){case"INIT":return{};case"RECEIVE_RESOURCES":return function(e,r,t,n,o){if(n.latestFetchId===t){for(var s={},u=0,i=r;u<i.length;u++){var a=i[u];b(a,"",s,o)}return s}return e}(e,t.rawResources,t.fetchId,n,s);case"ADD_RESOURCE":return u=e,i=t.resourceHash,o({},u,i);case"REMOVE_RESOURCE":return function(e,r){var t=o({},e);for(var n in delete t[r],t)t[n].parentId===r&&(t[n]=o({},t[n],{parentId:""}));return t}(e,t.resourceId);case"SET_RESOURCE_PROP":return function(e,r,t,n){var s,u,i=e[r];return i?o({},e,((s={})[r]=o({},i,((u={})[t]=n,u)),s)):e}(e,t.resourceId,t.propName,t.propValue);case"RESET_RESOURCES":return r.mapHash(e,function(e){return o({},e)});default:return e}var u,i}var _={resourceId:String,resourceIds:function(e){return(e||[]).map(function(e){return String(e)})},resourceEditable:Boolean};var w=function(){function e(e,r){this._calendar=e,this._resource=r}return e.prototype.setProp=function(e,r){this._calendar.dispatch({type:"SET_RESOURCE_PROP",resourceId:this._resource.id,propName:e,propValue:r})},e.prototype.remove=function(){this._calendar.dispatch({type:"REMOVE_RESOURCE",resourceId:this._resource.id})},e.prototype.getParent=function(){var r=this._calendar,t=this._resource.parentId;return t?new e(r,r.state.resourceSource[t]):null},e.prototype.getChildren=function(){var r=this._resource.id,t=this._calendar,n=t.state.resourceStore,o=[];for(var s in n)n[s].parentId===r&&o.push(new e(t,n[s]));return o},e.prototype.getEvents=function(){var e=this._resource.id,t=this._calendar,n=t.state.eventStore,o=n.defs,s=n.instances,u=[];for(var i in s){var a=s[i],c=o[a.defId];-1!==c.resourceIds.indexOf(e)&&u.push(new r.EventApi(t,c,a))}return u},Object.defineProperty(e.prototype,"id",{get:function(){return this._resource.id},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"title",{get:function(){return this._resource.title},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"eventConstraint",{get:function(){return this._resource.ui.constraints[0]||null},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"eventOverlap",{get:function(){return this._resource.ui.overlap},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"eventAllow",{get:function(){return this._resource.ui.allows[0]||null},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"eventBackgroundColor",{get:function(){return this._resource.ui.backgroundColor},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"eventBorderColor",{get:function(){return this._resource.ui.borderColor},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"eventTextColor",{get:function(){return this._resource.ui.textColor},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"eventClassNames",{get:function(){return this._resource.ui.classNames},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"extendedProps",{get:function(){return this._resource.extendedProps},enumerable:!0,configurable:!0}),e}();r.Calendar.prototype.addResource=function(e,r){var t,n,o;return void 0===r&&(r=!0),e instanceof w?((t={})[(o=e._resource).id]=o,n=t):o=b(e,"",n={},this),r&&this.component.view.addScroll({forcedRowId:o.id}),this.dispatch({type:"ADD_RESOURCE",resourceHash:n}),new w(this,o)},r.Calendar.prototype.getResourceById=function(e){if(e=String(e),this.state.resourceStore){var r=this.state.resourceStore[e];if(r)return new w(this,r)}return null},r.Calendar.prototype.getResources=function(){var e=this.state.resourceStore,r=[];if(e)for(var t in e)r.push(new w(this,e[t]));return r},r.Calendar.prototype.getTopLevelResources=function(){var e=this.state.resourceStore,r=[];if(e)for(var t in e)e[t].parentId||r.push(new w(this,e[t]));return r},r.Calendar.prototype.rerenderResources=function(){this.dispatch({type:"RESET_RESOURCES"})},r.Calendar.prototype.refetchResources=function(){this.dispatch({type:"REFETCH_RESOURCES"})};var P=function(e){function r(){return null!==e&&e.apply(this,arguments)||this}return n(r,e),r.prototype.getKeyInfo=function(e){return o({"":{}},e.resourceStore)},r.prototype.getKeysForDateSpan=function(e){return[e.resourceId||""]},r.prototype.getKeysForEventDef=function(e){var r=e.resourceIds;return r.length?r:[""]},r}(r.Splitter);function O(e,r){return o({},r,{constraints:x(e,r.constraints)})}function x(e,r){return r.map(function(r){var t=r.defs;if(t)for(var n in t){var o=t[n].resourceIds;if(o.length&&-1===o.indexOf(e))return!1}return r})}r.EventApi.prototype.getResources=function(){var e=this._calendar;return this._def.resourceIds.map(function(r){return e.getResourceById(r)})},r.EventApi.prototype.setResources=function(e){for(var r=[],t=0,n=e;t<n.length;t++){var o=n[t],s=null;"string"==typeof o?s=o:"number"==typeof o?s=String(o):o instanceof w?s=o.id:console.warn("unknown resource type: "+o),s&&r.push(s)}this.mutate({standardProps:{resourceIds:r}})};var T="2019-08-10",D=372,j="http://fullcalendar.io/scheduler/license/",F=["GPL-My-Project-Is-Open-Source","CC-Attribution-NonCommercial-NoDerivatives"],U={position:"absolute","z-index":99999,bottom:"1px",left:"1px",background:"#eee","border-color":"#ddd","border-style":"solid","border-width":"1px 1px 0 0",padding:"2px 4px","font-size":"12px","border-top-right-radius":"3px"};var A={resources:function(e,r,t){var n=r.state.resourceSource._raw;t(n,e)||r.dispatch({type:"RESET_RESOURCE_SOURCE",resourceSourceInput:e})}};function H(e,r){return"function"==typeof e?function(t){return e(new w(r,t))}:function(e){return e.title||(0===(r=e.id).indexOf(S)?"":r);var r}}h({ignoreRange:!0,parseMeta:function(e){return Array.isArray(e)?e:Array.isArray(e.resources)?e.resources:null},fetch:function(e,r){r({rawResources:e.resourceSource.meta})}}),h({parseMeta:function(e){return"function"==typeof e?e:"function"==typeof e.resources?e.resources:null},fetch:function(e,t,n){var o=e.calendar.dateEnv,s=e.resourceSource.meta,u={};e.range&&(u={start:o.toDate(e.range.start),end:o.toDate(e.range.end),startStr:o.formatIso(e.range.start),endStr:o.formatIso(e.range.end),timeZone:o.timeZone}),r.unpromisify(s.bind(null,u),function(e){t({rawResources:e})},n)}}),h({parseMeta:function(e){if("string"==typeof e)e={url:e};else if(!e||"object"!=typeof e||!e.url)return null;return{url:e.url,method:(e.method||"GET").toUpperCase(),extraParams:e.extraParams}},fetch:function(e,t,n){var s=e.resourceSource.meta,u=function(e,r,t){var n,s,u,i,a=t.dateEnv,c={};r&&(n=t.opt("startParam"),s=t.opt("endParam"),u=t.opt("timeZoneParam"),c[n]=a.formatIso(r.start),c[s]=a.formatIso(r.end),"local"!==a.timeZone&&(c[u]=a.timeZone));i="function"==typeof e.extraParams?e.extraParams():e.extraParams||{};return o(c,i),c}(s,e.range,e.calendar);r.requestJson(s.method,s.url,u,function(e,r){t({rawResources:e,xhr:r})},function(e,r){n({message:e,xhr:r})})}});var B=function(e){function t(t,n){var o=e.call(this,t)||this;return o.datesAboveResources=o.opt("datesAboveResources"),o.resourceTextFunc=H(o.opt("resourceText"),o.calendar),n.innerHTML="",n.appendChild(o.el=r.htmlToElement('<div class="fc-row '+o.theme.getClass("headerRow")+'"><table class="'+o.theme.getClass("tableGrid")+'"><thead></thead></table></div>')),o.thead=o.el.querySelector("thead"),o}return n(t,e),t.prototype.destroy=function(){r.removeElement(this.el)},t.prototype.render=function(e){var t;this.dateFormat=r.createFormatter(this.opt("columnHeaderFormat")||r.computeFallbackHeaderFormat(e.datesRepDistinctDays,e.dates.length)),t=1===e.dates.length?this.renderResourceRow(e.resources):this.datesAboveResources?this.renderDayAndResourceRows(e.dates,e.resources):this.renderResourceAndDayRows(e.resources,e.dates),this.thead.innerHTML=t,this.processResourceEls(e.resources)},t.prototype.renderResourceRow=function(e){var r=this,t=e.map(function(e){return r.renderResourceCell(e,1)});return this.buildTr(t)},t.prototype.renderDayAndResourceRows=function(e,r){for(var t=[],n=[],o=0,s=e;o<s.length;o++){var u=s[o];t.push(this.renderDateCell(u,r.length));for(var i=0,a=r;i<a.length;i++){var c=a[i];n.push(this.renderResourceCell(c,1,u))}}return this.buildTr(t)+this.buildTr(n)},t.prototype.renderResourceAndDayRows=function(e,r){for(var t=[],n=[],o=0,s=e;o<s.length;o++){var u=s[o];t.push(this.renderResourceCell(u,r.length));for(var i=0,a=r;i<a.length;i++){var c=a[i];n.push(this.renderDateCell(c,1,u))}}return this.buildTr(t)+this.buildTr(n)},t.prototype.renderResourceCell=function(e,t,n){var o=this.dateEnv;return'<th class="fc-resource-cell" data-resource-id="'+e.id+'"'+(n?' data-date="'+o.formatIso(n,{omitTime:!0})+'"':"")+(t>1?' colspan="'+t+'"':"")+">"+r.htmlEscape(this.resourceTextFunc(e))+"</th>"},t.prototype.renderDateCell=function(e,t,n){var o=this.props;return r.renderDateCell(e,o.dateProfile,o.datesRepDistinctDays,o.dates.length*o.resources.length,this.dateFormat,this.context,t,n?'data-resource-id="'+n.id+'"':"")},t.prototype.buildTr=function(e){return e.length||(e=["<td> </td>"]),this.props.renderIntroHtml&&(e=[this.props.renderIntroHtml()].concat(e)),this.isRtl&&e.reverse(),"<tr>"+e.join("")+"</tr>"},t.prototype.processResourceEls=function(e){var t=this,n=this.view;r.findElements(this.thead,".fc-resource-cell").forEach(function(r,o){o%=e.length,t.isRtl&&(o=e.length-1-o);var s=e[o];n.publiclyTrigger("resourceRender",[{resource:new w(t.calendar,s),el:r,view:n}])})},t}(r.Component),z=function(){function e(e,r){this.dayTable=e,this.resources=r,this.resourceIndex=new V(r),this.rowCnt=e.rowCnt,this.colCnt=e.colCnt*r.length,this.cells=this.buildCells()}return e.prototype.buildCells=function(){for(var e=this.rowCnt,r=this.dayTable,t=this.resources,n=[],o=0;o<e;o++){for(var s=[],u=0;u<r.colCnt;u++)for(var i=0;i<t.length;i++){var a=t[i],c='data-resource-id="'+a.id+'"';s[this.computeCol(u,i)]={date:r.cells[o][u].date,resource:a,htmlAttrs:c}}n.push(s)}return n},e}(),M=function(e){function r(){return null!==e&&e.apply(this,arguments)||this}return n(r,e),r.prototype.computeCol=function(e,r){return r*this.dayTable.colCnt+e},r.prototype.computeColRanges=function(e,r,t){return[{firstCol:this.computeCol(e,t),lastCol:this.computeCol(r,t),isStart:!0,isEnd:!0}]},r}(z),N=function(e){function r(){return null!==e&&e.apply(this,arguments)||this}return n(r,e),r.prototype.computeCol=function(e,r){return e*this.resources.length+r},r.prototype.computeColRanges=function(e,r,t){for(var n=[],o=e;o<=r;o++){var s=this.computeCol(o,t);n.push({firstCol:s,lastCol:s,isStart:o===e,isEnd:o===r})}return n},r}(z),V=function(e){for(var r={},t=[],n=0;n<e.length;n++){var o=e[n].id;t.push(o),r[o]=n}this.ids=t,this.indicesById=r,this.length=e.length},k=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return n(t,e),t.prototype.getKeyInfo=function(e){var t=e.resourceDayTable,n=r.mapHash(t.resourceIndex.indicesById,function(e){return t.resources[e]});return n[""]={},n},t.prototype.getKeysForDateSpan=function(e){return[e.resourceId||""]},t.prototype.getKeysForEventDef=function(e){var r=e.resourceIds;return r.length?r:[""]},t}(r.Splitter),K=[],q=function(){function e(){this.joinDateSelection=r.memoize(this.joinSegs),this.joinBusinessHours=r.memoize(this.joinSegs),this.joinFgEvents=r.memoize(this.joinSegs),this.joinBgEvents=r.memoize(this.joinSegs),this.joinEventDrags=r.memoize(this.joinInteractions),this.joinEventResizes=r.memoize(this.joinInteractions)}return e.prototype.joinProps=function(e,r){for(var t=[],n=[],o=[],s=[],u=[],i=[],a="",c=0,l=r.resourceIndex.ids.concat([""]);c<l.length;c++){var d=l[c],f=e[d];t.push(f.dateSelectionSegs),n.push(d?f.businessHourSegs:K),o.push(d?f.fgEventSegs:K),s.push(f.bgEventSegs),u.push(f.eventDrag),i.push(f.eventResize),a=a||f.eventSelection}return{dateSelectionSegs:this.joinDateSelection.apply(this,[r].concat(t)),businessHourSegs:this.joinBusinessHours.apply(this,[r].concat(n)),fgEventSegs:this.joinFgEvents.apply(this,[r].concat(o)),bgEventSegs:this.joinBgEvents.apply(this,[r].concat(s)),eventDrag:this.joinEventDrags.apply(this,[r].concat(u)),eventResize:this.joinEventResizes.apply(this,[r].concat(i)),eventSelection:a}},e.prototype.joinSegs=function(e){for(var r=[],t=1;t<arguments.length;t++)r[t-1]=arguments[t];for(var n=e.resources.length,o=[],s=0;s<n;s++){for(var u=0,i=r[s];u<i.length;u++){var a=i[u];o.push.apply(o,this.transformSeg(a,e,s))}for(var c=0,l=r[n];c<l.length;c++){a=l[c];o.push.apply(o,this.transformSeg(a,e,s))}}return o},e.prototype.expandSegs=function(e,r){for(var t=e.resources.length,n=[],o=0;o<t;o++)for(var s=0,u=r;s<u.length;s++){var i=u[s];n.push.apply(n,this.transformSeg(i,e,o))}return n},e.prototype.joinInteractions=function(e){for(var r=[],t=1;t<arguments.length;t++)r[t-1]=arguments[t];for(var n=e.resources.length,s={},u=[],i=!1,a=null,c=0;c<n;c++){var l=r[c];if(l){for(var d=0,f=l.segs;d<f.length;d++){var p=f[d];u.push.apply(u,this.transformSeg(p,e,c))}o(s,l.affectedInstances),i=i||l.isEvent,a=a||l.sourceSeg}if(r[n])for(var h=0,v=r[n].segs;h<v.length;h++){p=v[h];u.push.apply(u,this.transformSeg(p,e,c))}}return{affectedInstances:s,segs:u,isEvent:i,sourceSeg:a}},e}();function L(e,r,t,n,o,s){var u=[];return function e(r,t,n,o,s,u,i){for(var a=0;a<r.length;a++){var c=r[a],l=c.group;if(l)if(n){var d=t.length,f=o.length;if(e(c.children,t,n,o.concat(0),s,u,i),d<t.length){var p=t[d],h=p.rowSpans=p.rowSpans.slice();h[f]=t.length-d}}else{var v=l.spec.field+":"+l.value,g=null!=u[v]?u[v]:i;t.push({id:v,group:l,isExpanded:g}),g&&e(c.children,t,n,o,s+1,u,i)}else if(c.resource){var v=c.resource.id,g=null!=u[v]?u[v]:i;t.push({id:v,rowSpans:o,depth:s,isExpanded:g,hasChildren:Boolean(c.children.length),resource:c.resource,resourceFields:c.resourceFields}),g&&e(c.children,t,n,o,s+1,u,i)}}}(function(e,r,t,n){var o=function(e,r){var t={};for(var n in e){var o=e[n];t[n]={resource:o,resourceFields:J(o),children:[]}}for(var n in e){var o=e[n];if(o.parentId){var s=t[o.parentId];s&&G(t[n],s.children,r)}}return t}(e,n),s=[];for(var u in o){var i=o[u];i.resource.parentId||Z(i,s,t,0,r,n)}return s}(e,n?-1:1,r,t),u,n,[],0,o,s),u}function Z(e,t,n,o,s,u){n.length&&(-1===s||o<=s)?Z(e,function(e,t,n){var o,s,u=e.resourceFields[n.field];if(n.order)for(s=0;s<t.length;s++){var i=t[s];if(i.group){var a=r.flexibleCompare(u,i.group.value)*n.order;if(0===a){o=i;break}if(a<0)break}}else for(s=0;s<t.length;s++){var i=t[s];if(i.group&&u===i.group.value){o=i;break}}o||(o={group:{value:u,spec:n},children:[]},t.splice(s,0,o));return o}(e,t,n[0]).children,n.slice(1),o+1,s,u):G(e,t,u)}function G(e,t,n){var o;for(o=0;o<t.length;o++){if(r.compareByFieldSpecs(t[o].resourceFields,e.resourceFields,n)>0)break}t.splice(o,0,e)}function J(e){var r=o({},e.extendedProps,e.ui,e);return delete r.ui,delete r.extendedProps,r}var W=r.createPlugin({reducers:[function(e,r,t){var n=g(e.resourceSource,r,e.dateProfile,t),s=C(e.resourceStore,r,n,t),u=function(e,r){var t;switch(r.type){case"INIT":return{};case"SET_RESOURCE_ENTITY_EXPANDED":return o({},e,((t={})[r.id]=r.isExpanded,t));default:return e}}(e.resourceEntityExpansions,r);return o({},e,{resourceSource:n,resourceStore:s,resourceEntityExpansions:u})}],eventDefParsers:[function(e,t,n){var o=r.refineProps(t,_,{},n),s=o.resourceIds;o.resourceId&&s.push(o.resourceId),e.resourceIds=s,e.resourceEditable=o.resourceEditable}],isDraggableTransformers:[function(e,r,t,n){return!(e||!n.viewSpec.class.needsResourceData||!s(r,n.calendar))||e}],eventDragMutationMassagers:[function(e,r,t){var n=r.dateSpan.resourceId,o=t.dateSpan.resourceId;n&&o&&n!==o&&(e.resourceMutation={matchResourceId:n,setResourceId:o})}],eventDefMutationAppliers:[function(e,r,t){var n=r.resourceMutation;if(n&&s(e,t)){var o=e.resourceIds.indexOf(n.matchResourceId);if(-1!==o){var u=e.resourceIds.slice();u.splice(o,1),-1===u.indexOf(n.setResourceId)&&u.push(n.setResourceId),e.resourceIds=u}}}],dateSelectionTransformers:[function(e,r){var t=e.dateSpan.resourceId,n=r.dateSpan.resourceId;if(t&&n)return(!1!==e.component.allowAcrossResources||t===n)&&{resourceId:t}}],datePointTransforms:[function(e,r){return e.resourceId?{resource:r.getResourceById(e.resourceId)}:{}}],dateSpanTransforms:[function(e,r){return e.resourceId?{resource:r.getResourceById(e.resourceId)}:{}}],viewPropsTransformers:[u,a],isPropsValid:function(e,t){var n=(new P).splitProps(o({},e,{resourceStore:t.state.resourceStore}));for(var s in n){var u=n[s];if(s&&n[""]&&(u=o({},u,{eventStore:r.mergeEventStores(n[""].eventStore,u.eventStore),eventUiBases:o({},n[""].eventUiBases,u.eventUiBases)})),!r.isPropsValid(u,t,{resourceId:s},O.bind(null,s)))return!1}return!0},externalDefTransforms:[function(e){return e.resourceId?{resourceId:e.resourceId}:{}}],eventResizeJoinTransforms:[function(e,r){if(!1===e.component.allowAcrossResources&&e.dateSpan.resourceId!==r.dateSpan.resourceId)return!1}],viewContainerModifiers:[function(e,t){var n,o=t.opt("schedulerLicenseKey");n=window.location.href,/\w+\:\/\/fullcalendar\.io\/|\/examples\/[\w-]+\.html$/.test(n)||function(e){if(-1!==F.indexOf(e))return!0;var t=(e||"").match(/^(\d+)\-fcs\-(\d+)$/);if(t&&10===t[1].length){var n=new Date(1e3*parseInt(t[2],10)),o=new Date(r.config.mockSchedulerReleaseDate||T);if(r.isValidDate(o)){var s=r.addDays(o,-D);if(s<n)return!0}}return!1}(o)||r.appendToElement(e,'<div class="fc-license-message" style="'+r.htmlEscape(r.cssToStr(U))+'">Please use a valid license key. <a href="'+j+'">More Info</a></div>')}],eventDropTransformers:[function(e,r){var t=e.resourceMutation;return t?{oldResource:r.getResourceById(t.matchResourceId),newResource:r.getResourceById(t.setResourceId)}:{oldResource:null,newResource:null}}],optionChangeHandlers:A});e.AbstractResourceDayTable=z,e.DayResourceTable=N,e.ResourceApi=w,e.ResourceDayHeader=B,e.ResourceDayTable=M,e.ResourceSplitter=P,e.VResourceJoiner=q,e.VResourceSplitter=k,e.buildResourceFields=J,e.buildResourceTextFunc=H,e.buildRowNodes=L,e.default=W,e.flattenResources=function(e,r){return L(e,[],r,!1,{},!0).map(function(e){return e.resource})},e.isGroupsEqual=function(e,r){return e.spec===r.spec&&e.value===r.value},Object.defineProperty(e,"__esModule",{value:!0})}); \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-common/package.json b/AKPlan/static/AKPlan/fullcalendar/resource-common/package.json new file mode 100644 index 00000000..0af6409e --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-common/package.json @@ -0,0 +1,33 @@ +{ + "name": "@fullcalendar/resource-common", + "version": "4.3.1", + "title": "FullCalendar Resources Common Plugin", + "description": "Offers base support for resources. Required for all resource-related plugins.", + "keywords": [ + "calendar", + "event", + "full-sized" + ], + "homepage": "https://fullcalendar.io/scheduler", + "docs": "https://fullcalendar.io/docs/scheduler", + "bugs": "https://fullcalendar.io/reporting-bugs", + "repository": { + "type": "git", + "url": "https://github.com/fullcalendar/fullcalendar-scheduler.git", + "homepage": "https://github.com/fullcalendar/fullcalendar-scheduler" + }, + "license": "SEE LICENSE IN LICENSE.md", + "author": { + "name": "Adam Shaw", + "email": "arshaw@arshaw.com", + "url": "http://arshaw.com/" + }, + "copyright": "2019 Adam Shaw", + "peerDependencies": { + "@fullcalendar/core": "~4.3.0" + }, + "main": "main.js", + "module": "main.esm.js", + "unpkg": "main.min.js", + "types": "main.d.ts" +} diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-daygrid/LICENSE.md b/AKPlan/static/AKPlan/fullcalendar/resource-daygrid/LICENSE.md new file mode 100644 index 00000000..52296639 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-daygrid/LICENSE.md @@ -0,0 +1,18 @@ + +For complete licensing information, visit: +http://fullcalendar.io/scheduler/license + +FullCalendar Scheduler is tri-licensed, meaning you must choose +one of three licenses to use. Here is a summary of those licenses: + +- Commercial License + (a paid license, meant for commercial use) + http://fullcalendar.io/scheduler/license-details + +- Creative Commons Non-Commercial No-Derivatives + (meant for trial and non-commercial use) + https://creativecommons.org/licenses/by-nc-nd/4.0/ + +- GPLv3 License + (meant for open-source projects) + http://www.gnu.org/licenses/gpl-3.0.en.html diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-daygrid/README.md b/AKPlan/static/AKPlan/fullcalendar/resource-daygrid/README.md new file mode 100644 index 00000000..c56092c0 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-daygrid/README.md @@ -0,0 +1,8 @@ + +# FullCalendar Resource Day Grid Plugin + +Displays events in individual columns for days and resources + +[View the docs »](https://fullcalendar.io/docs/resource-daygrid-view) + +This package was created from the [FullCalendar monorepo »](https://github.com/fullcalendar/fullcalendar-scheduler) diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-daygrid/main.d.ts b/AKPlan/static/AKPlan/fullcalendar/resource-daygrid/main.d.ts new file mode 100644 index 00000000..e92d21b6 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-daygrid/main.d.ts @@ -0,0 +1,59 @@ +// Generated by dts-bundle v0.7.3-fork.1 +// Dependencies for this module: +// ../../../../../@fullcalendar/core +// ../../../../../@fullcalendar/daygrid +// ../../../../../@fullcalendar/resource-common + +declare module '@fullcalendar/resource-daygrid' { + import ResourceDayGridView from '@fullcalendar/resource-daygrid/ResourceDayGridView'; + export { ResourceDayGridView }; + export { default as ResourceDayGrid } from '@fullcalendar/resource-daygrid/ResourceDayGrid'; + const _default: import("@fullcalendar/core").PluginDef; + export default _default; +} + +declare module '@fullcalendar/resource-daygrid/ResourceDayGridView' { + import { ComponentContext, ViewSpec, DateProfileGenerator } from '@fullcalendar/core'; + import { AbstractDayGridView } from '@fullcalendar/daygrid'; + import { ResourceDayHeader, ResourceViewProps } from '@fullcalendar/resource-common'; + import ResourceDayGrid from '@fullcalendar/resource-daygrid/ResourceDayGrid'; + export { ResourceDayGridView as default, ResourceDayGridView }; + class ResourceDayGridView extends AbstractDayGridView { + static needsResourceData: boolean; + props: ResourceViewProps; + header: ResourceDayHeader; + resourceDayGrid: ResourceDayGrid; + constructor(context: ComponentContext, viewSpec: ViewSpec, dateProfileGenerator: DateProfileGenerator, parentEl: HTMLElement); + destroy(): void; + render(props: ResourceViewProps): void; + } +} + +declare module '@fullcalendar/resource-daygrid/ResourceDayGrid' { + import { Hit, DateSpan, DateComponent, DateProfile, EventStore, EventUiHash, EventInteractionState, ComponentContext, Duration } from '@fullcalendar/core'; + import { DayGrid } from '@fullcalendar/daygrid'; + import { AbstractResourceDayTable } from '@fullcalendar/resource-common'; + export interface ResourceDayGridProps { + dateProfile: DateProfile | null; + resourceDayTable: AbstractResourceDayTable; + businessHours: EventStore; + eventStore: EventStore; + eventUiBases: EventUiHash; + dateSelection: DateSpan | null; + eventSelection: string; + eventDrag: EventInteractionState | null; + eventResize: EventInteractionState | null; + isRigid: boolean; + nextDayThreshold: Duration; + } + export { ResourceDayGrid as default, ResourceDayGrid }; + class ResourceDayGrid extends DateComponent<ResourceDayGridProps> { + dayGrid: DayGrid; + constructor(context: ComponentContext, dayGrid: DayGrid); + destroy(): void; + render(props: ResourceDayGridProps): void; + buildPositionCaches(): void; + queryHit(positionLeft: number, positionTop: number): Hit; + } +} + diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-daygrid/main.esm.js b/AKPlan/static/AKPlan/fullcalendar/resource-daygrid/main.esm.js new file mode 100644 index 00000000..2c573004 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-daygrid/main.esm.js @@ -0,0 +1,203 @@ +/*! +FullCalendar Resource Day Grid Plugin v4.3.0 +Docs & License: https://fullcalendar.io/scheduler +(c) 2019 Adam Shaw +*/ + +import { mapHash, DateComponent, memoize, parseFieldSpecs, createPlugin } from '@fullcalendar/core'; +import ResourceCommonPlugin, { VResourceSplitter, VResourceJoiner, flattenResources, ResourceDayHeader, DayResourceTable, ResourceDayTable } from '@fullcalendar/resource-common'; +import DayGridPlugin, { DayGridSlicer, AbstractDayGridView, buildBasicDayTable } from '@fullcalendar/daygrid'; + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} + +var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; + +var ResourceDayGrid = /** @class */ (function (_super) { + __extends(ResourceDayGrid, _super); + function ResourceDayGrid(context, dayGrid) { + var _this = _super.call(this, context, dayGrid.el) || this; + _this.splitter = new VResourceSplitter(); + _this.slicers = {}; + _this.joiner = new ResourceDayGridJoiner(); + _this.dayGrid = dayGrid; + context.calendar.registerInteractiveComponent(_this, { + el: _this.dayGrid.el + }); + return _this; + } + ResourceDayGrid.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.calendar.unregisterInteractiveComponent(this); + }; + ResourceDayGrid.prototype.render = function (props) { + var _this = this; + var dayGrid = this.dayGrid; + var dateProfile = props.dateProfile, resourceDayTable = props.resourceDayTable, nextDayThreshold = props.nextDayThreshold; + var splitProps = this.splitter.splitProps(props); + this.slicers = mapHash(splitProps, function (split, resourceId) { + return _this.slicers[resourceId] || new DayGridSlicer(); + }); + var slicedProps = mapHash(this.slicers, function (slicer, resourceId) { + return slicer.sliceProps(splitProps[resourceId], dateProfile, nextDayThreshold, dayGrid, resourceDayTable.dayTable); + }); + dayGrid.allowAcrossResources = resourceDayTable.dayTable.colCnt === 1; + dayGrid.receiveProps(__assign({}, this.joiner.joinProps(slicedProps, resourceDayTable), { dateProfile: dateProfile, cells: resourceDayTable.cells, isRigid: props.isRigid })); + }; + ResourceDayGrid.prototype.buildPositionCaches = function () { + this.dayGrid.buildPositionCaches(); + }; + ResourceDayGrid.prototype.queryHit = function (positionLeft, positionTop) { + var rawHit = this.dayGrid.positionToHit(positionLeft, positionTop); + if (rawHit) { + return { + component: this.dayGrid, + dateSpan: { + range: rawHit.dateSpan.range, + allDay: rawHit.dateSpan.allDay, + resourceId: this.props.resourceDayTable.cells[rawHit.row][rawHit.col].resource.id + }, + dayEl: rawHit.dayEl, + rect: { + left: rawHit.relativeRect.left, + right: rawHit.relativeRect.right, + top: rawHit.relativeRect.top, + bottom: rawHit.relativeRect.bottom + }, + layer: 0 + }; + } + }; + return ResourceDayGrid; +}(DateComponent)); +var ResourceDayGridJoiner = /** @class */ (function (_super) { + __extends(ResourceDayGridJoiner, _super); + function ResourceDayGridJoiner() { + return _super !== null && _super.apply(this, arguments) || this; + } + ResourceDayGridJoiner.prototype.transformSeg = function (seg, resourceDayTable, resourceI) { + var colRanges = resourceDayTable.computeColRanges(seg.firstCol, seg.lastCol, resourceI); + return colRanges.map(function (colRange) { + return __assign({}, seg, colRange, { isStart: seg.isStart && colRange.isStart, isEnd: seg.isEnd && colRange.isEnd }); + }); + }; + return ResourceDayGridJoiner; +}(VResourceJoiner)); + +var ResourceDayGridView = /** @class */ (function (_super) { + __extends(ResourceDayGridView, _super); + function ResourceDayGridView(context, viewSpec, dateProfileGenerator, parentEl) { + var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this; + _this.flattenResources = memoize(flattenResources); + _this.buildResourceDayTable = memoize(buildResourceDayTable); + _this.resourceOrderSpecs = parseFieldSpecs(_this.opt('resourceOrder')); + if (_this.opt('columnHeader')) { + _this.header = new ResourceDayHeader(_this.context, _this.el.querySelector('.fc-head-container')); + } + _this.resourceDayGrid = new ResourceDayGrid(context, _this.dayGrid); + return _this; + } + ResourceDayGridView.prototype.destroy = function () { + _super.prototype.destroy.call(this); + if (this.header) { + this.header.destroy(); + } + this.resourceDayGrid.destroy(); + }; + ResourceDayGridView.prototype.render = function (props) { + _super.prototype.render.call(this, props); // for flags for updateSize + var resources = this.flattenResources(props.resourceStore, this.resourceOrderSpecs); + var resourceDayTable = this.buildResourceDayTable(this.props.dateProfile, this.dateProfileGenerator, resources, this.opt('datesAboveResources')); + if (this.header) { + this.header.receiveProps({ + resources: resources, + dates: resourceDayTable.dayTable.headerDates, + dateProfile: props.dateProfile, + datesRepDistinctDays: true, + renderIntroHtml: this.renderHeadIntroHtml + }); + } + this.resourceDayGrid.receiveProps({ + dateProfile: props.dateProfile, + resourceDayTable: resourceDayTable, + businessHours: props.businessHours, + eventStore: props.eventStore, + eventUiBases: props.eventUiBases, + dateSelection: props.dateSelection, + eventSelection: props.eventSelection, + eventDrag: props.eventDrag, + eventResize: props.eventResize, + isRigid: this.hasRigidRows(), + nextDayThreshold: this.nextDayThreshold + }); + }; + ResourceDayGridView.needsResourceData = true; // for ResourceViewProps + return ResourceDayGridView; +}(AbstractDayGridView)); +function buildResourceDayTable(dateProfile, dateProfileGenerator, resources, datesAboveResources) { + var dayTable = buildBasicDayTable(dateProfile, dateProfileGenerator); + return datesAboveResources ? + new DayResourceTable(dayTable, resources) : + new ResourceDayTable(dayTable, resources); +} + +var main = createPlugin({ + deps: [ResourceCommonPlugin, DayGridPlugin], + defaultView: 'resourceDayGridDay', + views: { + resourceDayGrid: ResourceDayGridView, + resourceDayGridDay: { + type: 'resourceDayGrid', + duration: { days: 1 } + }, + resourceDayGridWeek: { + type: 'resourceDayGrid', + duration: { weeks: 1 } + }, + resourceDayGridMonth: { + type: 'resourceDayGrid', + duration: { months: 1 }, + // TODO: wish we didn't have to C&P from dayGrid's file + monthMode: true, + fixedWeekCount: true + } + } +}); + +export default main; +export { ResourceDayGrid, ResourceDayGridView }; diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-daygrid/main.js b/AKPlan/static/AKPlan/fullcalendar/resource-daygrid/main.js new file mode 100644 index 00000000..6b446411 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-daygrid/main.js @@ -0,0 +1,213 @@ +/*! +FullCalendar Resource Day Grid Plugin v4.3.0 +Docs & License: https://fullcalendar.io/scheduler +(c) 2019 Adam Shaw +*/ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core'), require('@fullcalendar/resource-common'), require('@fullcalendar/daygrid')) : + typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core', '@fullcalendar/resource-common', '@fullcalendar/daygrid'], factory) : + (global = global || self, factory(global.FullCalendarResourceDayGrid = {}, global.FullCalendar, global.FullCalendarResourceCommon, global.FullCalendarDayGrid)); +}(this, function (exports, core, ResourceCommonPlugin, DayGridPlugin) { 'use strict'; + + var ResourceCommonPlugin__default = 'default' in ResourceCommonPlugin ? ResourceCommonPlugin['default'] : ResourceCommonPlugin; + var DayGridPlugin__default = 'default' in DayGridPlugin ? DayGridPlugin['default'] : DayGridPlugin; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + var ResourceDayGrid = /** @class */ (function (_super) { + __extends(ResourceDayGrid, _super); + function ResourceDayGrid(context, dayGrid) { + var _this = _super.call(this, context, dayGrid.el) || this; + _this.splitter = new ResourceCommonPlugin.VResourceSplitter(); + _this.slicers = {}; + _this.joiner = new ResourceDayGridJoiner(); + _this.dayGrid = dayGrid; + context.calendar.registerInteractiveComponent(_this, { + el: _this.dayGrid.el + }); + return _this; + } + ResourceDayGrid.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.calendar.unregisterInteractiveComponent(this); + }; + ResourceDayGrid.prototype.render = function (props) { + var _this = this; + var dayGrid = this.dayGrid; + var dateProfile = props.dateProfile, resourceDayTable = props.resourceDayTable, nextDayThreshold = props.nextDayThreshold; + var splitProps = this.splitter.splitProps(props); + this.slicers = core.mapHash(splitProps, function (split, resourceId) { + return _this.slicers[resourceId] || new DayGridPlugin.DayGridSlicer(); + }); + var slicedProps = core.mapHash(this.slicers, function (slicer, resourceId) { + return slicer.sliceProps(splitProps[resourceId], dateProfile, nextDayThreshold, dayGrid, resourceDayTable.dayTable); + }); + dayGrid.allowAcrossResources = resourceDayTable.dayTable.colCnt === 1; + dayGrid.receiveProps(__assign({}, this.joiner.joinProps(slicedProps, resourceDayTable), { dateProfile: dateProfile, cells: resourceDayTable.cells, isRigid: props.isRigid })); + }; + ResourceDayGrid.prototype.buildPositionCaches = function () { + this.dayGrid.buildPositionCaches(); + }; + ResourceDayGrid.prototype.queryHit = function (positionLeft, positionTop) { + var rawHit = this.dayGrid.positionToHit(positionLeft, positionTop); + if (rawHit) { + return { + component: this.dayGrid, + dateSpan: { + range: rawHit.dateSpan.range, + allDay: rawHit.dateSpan.allDay, + resourceId: this.props.resourceDayTable.cells[rawHit.row][rawHit.col].resource.id + }, + dayEl: rawHit.dayEl, + rect: { + left: rawHit.relativeRect.left, + right: rawHit.relativeRect.right, + top: rawHit.relativeRect.top, + bottom: rawHit.relativeRect.bottom + }, + layer: 0 + }; + } + }; + return ResourceDayGrid; + }(core.DateComponent)); + var ResourceDayGridJoiner = /** @class */ (function (_super) { + __extends(ResourceDayGridJoiner, _super); + function ResourceDayGridJoiner() { + return _super !== null && _super.apply(this, arguments) || this; + } + ResourceDayGridJoiner.prototype.transformSeg = function (seg, resourceDayTable, resourceI) { + var colRanges = resourceDayTable.computeColRanges(seg.firstCol, seg.lastCol, resourceI); + return colRanges.map(function (colRange) { + return __assign({}, seg, colRange, { isStart: seg.isStart && colRange.isStart, isEnd: seg.isEnd && colRange.isEnd }); + }); + }; + return ResourceDayGridJoiner; + }(ResourceCommonPlugin.VResourceJoiner)); + + var ResourceDayGridView = /** @class */ (function (_super) { + __extends(ResourceDayGridView, _super); + function ResourceDayGridView(context, viewSpec, dateProfileGenerator, parentEl) { + var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this; + _this.flattenResources = core.memoize(ResourceCommonPlugin.flattenResources); + _this.buildResourceDayTable = core.memoize(buildResourceDayTable); + _this.resourceOrderSpecs = core.parseFieldSpecs(_this.opt('resourceOrder')); + if (_this.opt('columnHeader')) { + _this.header = new ResourceCommonPlugin.ResourceDayHeader(_this.context, _this.el.querySelector('.fc-head-container')); + } + _this.resourceDayGrid = new ResourceDayGrid(context, _this.dayGrid); + return _this; + } + ResourceDayGridView.prototype.destroy = function () { + _super.prototype.destroy.call(this); + if (this.header) { + this.header.destroy(); + } + this.resourceDayGrid.destroy(); + }; + ResourceDayGridView.prototype.render = function (props) { + _super.prototype.render.call(this, props); // for flags for updateSize + var resources = this.flattenResources(props.resourceStore, this.resourceOrderSpecs); + var resourceDayTable = this.buildResourceDayTable(this.props.dateProfile, this.dateProfileGenerator, resources, this.opt('datesAboveResources')); + if (this.header) { + this.header.receiveProps({ + resources: resources, + dates: resourceDayTable.dayTable.headerDates, + dateProfile: props.dateProfile, + datesRepDistinctDays: true, + renderIntroHtml: this.renderHeadIntroHtml + }); + } + this.resourceDayGrid.receiveProps({ + dateProfile: props.dateProfile, + resourceDayTable: resourceDayTable, + businessHours: props.businessHours, + eventStore: props.eventStore, + eventUiBases: props.eventUiBases, + dateSelection: props.dateSelection, + eventSelection: props.eventSelection, + eventDrag: props.eventDrag, + eventResize: props.eventResize, + isRigid: this.hasRigidRows(), + nextDayThreshold: this.nextDayThreshold + }); + }; + ResourceDayGridView.needsResourceData = true; // for ResourceViewProps + return ResourceDayGridView; + }(DayGridPlugin.AbstractDayGridView)); + function buildResourceDayTable(dateProfile, dateProfileGenerator, resources, datesAboveResources) { + var dayTable = DayGridPlugin.buildBasicDayTable(dateProfile, dateProfileGenerator); + return datesAboveResources ? + new ResourceCommonPlugin.DayResourceTable(dayTable, resources) : + new ResourceCommonPlugin.ResourceDayTable(dayTable, resources); + } + + var main = core.createPlugin({ + deps: [ResourceCommonPlugin__default, DayGridPlugin__default], + defaultView: 'resourceDayGridDay', + views: { + resourceDayGrid: ResourceDayGridView, + resourceDayGridDay: { + type: 'resourceDayGrid', + duration: { days: 1 } + }, + resourceDayGridWeek: { + type: 'resourceDayGrid', + duration: { weeks: 1 } + }, + resourceDayGridMonth: { + type: 'resourceDayGrid', + duration: { months: 1 }, + // TODO: wish we didn't have to C&P from dayGrid's file + monthMode: true, + fixedWeekCount: true + } + } + }); + + exports.ResourceDayGrid = ResourceDayGrid; + exports.ResourceDayGridView = ResourceDayGridView; + exports.default = main; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-daygrid/main.min.js b/AKPlan/static/AKPlan/fullcalendar/resource-daygrid/main.min.js new file mode 100644 index 00000000..cfc82d0c --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-daygrid/main.min.js @@ -0,0 +1,6 @@ +/*! +FullCalendar Resource Day Grid Plugin v4.3.0 +Docs & License: https://fullcalendar.io/scheduler +(c) 2019 Adam Shaw +*/ +!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("@fullcalendar/core"),require("@fullcalendar/resource-common"),require("@fullcalendar/daygrid")):"function"==typeof define&&define.amd?define(["exports","@fullcalendar/core","@fullcalendar/resource-common","@fullcalendar/daygrid"],r):r((e=e||self).FullCalendarResourceDayGrid={},e.FullCalendar,e.FullCalendarResourceCommon,e.FullCalendarDayGrid)}(this,function(e,r,t,o){"use strict";var i="default"in t?t.default:t,a="default"in o?o.default:o,s=function(e,r){return(s=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,r){e.__proto__=r}||function(e,r){for(var t in r)r.hasOwnProperty(t)&&(e[t]=r[t])})(e,r)};function n(e,r){function t(){this.constructor=e}s(e,r),e.prototype=null===r?Object.create(r):(t.prototype=r.prototype,new t)}var l=function(){return(l=Object.assign||function(e){for(var r,t=1,o=arguments.length;t<o;t++)for(var i in r=arguments[t])Object.prototype.hasOwnProperty.call(r,i)&&(e[i]=r[i]);return e}).apply(this,arguments)},c=function(e){function i(r,o){var i=e.call(this,r,o.el)||this;return i.splitter=new t.VResourceSplitter,i.slicers={},i.joiner=new d,i.dayGrid=o,r.calendar.registerInteractiveComponent(i,{el:i.dayGrid.el}),i}return n(i,e),i.prototype.destroy=function(){e.prototype.destroy.call(this),this.calendar.unregisterInteractiveComponent(this)},i.prototype.render=function(e){var t=this,i=this.dayGrid,a=e.dateProfile,s=e.resourceDayTable,n=e.nextDayThreshold,c=this.splitter.splitProps(e);this.slicers=r.mapHash(c,function(e,r){return t.slicers[r]||new o.DayGridSlicer});var d=r.mapHash(this.slicers,function(e,r){return e.sliceProps(c[r],a,n,i,s.dayTable)});i.allowAcrossResources=1===s.dayTable.colCnt,i.receiveProps(l({},this.joiner.joinProps(d,s),{dateProfile:a,cells:s.cells,isRigid:e.isRigid}))},i.prototype.buildPositionCaches=function(){this.dayGrid.buildPositionCaches()},i.prototype.queryHit=function(e,r){var t=this.dayGrid.positionToHit(e,r);if(t)return{component:this.dayGrid,dateSpan:{range:t.dateSpan.range,allDay:t.dateSpan.allDay,resourceId:this.props.resourceDayTable.cells[t.row][t.col].resource.id},dayEl:t.dayEl,rect:{left:t.relativeRect.left,right:t.relativeRect.right,top:t.relativeRect.top,bottom:t.relativeRect.bottom},layer:0}},i}(r.DateComponent),d=function(e){function r(){return null!==e&&e.apply(this,arguments)||this}return n(r,e),r.prototype.transformSeg=function(e,r,t){return r.computeColRanges(e.firstCol,e.lastCol,t).map(function(r){return l({},e,r,{isStart:e.isStart&&r.isStart,isEnd:e.isEnd&&r.isEnd})})},r}(t.VResourceJoiner),u=function(e){function o(o,i,a,s){var n=e.call(this,o,i,a,s)||this;return n.flattenResources=r.memoize(t.flattenResources),n.buildResourceDayTable=r.memoize(y),n.resourceOrderSpecs=r.parseFieldSpecs(n.opt("resourceOrder")),n.opt("columnHeader")&&(n.header=new t.ResourceDayHeader(n.context,n.el.querySelector(".fc-head-container"))),n.resourceDayGrid=new c(o,n.dayGrid),n}return n(o,e),o.prototype.destroy=function(){e.prototype.destroy.call(this),this.header&&this.header.destroy(),this.resourceDayGrid.destroy()},o.prototype.render=function(r){e.prototype.render.call(this,r);var t=this.flattenResources(r.resourceStore,this.resourceOrderSpecs),o=this.buildResourceDayTable(this.props.dateProfile,this.dateProfileGenerator,t,this.opt("datesAboveResources"));this.header&&this.header.receiveProps({resources:t,dates:o.dayTable.headerDates,dateProfile:r.dateProfile,datesRepDistinctDays:!0,renderIntroHtml:this.renderHeadIntroHtml}),this.resourceDayGrid.receiveProps({dateProfile:r.dateProfile,resourceDayTable:o,businessHours:r.businessHours,eventStore:r.eventStore,eventUiBases:r.eventUiBases,dateSelection:r.dateSelection,eventSelection:r.eventSelection,eventDrag:r.eventDrag,eventResize:r.eventResize,isRigid:this.hasRigidRows(),nextDayThreshold:this.nextDayThreshold})},o.needsResourceData=!0,o}(o.AbstractDayGridView);function y(e,r,i,a){var s=o.buildBasicDayTable(e,r);return a?new t.DayResourceTable(s,i):new t.ResourceDayTable(s,i)}var p=r.createPlugin({deps:[i,a],defaultView:"resourceDayGridDay",views:{resourceDayGrid:u,resourceDayGridDay:{type:"resourceDayGrid",duration:{days:1}},resourceDayGridWeek:{type:"resourceDayGrid",duration:{weeks:1}},resourceDayGridMonth:{type:"resourceDayGrid",duration:{months:1},monthMode:!0,fixedWeekCount:!0}}});e.ResourceDayGrid=c,e.ResourceDayGridView=u,e.default=p,Object.defineProperty(e,"__esModule",{value:!0})}); \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-daygrid/package.json b/AKPlan/static/AKPlan/fullcalendar/resource-daygrid/package.json new file mode 100644 index 00000000..4c9676d7 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-daygrid/package.json @@ -0,0 +1,37 @@ +{ + "name": "@fullcalendar/resource-daygrid", + "version": "4.3.0", + "title": "FullCalendar Resource Day Grid Plugin", + "description": "Displays events in individual columns for days and resources", + "keywords": [ + "calendar", + "event", + "full-sized" + ], + "homepage": "https://fullcalendar.io/scheduler", + "docs": "https://fullcalendar.io/docs/resource-daygrid-view", + "bugs": "https://fullcalendar.io/reporting-bugs", + "repository": { + "type": "git", + "url": "https://github.com/fullcalendar/fullcalendar-scheduler.git", + "homepage": "https://github.com/fullcalendar/fullcalendar-scheduler" + }, + "license": "SEE LICENSE IN LICENSE.md", + "author": { + "name": "Adam Shaw", + "email": "arshaw@arshaw.com", + "url": "http://arshaw.com/" + }, + "copyright": "2019 Adam Shaw", + "dependencies": { + "@fullcalendar/resource-common": "~4.3.0", + "@fullcalendar/daygrid": "~4.3.0" + }, + "peerDependencies": { + "@fullcalendar/core": "~4.3.0" + }, + "main": "main.js", + "module": "main.esm.js", + "unpkg": "main.min.js", + "types": "main.d.ts" +} diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-timegrid/LICENSE.md b/AKPlan/static/AKPlan/fullcalendar/resource-timegrid/LICENSE.md new file mode 100644 index 00000000..52296639 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-timegrid/LICENSE.md @@ -0,0 +1,18 @@ + +For complete licensing information, visit: +http://fullcalendar.io/scheduler/license + +FullCalendar Scheduler is tri-licensed, meaning you must choose +one of three licenses to use. Here is a summary of those licenses: + +- Commercial License + (a paid license, meant for commercial use) + http://fullcalendar.io/scheduler/license-details + +- Creative Commons Non-Commercial No-Derivatives + (meant for trial and non-commercial use) + https://creativecommons.org/licenses/by-nc-nd/4.0/ + +- GPLv3 License + (meant for open-source projects) + http://www.gnu.org/licenses/gpl-3.0.en.html diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-timegrid/README.md b/AKPlan/static/AKPlan/fullcalendar/resource-timegrid/README.md new file mode 100644 index 00000000..f011ad54 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-timegrid/README.md @@ -0,0 +1,8 @@ + +# FullCalendar Resource Time Grid Plugin + +Displays events on a vertical resource view with time slots + +[View the docs »](https://fullcalendar.io/docs/vertical-resource-view) + +This package was created from the [FullCalendar monorepo »](https://github.com/fullcalendar/fullcalendar-scheduler) diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-timegrid/main.d.ts b/AKPlan/static/AKPlan/fullcalendar/resource-timegrid/main.d.ts new file mode 100644 index 00000000..db710853 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-timegrid/main.d.ts @@ -0,0 +1,62 @@ +// Generated by dts-bundle v0.7.3-fork.1 +// Dependencies for this module: +// ../../../../../@fullcalendar/core +// ../../../../../@fullcalendar/timegrid +// ../../../../../@fullcalendar/resource-common +// ../../../../../@fullcalendar/resource-daygrid + +declare module '@fullcalendar/resource-timegrid' { + import ResourceTimeGridView from '@fullcalendar/resource-timegrid/ResourceTimeGridView'; + export { ResourceTimeGridView }; + export { default as ResourceTimeGrid } from '@fullcalendar/resource-timegrid/ResourceTimeGrid'; + const _default: import("@fullcalendar/core").PluginDef; + export default _default; +} + +declare module '@fullcalendar/resource-timegrid/ResourceTimeGridView' { + import { ComponentContext, ViewSpec, DateProfileGenerator } from '@fullcalendar/core'; + import { AbstractTimeGridView } from '@fullcalendar/timegrid'; + import { ResourceDayHeader, ResourceViewProps } from '@fullcalendar/resource-common'; + import { ResourceDayGrid } from '@fullcalendar/resource-daygrid'; + import ResourceTimeGrid from '@fullcalendar/resource-timegrid/ResourceTimeGrid'; + export { ResourceTimeGridView as default, ResourceTimeGridView }; + class ResourceTimeGridView extends AbstractTimeGridView { + static needsResourceData: boolean; + props: ResourceViewProps; + header: ResourceDayHeader; + resourceTimeGrid: ResourceTimeGrid; + resourceDayGrid: ResourceDayGrid; + constructor(context: ComponentContext, viewSpec: ViewSpec, dateProfileGenerator: DateProfileGenerator, parentEl: HTMLElement); + destroy(): void; + render(props: ResourceViewProps): void; + renderNowIndicator(date: any): void; + } +} + +declare module '@fullcalendar/resource-timegrid/ResourceTimeGrid' { + import { DateSpan, DateComponent, DateProfile, EventStore, EventUiHash, EventInteractionState, ComponentContext, DateMarker, Hit } from '@fullcalendar/core'; + import { TimeGrid } from '@fullcalendar/timegrid'; + import { AbstractResourceDayTable } from '@fullcalendar/resource-common'; + export interface ResourceTimeGridProps { + dateProfile: DateProfile | null; + resourceDayTable: AbstractResourceDayTable; + businessHours: EventStore; + eventStore: EventStore; + eventUiBases: EventUiHash; + dateSelection: DateSpan | null; + eventSelection: string; + eventDrag: EventInteractionState | null; + eventResize: EventInteractionState | null; + } + export { ResourceTimeGrid as default, ResourceTimeGrid }; + class ResourceTimeGrid extends DateComponent<ResourceTimeGridProps> { + timeGrid: TimeGrid; + constructor(context: ComponentContext, timeGrid: TimeGrid); + destroy(): void; + render(props: ResourceTimeGridProps): void; + renderNowIndicator(date: DateMarker): void; + buildPositionCaches(): void; + queryHit(positionLeft: number, positionTop: number): Hit; + } +} + diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-timegrid/main.esm.js b/AKPlan/static/AKPlan/fullcalendar/resource-timegrid/main.esm.js new file mode 100644 index 00000000..0e82575c --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-timegrid/main.esm.js @@ -0,0 +1,211 @@ +/*! +FullCalendar Resource Time Grid Plugin v4.3.0 +Docs & License: https://fullcalendar.io/scheduler +(c) 2019 Adam Shaw +*/ + +import { memoize, mapHash, DateComponent, parseFieldSpecs, createPlugin } from '@fullcalendar/core'; +import ResourceCommonPlugin, { VResourceSplitter, VResourceJoiner, flattenResources, ResourceDayHeader, DayResourceTable, ResourceDayTable } from '@fullcalendar/resource-common'; +import TimeGridPlugin, { buildDayRanges, TimeGridSlicer, AbstractTimeGridView, buildDayTable } from '@fullcalendar/timegrid'; +import { ResourceDayGrid } from '@fullcalendar/resource-daygrid'; + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} + +var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; + +var ResourceTimeGrid = /** @class */ (function (_super) { + __extends(ResourceTimeGrid, _super); + function ResourceTimeGrid(context, timeGrid) { + var _this = _super.call(this, context, timeGrid.el) || this; + _this.buildDayRanges = memoize(buildDayRanges); + _this.splitter = new VResourceSplitter(); + _this.slicers = {}; + _this.joiner = new ResourceTimeGridJoiner(); + _this.timeGrid = timeGrid; + context.calendar.registerInteractiveComponent(_this, { + el: _this.timeGrid.el + }); + return _this; + } + ResourceTimeGrid.prototype.destroy = function () { + this.calendar.unregisterInteractiveComponent(this); + }; + ResourceTimeGrid.prototype.render = function (props) { + var _this = this; + var timeGrid = this.timeGrid; + var dateProfile = props.dateProfile, resourceDayTable = props.resourceDayTable; + var dayRanges = this.dayRanges = this.buildDayRanges(resourceDayTable.dayTable, dateProfile, this.dateEnv); + var splitProps = this.splitter.splitProps(props); + this.slicers = mapHash(splitProps, function (split, resourceId) { + return _this.slicers[resourceId] || new TimeGridSlicer(); + }); + var slicedProps = mapHash(this.slicers, function (slicer, resourceId) { + return slicer.sliceProps(splitProps[resourceId], dateProfile, null, timeGrid, dayRanges); + }); + timeGrid.allowAcrossResources = dayRanges.length === 1; + timeGrid.receiveProps(__assign({}, this.joiner.joinProps(slicedProps, resourceDayTable), { dateProfile: dateProfile, cells: resourceDayTable.cells[0] })); + }; + ResourceTimeGrid.prototype.renderNowIndicator = function (date) { + var timeGrid = this.timeGrid; + var resourceDayTable = this.props.resourceDayTable; + var nonResourceSegs = this.slicers[''].sliceNowDate(date, timeGrid, this.dayRanges); + var segs = this.joiner.expandSegs(resourceDayTable, nonResourceSegs); + timeGrid.renderNowIndicator(segs, date); + }; + ResourceTimeGrid.prototype.buildPositionCaches = function () { + this.timeGrid.buildPositionCaches(); + }; + ResourceTimeGrid.prototype.queryHit = function (positionLeft, positionTop) { + var rawHit = this.timeGrid.positionToHit(positionLeft, positionTop); + if (rawHit) { + return { + component: this.timeGrid, + dateSpan: { + range: rawHit.dateSpan.range, + allDay: rawHit.dateSpan.allDay, + resourceId: this.props.resourceDayTable.cells[0][rawHit.col].resource.id + }, + dayEl: rawHit.dayEl, + rect: { + left: rawHit.relativeRect.left, + right: rawHit.relativeRect.right, + top: rawHit.relativeRect.top, + bottom: rawHit.relativeRect.bottom + }, + layer: 0 + }; + } + }; + return ResourceTimeGrid; +}(DateComponent)); +var ResourceTimeGridJoiner = /** @class */ (function (_super) { + __extends(ResourceTimeGridJoiner, _super); + function ResourceTimeGridJoiner() { + return _super !== null && _super.apply(this, arguments) || this; + } + ResourceTimeGridJoiner.prototype.transformSeg = function (seg, resourceDayTable, resourceI) { + return [ + __assign({}, seg, { col: resourceDayTable.computeCol(seg.col, resourceI) }) + ]; + }; + return ResourceTimeGridJoiner; +}(VResourceJoiner)); + +var ResourceTimeGridView = /** @class */ (function (_super) { + __extends(ResourceTimeGridView, _super); + function ResourceTimeGridView(context, viewSpec, dateProfileGenerator, parentEl) { + var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this; + _this.flattenResources = memoize(flattenResources); + _this.buildResourceDayTable = memoize(buildResourceDayTable); + _this.resourceOrderSpecs = parseFieldSpecs(_this.opt('resourceOrder')); + if (_this.opt('columnHeader')) { + _this.header = new ResourceDayHeader(_this.context, _this.el.querySelector('.fc-head-container')); + } + _this.resourceTimeGrid = new ResourceTimeGrid(context, _this.timeGrid); + if (_this.dayGrid) { + _this.resourceDayGrid = new ResourceDayGrid(context, _this.dayGrid); + } + return _this; + } + ResourceTimeGridView.prototype.destroy = function () { + _super.prototype.destroy.call(this); + if (this.header) { + this.header.destroy(); + } + this.resourceTimeGrid.destroy(); + if (this.resourceDayGrid) { + this.resourceDayGrid.destroy(); + } + }; + ResourceTimeGridView.prototype.render = function (props) { + _super.prototype.render.call(this, props); // for flags for updateSize + var splitProps = this.splitter.splitProps(props); + var resources = this.flattenResources(props.resourceStore, this.resourceOrderSpecs); + var resourceDayTable = this.buildResourceDayTable(this.props.dateProfile, this.dateProfileGenerator, resources, this.opt('datesAboveResources')); + if (this.header) { + this.header.receiveProps({ + resources: resources, + dates: resourceDayTable.dayTable.headerDates, + dateProfile: props.dateProfile, + datesRepDistinctDays: true, + renderIntroHtml: this.renderHeadIntroHtml + }); + } + this.resourceTimeGrid.receiveProps(__assign({}, splitProps['timed'], { dateProfile: props.dateProfile, resourceDayTable: resourceDayTable })); + if (this.resourceDayGrid) { + this.resourceDayGrid.receiveProps(__assign({}, splitProps['allDay'], { dateProfile: props.dateProfile, resourceDayTable: resourceDayTable, isRigid: false, nextDayThreshold: this.nextDayThreshold })); + } + }; + ResourceTimeGridView.prototype.renderNowIndicator = function (date) { + this.resourceTimeGrid.renderNowIndicator(date); + }; + ResourceTimeGridView.needsResourceData = true; // for ResourceViewProps + return ResourceTimeGridView; +}(AbstractTimeGridView)); +function buildResourceDayTable(dateProfile, dateProfileGenerator, resources, datesAboveResources) { + var dayTable = buildDayTable(dateProfile, dateProfileGenerator); + return datesAboveResources ? + new DayResourceTable(dayTable, resources) : + new ResourceDayTable(dayTable, resources); +} + +var main = createPlugin({ + deps: [ResourceCommonPlugin, TimeGridPlugin], + defaultView: 'resourceTimeGridDay', + views: { + resourceTimeGrid: { + class: ResourceTimeGridView, + // TODO: wish we didn't have to C&P from timeGrid's file + allDaySlot: true, + slotDuration: '00:30:00', + slotEventOverlap: true // a bad name. confused with overlap/constraint system + }, + resourceTimeGridDay: { + type: 'resourceTimeGrid', + duration: { days: 1 } + }, + resourceTimeGridWeek: { + type: 'resourceTimeGrid', + duration: { weeks: 1 } + } + } +}); + +export default main; +export { ResourceTimeGrid, ResourceTimeGridView }; diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-timegrid/main.js b/AKPlan/static/AKPlan/fullcalendar/resource-timegrid/main.js new file mode 100644 index 00000000..c00b37ea --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-timegrid/main.js @@ -0,0 +1,220 @@ +/*! +FullCalendar Resource Time Grid Plugin v4.3.0 +Docs & License: https://fullcalendar.io/scheduler +(c) 2019 Adam Shaw +*/ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core'), require('@fullcalendar/resource-common'), require('@fullcalendar/timegrid'), require('@fullcalendar/resource-daygrid')) : + typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core', '@fullcalendar/resource-common', '@fullcalendar/timegrid', '@fullcalendar/resource-daygrid'], factory) : + (global = global || self, factory(global.FullCalendarResourceTimeGrid = {}, global.FullCalendar, global.FullCalendarResourceCommon, global.FullCalendarTimeGrid, global.FullCalendarResourceDayGrid)); +}(this, function (exports, core, ResourceCommonPlugin, TimeGridPlugin, resourceDaygrid) { 'use strict'; + + var ResourceCommonPlugin__default = 'default' in ResourceCommonPlugin ? ResourceCommonPlugin['default'] : ResourceCommonPlugin; + var TimeGridPlugin__default = 'default' in TimeGridPlugin ? TimeGridPlugin['default'] : TimeGridPlugin; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + var ResourceTimeGrid = /** @class */ (function (_super) { + __extends(ResourceTimeGrid, _super); + function ResourceTimeGrid(context, timeGrid) { + var _this = _super.call(this, context, timeGrid.el) || this; + _this.buildDayRanges = core.memoize(TimeGridPlugin.buildDayRanges); + _this.splitter = new ResourceCommonPlugin.VResourceSplitter(); + _this.slicers = {}; + _this.joiner = new ResourceTimeGridJoiner(); + _this.timeGrid = timeGrid; + context.calendar.registerInteractiveComponent(_this, { + el: _this.timeGrid.el + }); + return _this; + } + ResourceTimeGrid.prototype.destroy = function () { + this.calendar.unregisterInteractiveComponent(this); + }; + ResourceTimeGrid.prototype.render = function (props) { + var _this = this; + var timeGrid = this.timeGrid; + var dateProfile = props.dateProfile, resourceDayTable = props.resourceDayTable; + var dayRanges = this.dayRanges = this.buildDayRanges(resourceDayTable.dayTable, dateProfile, this.dateEnv); + var splitProps = this.splitter.splitProps(props); + this.slicers = core.mapHash(splitProps, function (split, resourceId) { + return _this.slicers[resourceId] || new TimeGridPlugin.TimeGridSlicer(); + }); + var slicedProps = core.mapHash(this.slicers, function (slicer, resourceId) { + return slicer.sliceProps(splitProps[resourceId], dateProfile, null, timeGrid, dayRanges); + }); + timeGrid.allowAcrossResources = dayRanges.length === 1; + timeGrid.receiveProps(__assign({}, this.joiner.joinProps(slicedProps, resourceDayTable), { dateProfile: dateProfile, cells: resourceDayTable.cells[0] })); + }; + ResourceTimeGrid.prototype.renderNowIndicator = function (date) { + var timeGrid = this.timeGrid; + var resourceDayTable = this.props.resourceDayTable; + var nonResourceSegs = this.slicers[''].sliceNowDate(date, timeGrid, this.dayRanges); + var segs = this.joiner.expandSegs(resourceDayTable, nonResourceSegs); + timeGrid.renderNowIndicator(segs, date); + }; + ResourceTimeGrid.prototype.buildPositionCaches = function () { + this.timeGrid.buildPositionCaches(); + }; + ResourceTimeGrid.prototype.queryHit = function (positionLeft, positionTop) { + var rawHit = this.timeGrid.positionToHit(positionLeft, positionTop); + if (rawHit) { + return { + component: this.timeGrid, + dateSpan: { + range: rawHit.dateSpan.range, + allDay: rawHit.dateSpan.allDay, + resourceId: this.props.resourceDayTable.cells[0][rawHit.col].resource.id + }, + dayEl: rawHit.dayEl, + rect: { + left: rawHit.relativeRect.left, + right: rawHit.relativeRect.right, + top: rawHit.relativeRect.top, + bottom: rawHit.relativeRect.bottom + }, + layer: 0 + }; + } + }; + return ResourceTimeGrid; + }(core.DateComponent)); + var ResourceTimeGridJoiner = /** @class */ (function (_super) { + __extends(ResourceTimeGridJoiner, _super); + function ResourceTimeGridJoiner() { + return _super !== null && _super.apply(this, arguments) || this; + } + ResourceTimeGridJoiner.prototype.transformSeg = function (seg, resourceDayTable, resourceI) { + return [ + __assign({}, seg, { col: resourceDayTable.computeCol(seg.col, resourceI) }) + ]; + }; + return ResourceTimeGridJoiner; + }(ResourceCommonPlugin.VResourceJoiner)); + + var ResourceTimeGridView = /** @class */ (function (_super) { + __extends(ResourceTimeGridView, _super); + function ResourceTimeGridView(context, viewSpec, dateProfileGenerator, parentEl) { + var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this; + _this.flattenResources = core.memoize(ResourceCommonPlugin.flattenResources); + _this.buildResourceDayTable = core.memoize(buildResourceDayTable); + _this.resourceOrderSpecs = core.parseFieldSpecs(_this.opt('resourceOrder')); + if (_this.opt('columnHeader')) { + _this.header = new ResourceCommonPlugin.ResourceDayHeader(_this.context, _this.el.querySelector('.fc-head-container')); + } + _this.resourceTimeGrid = new ResourceTimeGrid(context, _this.timeGrid); + if (_this.dayGrid) { + _this.resourceDayGrid = new resourceDaygrid.ResourceDayGrid(context, _this.dayGrid); + } + return _this; + } + ResourceTimeGridView.prototype.destroy = function () { + _super.prototype.destroy.call(this); + if (this.header) { + this.header.destroy(); + } + this.resourceTimeGrid.destroy(); + if (this.resourceDayGrid) { + this.resourceDayGrid.destroy(); + } + }; + ResourceTimeGridView.prototype.render = function (props) { + _super.prototype.render.call(this, props); // for flags for updateSize + var splitProps = this.splitter.splitProps(props); + var resources = this.flattenResources(props.resourceStore, this.resourceOrderSpecs); + var resourceDayTable = this.buildResourceDayTable(this.props.dateProfile, this.dateProfileGenerator, resources, this.opt('datesAboveResources')); + if (this.header) { + this.header.receiveProps({ + resources: resources, + dates: resourceDayTable.dayTable.headerDates, + dateProfile: props.dateProfile, + datesRepDistinctDays: true, + renderIntroHtml: this.renderHeadIntroHtml + }); + } + this.resourceTimeGrid.receiveProps(__assign({}, splitProps['timed'], { dateProfile: props.dateProfile, resourceDayTable: resourceDayTable })); + if (this.resourceDayGrid) { + this.resourceDayGrid.receiveProps(__assign({}, splitProps['allDay'], { dateProfile: props.dateProfile, resourceDayTable: resourceDayTable, isRigid: false, nextDayThreshold: this.nextDayThreshold })); + } + }; + ResourceTimeGridView.prototype.renderNowIndicator = function (date) { + this.resourceTimeGrid.renderNowIndicator(date); + }; + ResourceTimeGridView.needsResourceData = true; // for ResourceViewProps + return ResourceTimeGridView; + }(TimeGridPlugin.AbstractTimeGridView)); + function buildResourceDayTable(dateProfile, dateProfileGenerator, resources, datesAboveResources) { + var dayTable = TimeGridPlugin.buildDayTable(dateProfile, dateProfileGenerator); + return datesAboveResources ? + new ResourceCommonPlugin.DayResourceTable(dayTable, resources) : + new ResourceCommonPlugin.ResourceDayTable(dayTable, resources); + } + + var main = core.createPlugin({ + deps: [ResourceCommonPlugin__default, TimeGridPlugin__default], + defaultView: 'resourceTimeGridDay', + views: { + resourceTimeGrid: { + class: ResourceTimeGridView, + // TODO: wish we didn't have to C&P from timeGrid's file + allDaySlot: true, + slotDuration: '00:30:00', + slotEventOverlap: true // a bad name. confused with overlap/constraint system + }, + resourceTimeGridDay: { + type: 'resourceTimeGrid', + duration: { days: 1 } + }, + resourceTimeGridWeek: { + type: 'resourceTimeGrid', + duration: { weeks: 1 } + } + } + }); + + exports.ResourceTimeGrid = ResourceTimeGrid; + exports.ResourceTimeGridView = ResourceTimeGridView; + exports.default = main; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-timegrid/main.min.js b/AKPlan/static/AKPlan/fullcalendar/resource-timegrid/main.min.js new file mode 100644 index 00000000..27621fea --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-timegrid/main.min.js @@ -0,0 +1,6 @@ +/*! +FullCalendar Resource Time Grid Plugin v4.3.0 +Docs & License: https://fullcalendar.io/scheduler +(c) 2019 Adam Shaw +*/ +!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("@fullcalendar/core"),require("@fullcalendar/resource-common"),require("@fullcalendar/timegrid"),require("@fullcalendar/resource-daygrid")):"function"==typeof define&&define.amd?define(["exports","@fullcalendar/core","@fullcalendar/resource-common","@fullcalendar/timegrid","@fullcalendar/resource-daygrid"],r):r((e=e||self).FullCalendarResourceTimeGrid={},e.FullCalendar,e.FullCalendarResourceCommon,e.FullCalendarTimeGrid,e.FullCalendarResourceDayGrid)}(this,function(e,r,t,i,o){"use strict";var s="default"in t?t.default:t,a="default"in i?i.default:i,n=function(e,r){return(n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,r){e.__proto__=r}||function(e,r){for(var t in r)r.hasOwnProperty(t)&&(e[t]=r[t])})(e,r)};function l(e,r){function t(){this.constructor=e}n(e,r),e.prototype=null===r?Object.create(r):(t.prototype=r.prototype,new t)}var c=function(){return(c=Object.assign||function(e){for(var r,t=1,i=arguments.length;t<i;t++)for(var o in r=arguments[t])Object.prototype.hasOwnProperty.call(r,o)&&(e[o]=r[o]);return e}).apply(this,arguments)},d=function(e){function o(o,s){var a=e.call(this,o,s.el)||this;return a.buildDayRanges=r.memoize(i.buildDayRanges),a.splitter=new t.VResourceSplitter,a.slicers={},a.joiner=new u,a.timeGrid=s,o.calendar.registerInteractiveComponent(a,{el:a.timeGrid.el}),a}return l(o,e),o.prototype.destroy=function(){this.calendar.unregisterInteractiveComponent(this)},o.prototype.render=function(e){var t=this,o=this.timeGrid,s=e.dateProfile,a=e.resourceDayTable,n=this.dayRanges=this.buildDayRanges(a.dayTable,s,this.dateEnv),l=this.splitter.splitProps(e);this.slicers=r.mapHash(l,function(e,r){return t.slicers[r]||new i.TimeGridSlicer});var d=r.mapHash(this.slicers,function(e,r){return e.sliceProps(l[r],s,null,o,n)});o.allowAcrossResources=1===n.length,o.receiveProps(c({},this.joiner.joinProps(d,a),{dateProfile:s,cells:a.cells[0]}))},o.prototype.renderNowIndicator=function(e){var r=this.timeGrid,t=this.props.resourceDayTable,i=this.slicers[""].sliceNowDate(e,r,this.dayRanges),o=this.joiner.expandSegs(t,i);r.renderNowIndicator(o,e)},o.prototype.buildPositionCaches=function(){this.timeGrid.buildPositionCaches()},o.prototype.queryHit=function(e,r){var t=this.timeGrid.positionToHit(e,r);if(t)return{component:this.timeGrid,dateSpan:{range:t.dateSpan.range,allDay:t.dateSpan.allDay,resourceId:this.props.resourceDayTable.cells[0][t.col].resource.id},dayEl:t.dayEl,rect:{left:t.relativeRect.left,right:t.relativeRect.right,top:t.relativeRect.top,bottom:t.relativeRect.bottom},layer:0}},o}(r.DateComponent),u=function(e){function r(){return null!==e&&e.apply(this,arguments)||this}return l(r,e),r.prototype.transformSeg=function(e,r,t){return[c({},e,{col:r.computeCol(e.col,t)})]},r}(t.VResourceJoiner),p=function(e){function i(i,s,a,n){var l=e.call(this,i,s,a,n)||this;return l.flattenResources=r.memoize(t.flattenResources),l.buildResourceDayTable=r.memoize(y),l.resourceOrderSpecs=r.parseFieldSpecs(l.opt("resourceOrder")),l.opt("columnHeader")&&(l.header=new t.ResourceDayHeader(l.context,l.el.querySelector(".fc-head-container"))),l.resourceTimeGrid=new d(i,l.timeGrid),l.dayGrid&&(l.resourceDayGrid=new o.ResourceDayGrid(i,l.dayGrid)),l}return l(i,e),i.prototype.destroy=function(){e.prototype.destroy.call(this),this.header&&this.header.destroy(),this.resourceTimeGrid.destroy(),this.resourceDayGrid&&this.resourceDayGrid.destroy()},i.prototype.render=function(r){e.prototype.render.call(this,r);var t=this.splitter.splitProps(r),i=this.flattenResources(r.resourceStore,this.resourceOrderSpecs),o=this.buildResourceDayTable(this.props.dateProfile,this.dateProfileGenerator,i,this.opt("datesAboveResources"));this.header&&this.header.receiveProps({resources:i,dates:o.dayTable.headerDates,dateProfile:r.dateProfile,datesRepDistinctDays:!0,renderIntroHtml:this.renderHeadIntroHtml}),this.resourceTimeGrid.receiveProps(c({},t.timed,{dateProfile:r.dateProfile,resourceDayTable:o})),this.resourceDayGrid&&this.resourceDayGrid.receiveProps(c({},t.allDay,{dateProfile:r.dateProfile,resourceDayTable:o,isRigid:!1,nextDayThreshold:this.nextDayThreshold}))},i.prototype.renderNowIndicator=function(e){this.resourceTimeGrid.renderNowIndicator(e)},i.needsResourceData=!0,i}(i.AbstractTimeGridView);function y(e,r,o,s){var a=i.buildDayTable(e,r);return s?new t.DayResourceTable(a,o):new t.ResourceDayTable(a,o)}var f=r.createPlugin({deps:[s,a],defaultView:"resourceTimeGridDay",views:{resourceTimeGrid:{class:p,allDaySlot:!0,slotDuration:"00:30:00",slotEventOverlap:!0},resourceTimeGridDay:{type:"resourceTimeGrid",duration:{days:1}},resourceTimeGridWeek:{type:"resourceTimeGrid",duration:{weeks:1}}}});e.ResourceTimeGrid=d,e.ResourceTimeGridView=p,e.default=f,Object.defineProperty(e,"__esModule",{value:!0})}); \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-timegrid/package.json b/AKPlan/static/AKPlan/fullcalendar/resource-timegrid/package.json new file mode 100644 index 00000000..d8f7b524 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-timegrid/package.json @@ -0,0 +1,38 @@ +{ + "name": "@fullcalendar/resource-timegrid", + "version": "4.3.0", + "title": "FullCalendar Resource Time Grid Plugin", + "description": "Displays events on a vertical resource view with time slots", + "keywords": [ + "calendar", + "event", + "full-sized" + ], + "homepage": "https://fullcalendar.io/scheduler", + "docs": "https://fullcalendar.io/docs/vertical-resource-view", + "bugs": "https://fullcalendar.io/reporting-bugs", + "repository": { + "type": "git", + "url": "https://github.com/fullcalendar/fullcalendar-scheduler.git", + "homepage": "https://github.com/fullcalendar/fullcalendar-scheduler" + }, + "license": "SEE LICENSE IN LICENSE.md", + "author": { + "name": "Adam Shaw", + "email": "arshaw@arshaw.com", + "url": "http://arshaw.com/" + }, + "copyright": "2019 Adam Shaw", + "dependencies": { + "@fullcalendar/resource-common": "~4.3.0", + "@fullcalendar/timegrid": "~4.3.0", + "@fullcalendar/resource-daygrid": "~4.3.0" + }, + "peerDependencies": { + "@fullcalendar/core": "~4.3.0" + }, + "main": "main.js", + "module": "main.esm.js", + "unpkg": "main.min.js", + "types": "main.d.ts" +} diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-timeline/LICENSE.md b/AKPlan/static/AKPlan/fullcalendar/resource-timeline/LICENSE.md new file mode 100644 index 00000000..52296639 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-timeline/LICENSE.md @@ -0,0 +1,18 @@ + +For complete licensing information, visit: +http://fullcalendar.io/scheduler/license + +FullCalendar Scheduler is tri-licensed, meaning you must choose +one of three licenses to use. Here is a summary of those licenses: + +- Commercial License + (a paid license, meant for commercial use) + http://fullcalendar.io/scheduler/license-details + +- Creative Commons Non-Commercial No-Derivatives + (meant for trial and non-commercial use) + https://creativecommons.org/licenses/by-nc-nd/4.0/ + +- GPLv3 License + (meant for open-source projects) + http://www.gnu.org/licenses/gpl-3.0.en.html diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-timeline/README.md b/AKPlan/static/AKPlan/fullcalendar/resource-timeline/README.md new file mode 100644 index 00000000..4261c892 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-timeline/README.md @@ -0,0 +1,8 @@ + +# FullCalendar Resource Timeline Plugin + +Display events and resources on a horizontal time axis + +[View the docs »](https://fullcalendar.io/docs/timeline-view) + +This package was created from the [FullCalendar monorepo »](https://github.com/fullcalendar/fullcalendar-scheduler) diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.css b/AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.css new file mode 100644 index 00000000..584fe330 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.css @@ -0,0 +1,125 @@ +/* Divider between resources and time area +--------------------------------------------------------------------------------------------------*/ +.fc-timeline .fc-divider { + width: 3px; + border-style: double; + /* overcome neighboring borders */ +} + +.fc-timeline .fc-head > tr > .fc-divider { + border-bottom: 0; +} + +.fc-timeline .fc-body > tr > .fc-divider { + border-top: 0; +} + +/* Resource Area +--------------------------------------------------------------------------------------------------*/ +.fc-resource-area { + width: 30%; +} + +.fc-resource-area col { + width: 40%; + min-width: 70px; + /* will be read by JS */ +} + +.fc-resource-area col.fc-main-col { + width: 60%; + /* make the first column in a nested setup bigger */ +} + +.fc-flat .fc-expander-space { + /* fc-flat is opposite of fc-nested */ + display: none; +} + +.fc-ltr .fc-resource-area tr > * { + text-align: left; +} + +.fc-rtl .fc-resource-area tr > * { + text-align: right; +} + +.fc-resource-area .fc-cell-content { + padding-left: 4px; + padding-right: 4px; +} + +/* head */ +.fc-resource-area .fc-super th { + text-align: center; +} + +.fc-resource-area th > div { + position: relative; +} + +.fc-resource-area th .fc-cell-content { + position: relative; + z-index: 1; +} + +.fc-resource-area th .fc-col-resizer { + position: absolute; + z-index: 2; + top: 0; + bottom: 0; + width: 5px; +} + +.fc-timeline .fc-col-resizer { + cursor: col-resize; +} + +.fc-ltr .fc-resource-area th .fc-col-resizer { + right: -3px; +} + +.fc-rtl .fc-resource-area th .fc-col-resizer { + left: -3px; +} + +/* body */ +.fc-body .fc-resource-area .fc-cell-content { + /* might BE the cell */ + padding-top: 8px; + padding-bottom: 8px; +} + +.fc-no-overlap .fc-body .fc-resource-area .fc-cell-content { + /* might BE the cell */ + padding-top: 6px; + padding-bottom: 6px; +} + +.fc-resource-area .fc-icon { + /* the expander and spacers before the expander */ + display: inline-block; + width: 1em; + /* ensure constant width, esp for empty icons */ + text-align: center; +} + +.fc-resource-area .fc-expander { + cursor: pointer; + opacity: 0.65; +} + +/* body resource rows */ +.fc-time-area .fc-rows { + position: relative; + z-index: 3; +} + +.fc-time-area .fc-rows td > div { + position: relative; +} + +.fc-time-area .fc-rows .fc-bgevent-container, +.fc-time-area .fc-rows .fc-highlight-container { + z-index: 1; +} diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.d.ts b/AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.d.ts new file mode 100644 index 00000000..289f5ece --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.d.ts @@ -0,0 +1,237 @@ +// Generated by dts-bundle v0.7.3-fork.1 +// Dependencies for this module: +// ../../../../../@fullcalendar/core +// ../../../../../@fullcalendar/timeline +// ../../../../../@fullcalendar/resource-common + +declare module '@fullcalendar/resource-timeline' { + import ResourceTimelineView from '@fullcalendar/resource-timeline/ResourceTimelineView'; + export { ResourceTimelineView }; + const _default: import("@fullcalendar/core").PluginDef; + export default _default; +} + +declare module '@fullcalendar/resource-timeline/ResourceTimelineView' { + import { ElementDragging, SplittableProps, PositionCache, Hit, View, ViewSpec, ComponentContext, DateProfileGenerator, DateProfile, Duration } from '@fullcalendar/core'; + import { ScrollJoiner, TimelineLane, StickyScroller, TimeAxis } from '@fullcalendar/timeline'; + import { GroupNode, ResourceNode, ResourceViewProps } from '@fullcalendar/resource-common'; + import GroupRow from '@fullcalendar/resource-timeline/GroupRow'; + import ResourceRow from '@fullcalendar/resource-timeline/ResourceRow'; + import Spreadsheet from '@fullcalendar/resource-timeline/Spreadsheet'; + export { ResourceTimelineView as default, ResourceTimelineView }; + class ResourceTimelineView extends View { + static needsResourceData: boolean; + props: ResourceViewProps; + spreadsheet: Spreadsheet; + timeAxis: TimeAxis; + lane: TimelineLane; + bodyScrollJoiner: ScrollJoiner; + spreadsheetBodyStickyScroller: StickyScroller; + isStickyScrollDirty: boolean; + timeAxisTbody: HTMLElement; + miscHeight: number; + rowNodes: (GroupNode | ResourceNode)[]; + rowComponents: (GroupRow | ResourceRow)[]; + rowComponentsById: { + [id: string]: (GroupRow | ResourceRow); + }; + resourceAreaHeadEl: HTMLElement; + resourceAreaWidth?: number; + resourceAreaWidthDraggings: ElementDragging[]; + superHeaderText: any; + isVGrouping: any; + isHGrouping: any; + groupSpecs: any; + colSpecs: any; + orderSpecs: any; + rowPositions: PositionCache; + constructor(context: ComponentContext, viewSpec: ViewSpec, dateProfileGenerator: DateProfileGenerator, parentEl: HTMLElement); + renderSkeletonHtml(): string; + render(props: ResourceViewProps): void; + updateHasNesting(isNesting: boolean): void; + diffRows(newNodes: any): void; + addRow(index: any, rowNode: any): void; + removeRows(startIndex: any, len: any, oldRowNodes: any): void; + buildChildComponent(node: (GroupNode | ResourceNode), spreadsheetTbody: HTMLElement, spreadsheetNext: HTMLElement, timeAxisTbody: HTMLElement, timeAxisNext: HTMLElement): GroupRow | ResourceRow; + renderRows(dateProfile: DateProfile, fallbackBusinessHours: any, splitProps: { + [resourceId: string]: SplittableProps; + }): void; + updateSize(isResize: any, viewHeight: any, isAuto: any): void; + syncHeadHeights(): void; + updateRowSizes(isResize: boolean): number; + destroy(): void; + getNowIndicatorUnit(dateProfile: DateProfile): string; + renderNowIndicator(date: any): void; + unrenderNowIndicator(): void; + queryScroll(): any; + applyScroll(scroll: any, isResize: any): void; + computeDateScroll(duration: Duration): { + left: number; + }; + queryDateScroll(): { + left: number; + }; + applyDateScroll(scroll: any): void; + queryResourceScroll(): any; + applyResourceScroll(scroll: any): void; + buildPositionCaches(): void; + queryHit(positionLeft: number, positionTop: number): Hit; + setResourceAreaWidth(widthVal: any): void; + initResourceAreaWidthDragging(): void; + } +} + +declare module '@fullcalendar/resource-timeline/GroupRow' { + import { Group } from '@fullcalendar/resource-common'; + import Row from '@fullcalendar/resource-timeline/Row'; + export interface GroupRowProps { + spreadsheetColCnt: number; + id: string; + isExpanded: boolean; + group: Group; + } + export { GroupRow as default, GroupRow }; + class GroupRow extends Row<GroupRowProps> { + spreadsheetHeightEl: HTMLElement; + timeAxisHeightEl: HTMLElement; + expanderIconEl: HTMLElement; + render(props: GroupRowProps): void; + destroy(): void; + renderCells(group: Group, spreadsheetColCnt: number): void; + unrenderCells(): void; + renderSpreadsheetContent(group: Group): HTMLElement; + renderCellText(group: Group): any; + getHeightEls(): HTMLElement[]; + updateExpanderIcon(isExpanded: boolean): void; + onExpanderClick: (ev: UIEvent) => void; + } +} + +declare module '@fullcalendar/resource-timeline/ResourceRow' { + import { Duration, ComponentContext, EventInteractionState, DateSpan, EventUiHash, EventStore, DateProfile } from '@fullcalendar/core'; + import { TimelineLane, TimeAxis } from '@fullcalendar/timeline'; + import Row from '@fullcalendar/resource-timeline/Row'; + import SpreadsheetRow from '@fullcalendar/resource-timeline/SpreadsheetRow'; + import { Resource } from '@fullcalendar/resource-common'; + export interface ResourceRowProps { + dateProfile: DateProfile; + nextDayThreshold: Duration; + businessHours: EventStore | null; + eventStore: EventStore | null; + eventUiBases: EventUiHash; + dateSelection: DateSpan | null; + eventSelection: string; + eventDrag: EventInteractionState | null; + eventResize: EventInteractionState | null; + colSpecs: any; + id: string; + rowSpans: number[]; + depth: number; + isExpanded: boolean; + hasChildren: boolean; + resource: Resource; + } + export { ResourceRow as default, ResourceRow }; + class ResourceRow extends Row<ResourceRowProps> { + innerContainerEl: HTMLElement; + spreadsheetRow: SpreadsheetRow; + lane: TimelineLane; + constructor(context: ComponentContext, a: any, b: any, c: any, d: any, timeAxis: TimeAxis); + destroy(): void; + render(props: ResourceRowProps): void; + updateSize(isResize: boolean): void; + getHeightEls(): HTMLElement[]; + } +} + +declare module '@fullcalendar/resource-timeline/Spreadsheet' { + import { Component, ComponentContext } from '@fullcalendar/core'; + import { HeaderBodyLayout } from '@fullcalendar/timeline'; + import SpreadsheetHeader from '@fullcalendar/resource-timeline/SpreadsheetHeader'; + export interface SpreadsheetProps { + superHeaderText: string; + colSpecs: any; + } + export { Spreadsheet as default, Spreadsheet }; + class Spreadsheet extends Component<SpreadsheetProps> { + header: SpreadsheetHeader; + layout: HeaderBodyLayout; + bodyContainerEl: HTMLElement; + bodyColGroup: HTMLElement; + bodyTbody: HTMLElement; + bodyColEls: HTMLElement[]; + constructor(context: ComponentContext, headParentEl: HTMLElement, bodyParentEl: HTMLElement); + destroy(): void; + render(props: SpreadsheetProps): void; + renderCells(superHeaderText: any, colSpecs: any): void; + unrenderCells(): void; + renderColTags(colSpecs: any): string; + updateSize(isResize: any, totalHeight: any, isAuto: any): void; + applyColWidths(colWidths: (number | string)[]): void; + } +} + +declare module '@fullcalendar/resource-timeline/Row' { + import { Component, ComponentContext } from '@fullcalendar/core'; + export { Row as default, Row }; + abstract class Row<PropsType> extends Component<PropsType> { + spreadsheetTr: HTMLElement; + timeAxisTr: HTMLElement; + isSizeDirty: boolean; + constructor(context: ComponentContext, spreadsheetParent: HTMLElement, spreadsheetNextSibling: HTMLElement, timeAxisParent: HTMLElement, timeAxisNextSibling: HTMLElement); + destroy(): void; + abstract getHeightEls(): HTMLElement[]; + updateSize(isResize: boolean): void; + } +} + +declare module '@fullcalendar/resource-timeline/SpreadsheetRow' { + import { Component, ComponentContext } from '@fullcalendar/core'; + import { Resource } from '@fullcalendar/resource-common'; + export interface SpreadsheetRowProps { + colSpecs: any; + id: string; + rowSpans: number[]; + depth: number; + isExpanded: boolean; + hasChildren: boolean; + resource: Resource; + } + export { SpreadsheetRow as default, SpreadsheetRow }; + class SpreadsheetRow extends Component<SpreadsheetRowProps> { + tr: HTMLElement; + heightEl: HTMLElement; + expanderIconEl: HTMLElement; + constructor(context: ComponentContext, tr: HTMLElement); + render(props: SpreadsheetRowProps): void; + destroy(): void; + renderRow(resource: Resource, rowSpans: number[], depth: number, colSpecs: any): void; + unrenderRow(): void; + updateExpanderIcon(hasChildren: boolean, isExpanded: boolean): void; + onExpanderClick: (ev: UIEvent) => void; + } +} + +declare module '@fullcalendar/resource-timeline/SpreadsheetHeader' { + import { ElementDragging, Component, ComponentContext, EmitterMixin } from '@fullcalendar/core'; + export interface SpreadsheetHeaderProps { + superHeaderText: string; + colSpecs: any; + colTags: string; + } + export { SpreadsheetHeader as default, SpreadsheetHeader }; + class SpreadsheetHeader extends Component<SpreadsheetHeaderProps> { + tableEl: HTMLElement; + resizerEls: HTMLElement[]; + resizables: ElementDragging[]; + thEls: HTMLElement[]; + colEls: HTMLElement[]; + colWidths: number[]; + emitter: EmitterMixin; + constructor(context: ComponentContext, parentEl: HTMLElement); + destroy(): void; + render(props: SpreadsheetHeaderProps): void; + initColResizing(): void; + } +} + diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.esm.js b/AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.esm.js new file mode 100644 index 00000000..3ca4c0de --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.esm.js @@ -0,0 +1,1026 @@ +/*! +FullCalendar Resource Timeline Plugin v4.3.0 +Docs & License: https://fullcalendar.io/scheduler +(c) 2019 Adam Shaw +*/ + +import { removeElement, Component, memoizeRendering, createElement, htmlToElement, htmlEscape, isArraysEqual, EmitterMixin, memoize, parseFieldSpecs, PositionCache, applyStyleProp, View, createPlugin } from '@fullcalendar/core'; +import TimelinePlugin, { TimelineLane, HeaderBodyLayout, TimeAxis, ScrollJoiner, StickyScroller } from '@fullcalendar/timeline'; +import ResourceCommonPlugin, { isGroupsEqual, buildResourceFields, buildResourceTextFunc, ResourceApi, ResourceSplitter, buildRowNodes } from '@fullcalendar/resource-common'; + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} + +var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; + +var Row = /** @class */ (function (_super) { + __extends(Row, _super); + function Row(context, spreadsheetParent, spreadsheetNextSibling, timeAxisParent, timeAxisNextSibling) { + var _this = _super.call(this, context) || this; + _this.isSizeDirty = false; + spreadsheetParent.insertBefore(_this.spreadsheetTr = document.createElement('tr'), spreadsheetNextSibling); + timeAxisParent.insertBefore(_this.timeAxisTr = document.createElement('tr'), timeAxisNextSibling); + return _this; + } + Row.prototype.destroy = function () { + removeElement(this.spreadsheetTr); + removeElement(this.timeAxisTr); + _super.prototype.destroy.call(this); + }; + Row.prototype.updateSize = function (isResize) { + this.isSizeDirty = false; + }; + return Row; +}(Component)); + +function updateExpanderIcon(el, isExpanded) { + var classList = el.classList; + if (isExpanded) { + classList.remove('fc-icon-plus-square'); + classList.add('fc-icon-minus-square'); + } + else { + classList.remove('fc-icon-minus-square'); + classList.add('fc-icon-plus-square'); + } +} +function clearExpanderIcon(el) { + var classList = el.classList; + classList.remove('fc-icon-minus-square'); + classList.remove('fc-icon-plus-square'); +} +function updateTrResourceId(tr, resourceId) { + tr.setAttribute('data-resource-id', resourceId); +} + +var GroupRow = /** @class */ (function (_super) { + __extends(GroupRow, _super); + function GroupRow() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this._renderCells = memoizeRendering(_this.renderCells, _this.unrenderCells); + _this._updateExpanderIcon = memoizeRendering(_this.updateExpanderIcon, null, [_this._renderCells]); + _this.onExpanderClick = function (ev) { + var props = _this.props; + _this.calendar.dispatch({ + type: 'SET_RESOURCE_ENTITY_EXPANDED', + id: props.id, + isExpanded: !props.isExpanded + }); + }; + return _this; + } + GroupRow.prototype.render = function (props) { + this._renderCells(props.group, props.spreadsheetColCnt); + this._updateExpanderIcon(props.isExpanded); + this.isSizeDirty = true; + }; + GroupRow.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this._renderCells.unrender(); // should unrender everything else + }; + GroupRow.prototype.renderCells = function (group, spreadsheetColCnt) { + var spreadsheetContentEl = this.renderSpreadsheetContent(group); + this.spreadsheetTr.appendChild(createElement('td', { + className: 'fc-divider', + colSpan: spreadsheetColCnt // span across all columns + }, this.spreadsheetHeightEl = createElement('div', null, spreadsheetContentEl)) // needed by setTrInnerHeight + ); + this.expanderIconEl = spreadsheetContentEl.querySelector('.fc-icon'); + this.expanderIconEl.parentElement.addEventListener('click', this.onExpanderClick); + // insert a single cell, with a single empty <div>. + // there will be no content + this.timeAxisTr.appendChild(createElement('td', { className: 'fc-divider' }, this.timeAxisHeightEl = document.createElement('div'))); + }; + GroupRow.prototype.unrenderCells = function () { + this.spreadsheetTr.innerHTML = ''; + this.timeAxisTr.innerHTML = ''; + }; + /* + Renders the content wrapper element that will be inserted into this row's TD cell. + */ + GroupRow.prototype.renderSpreadsheetContent = function (group) { + var text = this.renderCellText(group); + var contentEl = htmlToElement('<div class="fc-cell-content">' + + '<span class="fc-expander">' + + '<span class="fc-icon"></span>' + + '</span>' + + '<span class="fc-cell-text">' + + (text ? htmlEscape(text) : ' ') + + '</span>' + + '</div>'); + var filter = group.spec.render; + if (typeof filter === 'function') { + contentEl = filter(contentEl, group.value) || contentEl; + } + return contentEl; + }; + GroupRow.prototype.renderCellText = function (group) { + var text = group.value || ''; // might be null/undefined if an ad-hoc grouping + var filter = group.spec.text; + if (typeof filter === 'function') { + text = filter(text) || text; + } + return text; + }; + GroupRow.prototype.getHeightEls = function () { + return [this.spreadsheetHeightEl, this.timeAxisHeightEl]; + }; + GroupRow.prototype.updateExpanderIcon = function (isExpanded) { + updateExpanderIcon(this.expanderIconEl, isExpanded); + }; + return GroupRow; +}(Row)); +GroupRow.addEqualityFuncs({ + group: isGroupsEqual // HACK for ResourceTimelineView::renderRows +}); + +var SpreadsheetRow = /** @class */ (function (_super) { + __extends(SpreadsheetRow, _super); + function SpreadsheetRow(context, tr) { + var _this = _super.call(this, context) || this; + _this._renderRow = memoizeRendering(_this.renderRow, _this.unrenderRow); + _this._updateTrResourceId = memoizeRendering(updateTrResourceId, null, [_this._renderRow]); + _this._updateExpanderIcon = memoizeRendering(_this.updateExpanderIcon, null, [_this._renderRow]); + _this.onExpanderClick = function (ev) { + var props = _this.props; + _this.calendar.dispatch({ + type: 'SET_RESOURCE_ENTITY_EXPANDED', + id: props.id, + isExpanded: !props.isExpanded + }); + }; + _this.tr = tr; + return _this; + } + SpreadsheetRow.prototype.render = function (props) { + this._renderRow(props.resource, props.rowSpans, props.depth, props.colSpecs); + this._updateTrResourceId(this.tr, props.resource.id); // TODO: only use public ID? + this._updateExpanderIcon(props.hasChildren, props.isExpanded); + }; + SpreadsheetRow.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this._renderRow.unrender(); // should unrender everything else + }; + SpreadsheetRow.prototype.renderRow = function (resource, rowSpans, depth, colSpecs) { + var _a = this, tr = _a.tr, theme = _a.theme, calendar = _a.calendar, view = _a.view; + var resourceFields = buildResourceFields(resource); // slightly inefficient. already done up the call stack + var mainTd; + for (var i = 0; i < colSpecs.length; i++) { + var colSpec = colSpecs[i]; + var rowSpan = rowSpans[i]; + if (rowSpan === 0) { // not responsible for group-based rows. VRowGroup is + continue; + } + else if (rowSpan == null) { + rowSpan = 1; + } + var text = void 0; + if (colSpec.field) { + text = resourceFields[colSpec.field]; + } + else { + text = buildResourceTextFunc(colSpec.text, calendar)(resource); + } + var contentEl = htmlToElement('<div class="fc-cell-content">' + + (colSpec.isMain ? renderIconHtml(depth) : '') + + '<span class="fc-cell-text">' + + (text ? htmlEscape(text) : ' ') + + '</span>' + + '</div>'); + if (typeof colSpec.render === 'function') { // a filter function for the element + contentEl = colSpec.render(new ResourceApi(calendar, resource), contentEl) || contentEl; + } + if (rowSpan > 1) { + contentEl.classList.add('fc-sticky'); + } + var td = createElement('td', { + className: theme.getClass('widgetContent'), + rowspan: rowSpan + }, contentEl); + // the first cell of the row needs to have an inner div for setTrInnerHeight + if (colSpec.isMain) { + td.appendChild(this.heightEl = createElement('div', null, td.childNodes) // inner wrap + ); + mainTd = td; + } + tr.appendChild(td); + } + this.expanderIconEl = tr.querySelector('.fc-expander-space .fc-icon'); + // wait until very end + view.publiclyTrigger('resourceRender', [ + { + resource: new ResourceApi(calendar, resource), + el: mainTd, + view: view + } + ]); + }; + SpreadsheetRow.prototype.unrenderRow = function () { + this.tr.innerHTML = ''; + }; + SpreadsheetRow.prototype.updateExpanderIcon = function (hasChildren, isExpanded) { + var expanderIconEl = this.expanderIconEl; + var expanderEl = expanderIconEl.parentElement; + if (expanderIconEl && + expanderEl // why would this be null?? was the case in IE11 + ) { + if (hasChildren) { + expanderEl.addEventListener('click', this.onExpanderClick); + expanderEl.classList.add('fc-expander'); + updateExpanderIcon(expanderIconEl, isExpanded); + } + else { + expanderEl.removeEventListener('click', this.onExpanderClick); + expanderEl.classList.remove('fc-expander'); + clearExpanderIcon(expanderIconEl); + } + } + }; + return SpreadsheetRow; +}(Component)); +/* +Renders the HTML responsible for the subrow expander area, +as well as the space before it (used to align expanders of similar depths) +*/ +function renderIconHtml(depth) { + var html = ''; + for (var i = 0; i < depth; i++) { + html += '<span class="fc-icon"></span>'; + } + html += + '<span class="fc-expander-space">' + + '<span class="fc-icon"></span>' + + '</span>'; + return html; +} + +var ResourceRow = /** @class */ (function (_super) { + __extends(ResourceRow, _super); + function ResourceRow(context, a, b, c, d, timeAxis) { + var _this = _super.call(this, context, a, b, c, d) || this; + _this._updateTrResourceId = memoizeRendering(updateTrResourceId); + _this.spreadsheetRow = new SpreadsheetRow(context, _this.spreadsheetTr); + _this.timeAxisTr.appendChild(createElement('td', { className: _this.theme.getClass('widgetContent') }, _this.innerContainerEl = document.createElement('div'))); + _this.lane = new TimelineLane(context, _this.innerContainerEl, _this.innerContainerEl, timeAxis); + return _this; + } + ResourceRow.prototype.destroy = function () { + this.spreadsheetRow.destroy(); + this.lane.destroy(); + _super.prototype.destroy.call(this); + }; + ResourceRow.prototype.render = function (props) { + // spreadsheetRow handles calling updateTrResourceId for spreadsheetTr + this.spreadsheetRow.receiveProps({ + colSpecs: props.colSpecs, + id: props.id, + rowSpans: props.rowSpans, + depth: props.depth, + isExpanded: props.isExpanded, + hasChildren: props.hasChildren, + resource: props.resource + }); + this._updateTrResourceId(this.timeAxisTr, props.resource.id); + this.lane.receiveProps({ + dateProfile: props.dateProfile, + nextDayThreshold: props.nextDayThreshold, + businessHours: props.businessHours, + eventStore: props.eventStore, + eventUiBases: props.eventUiBases, + dateSelection: props.dateSelection, + eventSelection: props.eventSelection, + eventDrag: props.eventDrag, + eventResize: props.eventResize + }); + this.isSizeDirty = true; + }; + ResourceRow.prototype.updateSize = function (isResize) { + _super.prototype.updateSize.call(this, isResize); + this.lane.updateSize(isResize); + }; + ResourceRow.prototype.getHeightEls = function () { + return [this.spreadsheetRow.heightEl, this.innerContainerEl]; + }; + return ResourceRow; +}(Row)); +ResourceRow.addEqualityFuncs({ + rowSpans: isArraysEqual // HACK for isSizeDirty, ResourceTimelineView::renderRows +}); + +var COL_MIN_WIDTH = 30; +var SpreadsheetHeader = /** @class */ (function (_super) { + __extends(SpreadsheetHeader, _super); + function SpreadsheetHeader(context, parentEl) { + var _this = _super.call(this, context) || this; + _this.resizables = []; + _this.colWidths = []; + _this.emitter = new EmitterMixin(); + parentEl.appendChild(_this.tableEl = createElement('table', { + className: _this.theme.getClass('tableGrid') + })); + return _this; + } + SpreadsheetHeader.prototype.destroy = function () { + for (var _i = 0, _a = this.resizables; _i < _a.length; _i++) { + var resizable = _a[_i]; + resizable.destroy(); + } + removeElement(this.tableEl); + _super.prototype.destroy.call(this); + }; + SpreadsheetHeader.prototype.render = function (props) { + var theme = this.theme; + var colSpecs = props.colSpecs; + var html = '<colgroup>' + props.colTags + '</colgroup>' + + '<tbody>'; + if (props.superHeaderText) { + html += + '<tr class="fc-super">' + + '<th class="' + theme.getClass('widgetHeader') + '" colspan="' + colSpecs.length + '">' + + '<div class="fc-cell-content">' + + '<span class="fc-cell-text">' + + htmlEscape(props.superHeaderText) + + '</span>' + + '</div>' + + '</th>' + + '</tr>'; + } + html += '<tr>'; + for (var i = 0; i < colSpecs.length; i++) { + var o = colSpecs[i]; + var isLast = i === (colSpecs.length - 1); + html += + "<th class=\"" + theme.getClass('widgetHeader') + "\">" + + '<div>' + + '<div class="fc-cell-content">' + + (o.isMain ? + '<span class="fc-expander-space">' + + '<span class="fc-icon"></span>' + + '</span>' : + '') + + '<span class="fc-cell-text">' + + htmlEscape(o.labelText || '') + // what about normalizing this value ahead of time? + '</span>' + + '</div>' + + (!isLast ? '<div class="fc-col-resizer"></div>' : '') + + '</div>' + + '</th>'; + } + html += '</tr>'; + html += '</tbody>'; + this.tableEl.innerHTML = html; + this.thEls = Array.prototype.slice.call(this.tableEl.querySelectorAll('th')); + this.colEls = Array.prototype.slice.call(this.tableEl.querySelectorAll('col')); + this.resizerEls = Array.prototype.slice.call(this.tableEl.querySelectorAll('.fc-col-resizer')); + this.initColResizing(); + }; + SpreadsheetHeader.prototype.initColResizing = function () { + var _this = this; + var ElementDraggingImpl = this.calendar.pluginSystem.hooks.elementDraggingImpl; + if (ElementDraggingImpl) { + this.resizables = this.resizerEls.map(function (handleEl, colIndex) { + var dragging = new ElementDraggingImpl(handleEl); + var startWidth; + dragging.emitter.on('dragstart', function () { + startWidth = _this.colWidths[colIndex]; + if (typeof startWidth !== 'number') { + startWidth = _this.thEls[colIndex].getBoundingClientRect().width; + } + }); + dragging.emitter.on('dragmove', function (pev) { + _this.colWidths[colIndex] = Math.max(startWidth + pev.deltaX * (_this.isRtl ? -1 : 1), COL_MIN_WIDTH); + _this.emitter.trigger('colwidthchange', _this.colWidths); + }); + dragging.setAutoScrollEnabled(false); // because gets weird with auto-scrolling time area + return dragging; + }); + } + }; + return SpreadsheetHeader; +}(Component)); + +var Spreadsheet = /** @class */ (function (_super) { + __extends(Spreadsheet, _super); + function Spreadsheet(context, headParentEl, bodyParentEl) { + var _this = _super.call(this, context) || this; + _this._renderCells = memoizeRendering(_this.renderCells, _this.unrenderCells); + _this.layout = new HeaderBodyLayout(headParentEl, bodyParentEl, 'clipped-scroll'); + var headerEnhancedScroller = _this.layout.headerScroller.enhancedScroll; + var bodyEnhancedScroller = _this.layout.bodyScroller.enhancedScroll; + _this.header = new SpreadsheetHeader(context, headerEnhancedScroller.canvas.contentEl); + _this.header.emitter.on('colwidthchange', function (colWidths) { + _this.applyColWidths(colWidths); + }); + bodyEnhancedScroller.canvas.contentEl + .appendChild(_this.bodyContainerEl = createElement('div', { className: 'fc-rows' }, '<table>' + + '<colgroup />' + + '<tbody />' + + '</table>')); + _this.bodyColGroup = _this.bodyContainerEl.querySelector('colgroup'); + _this.bodyTbody = _this.bodyContainerEl.querySelector('tbody'); + return _this; + } + Spreadsheet.prototype.destroy = function () { + this.header.destroy(); + this.layout.destroy(); + this._renderCells.unrender(); + _super.prototype.destroy.call(this); + }; + Spreadsheet.prototype.render = function (props) { + this._renderCells(props.superHeaderText, props.colSpecs); + }; + Spreadsheet.prototype.renderCells = function (superHeaderText, colSpecs) { + var colTags = this.renderColTags(colSpecs); + this.header.receiveProps({ + superHeaderText: superHeaderText, + colSpecs: colSpecs, + colTags: colTags + }); + this.bodyColGroup.innerHTML = colTags; + this.bodyColEls = Array.prototype.slice.call(this.bodyColGroup.querySelectorAll('col')); + this.applyColWidths(colSpecs.map(function (colSpec) { return colSpec.width; })); + }; + Spreadsheet.prototype.unrenderCells = function () { + this.bodyColGroup.innerHTML = ''; + }; + Spreadsheet.prototype.renderColTags = function (colSpecs) { + var html = ''; + for (var _i = 0, colSpecs_1 = colSpecs; _i < colSpecs_1.length; _i++) { + var o = colSpecs_1[_i]; + if (o.isMain) { + html += '<col class="fc-main-col"/>'; + } + else { + html += '<col/>'; + } + } + return html; + }; + Spreadsheet.prototype.updateSize = function (isResize, totalHeight, isAuto) { + this.layout.setHeight(totalHeight, isAuto); + }; + Spreadsheet.prototype.applyColWidths = function (colWidths) { + var _this = this; + colWidths.forEach(function (colWidth, colIndex) { + var headEl = _this.header.colEls[colIndex]; // bad to access child + var bodyEl = _this.bodyColEls[colIndex]; + var styleVal; + if (typeof colWidth === 'number') { + styleVal = colWidth + 'px'; + } + else if (typeof colWidth == null) { + styleVal = ''; + } + headEl.style.width = bodyEl.style.width = styleVal; + }); + }; + return Spreadsheet; +}(Component)); + +var MIN_RESOURCE_AREA_WIDTH = 30; // definitely bigger than scrollbars +var ResourceTimelineView = /** @class */ (function (_super) { + __extends(ResourceTimelineView, _super); + function ResourceTimelineView(context, viewSpec, dateProfileGenerator, parentEl) { + var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this; + _this.isStickyScrollDirty = false; + _this.rowNodes = []; + _this.rowComponents = []; + _this.rowComponentsById = {}; + _this.resourceAreaWidthDraggings = []; + _this.splitter = new ResourceSplitter(); // doesn't let it do businessHours tho + _this.hasResourceBusinessHours = memoize(hasResourceBusinessHours); + _this.buildRowNodes = memoize(buildRowNodes); + _this.hasNesting = memoize(hasNesting); + _this._updateHasNesting = memoizeRendering(_this.updateHasNesting); + var allColSpecs = _this.opt('resourceColumns') || []; + var labelText = _this.opt('resourceLabelText'); // TODO: view.override + var defaultLabelText = 'Resources'; // TODO: view.defaults + var superHeaderText = null; + if (!allColSpecs.length) { + allColSpecs.push({ + labelText: labelText || defaultLabelText, + text: buildResourceTextFunc(_this.opt('resourceText'), _this.calendar) + }); + } + else { + superHeaderText = labelText; + } + var plainColSpecs = []; + var groupColSpecs = []; + var groupSpecs = []; + var isVGrouping = false; + var isHGrouping = false; + for (var _i = 0, allColSpecs_1 = allColSpecs; _i < allColSpecs_1.length; _i++) { + var colSpec = allColSpecs_1[_i]; + if (colSpec.group) { + groupColSpecs.push(colSpec); + } + else { + plainColSpecs.push(colSpec); + } + } + plainColSpecs[0].isMain = true; + if (groupColSpecs.length) { + groupSpecs = groupColSpecs; + isVGrouping = true; + } + else { + var hGroupField = _this.opt('resourceGroupField'); + if (hGroupField) { + isHGrouping = true; + groupSpecs.push({ + field: hGroupField, + text: _this.opt('resourceGroupText'), + render: _this.opt('resourceGroupRender') + }); + } + } + var allOrderSpecs = parseFieldSpecs(_this.opt('resourceOrder')); + var plainOrderSpecs = []; + for (var _a = 0, allOrderSpecs_1 = allOrderSpecs; _a < allOrderSpecs_1.length; _a++) { + var orderSpec = allOrderSpecs_1[_a]; + var isGroup = false; + for (var _b = 0, groupSpecs_1 = groupSpecs; _b < groupSpecs_1.length; _b++) { + var groupSpec = groupSpecs_1[_b]; + if (groupSpec.field === orderSpec.field) { + groupSpec.order = orderSpec.order; // -1, 0, 1 + isGroup = true; + break; + } + } + if (!isGroup) { + plainOrderSpecs.push(orderSpec); + } + } + _this.superHeaderText = superHeaderText; + _this.isVGrouping = isVGrouping; + _this.isHGrouping = isHGrouping; + _this.groupSpecs = groupSpecs; + _this.colSpecs = groupColSpecs.concat(plainColSpecs); + _this.orderSpecs = plainOrderSpecs; + // START RENDERING... + _this.el.classList.add('fc-timeline'); + if (_this.opt('eventOverlap') === false) { + _this.el.classList.add('fc-no-overlap'); + } + _this.el.innerHTML = _this.renderSkeletonHtml(); + _this.resourceAreaHeadEl = _this.el.querySelector('thead .fc-resource-area'); + _this.setResourceAreaWidth(_this.opt('resourceAreaWidth')); + _this.initResourceAreaWidthDragging(); + _this.miscHeight = _this.el.getBoundingClientRect().height; + _this.spreadsheet = new Spreadsheet(_this.context, _this.resourceAreaHeadEl, _this.el.querySelector('tbody .fc-resource-area')); + _this.timeAxis = new TimeAxis(_this.context, _this.el.querySelector('thead .fc-time-area'), _this.el.querySelector('tbody .fc-time-area')); + var timeAxisRowContainer = createElement('div', { className: 'fc-rows' }, '<table><tbody /></table>'); + _this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.contentEl.appendChild(timeAxisRowContainer); + _this.timeAxisTbody = timeAxisRowContainer.querySelector('tbody'); + _this.lane = new TimelineLane(_this.context, null, _this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.bgEl, _this.timeAxis); + _this.bodyScrollJoiner = new ScrollJoiner('vertical', [ + _this.spreadsheet.layout.bodyScroller, + _this.timeAxis.layout.bodyScroller + ]); + // after scrolljoiner + _this.spreadsheetBodyStickyScroller = new StickyScroller(_this.spreadsheet.layout.bodyScroller.enhancedScroll, _this.isRtl, true // isVertical + ); + _this.spreadsheet.receiveProps({ + superHeaderText: _this.superHeaderText, + colSpecs: _this.colSpecs + }); + // Component... + context.calendar.registerInteractiveComponent(_this, { + el: _this.timeAxis.slats.el + }); + return _this; + } + ResourceTimelineView.prototype.renderSkeletonHtml = function () { + var theme = this.theme; + return "<table class=\"" + theme.getClass('tableGrid') + "\"> <thead class=\"fc-head\"> <tr> <td class=\"fc-resource-area " + theme.getClass('widgetHeader') + "\"></td> <td class=\"fc-divider fc-col-resizer " + theme.getClass('widgetHeader') + "\"></td> <td class=\"fc-time-area " + theme.getClass('widgetHeader') + "\"></td> </tr> </thead> <tbody class=\"fc-body\"> <tr> <td class=\"fc-resource-area " + theme.getClass('widgetContent') + "\"></td> <td class=\"fc-divider fc-col-resizer " + theme.getClass('widgetHeader') + "\"></td> <td class=\"fc-time-area " + theme.getClass('widgetContent') + "\"></td> </tr> </tbody> </table>"; + }; + ResourceTimelineView.prototype.render = function (props) { + _super.prototype.render.call(this, props); + var splitProps = this.splitter.splitProps(props); + var hasResourceBusinessHours = this.hasResourceBusinessHours(props.resourceStore); + this.timeAxis.receiveProps({ + dateProfile: props.dateProfile + }); + // for all-resource bg events / selections / business-hours + this.lane.receiveProps(__assign({}, splitProps[''], { dateProfile: props.dateProfile, nextDayThreshold: this.nextDayThreshold, businessHours: hasResourceBusinessHours ? null : props.businessHours })); + var newRowNodes = this.buildRowNodes(props.resourceStore, this.groupSpecs, this.orderSpecs, this.isVGrouping, props.resourceEntityExpansions, this.opt('resourcesInitiallyExpanded')); + this._updateHasNesting(this.hasNesting(newRowNodes)); + this.diffRows(newRowNodes); + this.renderRows(props.dateProfile, hasResourceBusinessHours ? props.businessHours : null, // CONFUSING, comment + splitProps); + }; + ResourceTimelineView.prototype.updateHasNesting = function (isNesting) { + var classList = this.el.classList; + if (isNesting) { + classList.remove('fc-flat'); + } + else { + classList.add('fc-flat'); + } + }; + ResourceTimelineView.prototype.diffRows = function (newNodes) { + var oldNodes = this.rowNodes; + var oldLen = oldNodes.length; + var oldIndexHash = {}; // id -> index + var oldI = 0; + var newI = 0; + for (oldI = 0; oldI < oldLen; oldI++) { + oldIndexHash[oldNodes[oldI].id] = oldI; + } + // iterate new nodes + for (oldI = 0, newI = 0; newI < newNodes.length; newI++) { + var newNode = newNodes[newI]; + var oldIFound = oldIndexHash[newNode.id]; + if (oldIFound != null && oldIFound >= oldI) { + this.removeRows(newI, oldIFound - oldI, oldNodes); // won't do anything if same index + oldI = oldIFound + 1; + } + else { + this.addRow(newI, newNode); + } + } + // old rows that weren't found need to be removed + this.removeRows(newI, oldLen - oldI, oldNodes); // won't do anything if same index + this.rowNodes = newNodes; + }; + /* + rowComponents is the in-progress result + */ + ResourceTimelineView.prototype.addRow = function (index, rowNode) { + var _a = this, rowComponents = _a.rowComponents, rowComponentsById = _a.rowComponentsById; + var nextComponent = rowComponents[index]; + var newComponent = this.buildChildComponent(rowNode, this.spreadsheet.bodyTbody, nextComponent ? nextComponent.spreadsheetTr : null, this.timeAxisTbody, nextComponent ? nextComponent.timeAxisTr : null); + rowComponents.splice(index, 0, newComponent); + rowComponentsById[rowNode.id] = newComponent; + }; + ResourceTimelineView.prototype.removeRows = function (startIndex, len, oldRowNodes) { + if (len) { + var _a = this, rowComponents = _a.rowComponents, rowComponentsById = _a.rowComponentsById; + for (var i = 0; i < len; i++) { + var rowComponent = rowComponents[startIndex + i]; + rowComponent.destroy(); + delete rowComponentsById[oldRowNodes[i].id]; + } + rowComponents.splice(startIndex, len); + } + }; + ResourceTimelineView.prototype.buildChildComponent = function (node, spreadsheetTbody, spreadsheetNext, timeAxisTbody, timeAxisNext) { + if (node.group) { + return new GroupRow(this.context, spreadsheetTbody, spreadsheetNext, timeAxisTbody, timeAxisNext); + } + else if (node.resource) { + return new ResourceRow(this.context, spreadsheetTbody, spreadsheetNext, timeAxisTbody, timeAxisNext, this.timeAxis); + } + }; + ResourceTimelineView.prototype.renderRows = function (dateProfile, fallbackBusinessHours, splitProps) { + var _a = this, rowNodes = _a.rowNodes, rowComponents = _a.rowComponents; + for (var i = 0; i < rowNodes.length; i++) { + var rowNode = rowNodes[i]; + var rowComponent = rowComponents[i]; + if (rowNode.group) { + rowComponent.receiveProps({ + spreadsheetColCnt: this.colSpecs.length, + id: rowNode.id, + isExpanded: rowNode.isExpanded, + group: rowNode.group + }); + } + else { + var resource = rowNode.resource; + rowComponent.receiveProps(__assign({}, splitProps[resource.id], { dateProfile: dateProfile, nextDayThreshold: this.nextDayThreshold, businessHours: resource.businessHours || fallbackBusinessHours, colSpecs: this.colSpecs, id: rowNode.id, rowSpans: rowNode.rowSpans, depth: rowNode.depth, isExpanded: rowNode.isExpanded, hasChildren: rowNode.hasChildren, resource: rowNode.resource })); + } + } + }; + ResourceTimelineView.prototype.updateSize = function (isResize, viewHeight, isAuto) { + // FYI: this ordering is really important + var calendar = this.calendar; + var isBaseSizing = isResize || calendar.isViewUpdated || calendar.isDatesUpdated || calendar.isEventsUpdated; + if (isBaseSizing) { + this.syncHeadHeights(); + this.timeAxis.updateSize(isResize, viewHeight - this.miscHeight, isAuto); + this.spreadsheet.updateSize(isResize, viewHeight - this.miscHeight, isAuto); + } + var rowSizingCnt = this.updateRowSizes(isResize); + this.lane.updateSize(isResize); // is efficient. uses flags + if (isBaseSizing || rowSizingCnt) { + this.bodyScrollJoiner.update(); + this.timeAxis.layout.scrollJoiner.update(); // hack + this.rowPositions = new PositionCache(this.timeAxis.slats.el, this.rowComponents.map(function (rowComponent) { + return rowComponent.timeAxisTr; + }), false, // isHorizontal + true // isVertical + ); + this.rowPositions.build(); + this.isStickyScrollDirty = true; + } + }; + ResourceTimelineView.prototype.syncHeadHeights = function () { + var spreadsheetHeadEl = this.spreadsheet.header.tableEl; + var timeAxisHeadEl = this.timeAxis.header.tableEl; + spreadsheetHeadEl.style.height = ''; + timeAxisHeadEl.style.height = ''; + var max = Math.max(spreadsheetHeadEl.getBoundingClientRect().height, timeAxisHeadEl.getBoundingClientRect().height); + spreadsheetHeadEl.style.height = + timeAxisHeadEl.style.height = max + 'px'; + }; + ResourceTimelineView.prototype.updateRowSizes = function (isResize) { + var dirtyRowComponents = this.rowComponents; + if (!isResize) { + dirtyRowComponents = dirtyRowComponents.filter(function (rowComponent) { + return rowComponent.isSizeDirty; + }); + } + var elArrays = dirtyRowComponents.map(function (rowComponent) { + return rowComponent.getHeightEls(); + }); + // reset to natural heights + for (var _i = 0, elArrays_1 = elArrays; _i < elArrays_1.length; _i++) { + var elArray = elArrays_1[_i]; + for (var _a = 0, elArray_1 = elArray; _a < elArray_1.length; _a++) { + var el = elArray_1[_a]; + el.style.height = ''; + } + } + // let rows update their contents' heights + for (var _b = 0, dirtyRowComponents_1 = dirtyRowComponents; _b < dirtyRowComponents_1.length; _b++) { + var rowComponent = dirtyRowComponents_1[_b]; + rowComponent.updateSize(isResize); // will reset isSizeDirty + } + var maxHeights = elArrays.map(function (elArray) { + var maxHeight = null; + for (var _i = 0, elArray_2 = elArray; _i < elArray_2.length; _i++) { + var el = elArray_2[_i]; + var height = el.getBoundingClientRect().height; + if (maxHeight === null || height > maxHeight) { + maxHeight = height; + } + } + return maxHeight; + }); + for (var i = 0; i < elArrays.length; i++) { + for (var _c = 0, _d = elArrays[i]; _c < _d.length; _c++) { + var el = _d[_c]; + el.style.height = maxHeights[i] + 'px'; + } + } + return dirtyRowComponents.length; + }; + ResourceTimelineView.prototype.destroy = function () { + for (var _i = 0, _a = this.rowComponents; _i < _a.length; _i++) { + var rowComponent = _a[_i]; + rowComponent.destroy(); + } + this.rowNodes = []; + this.rowComponents = []; + this.spreadsheet.destroy(); + this.timeAxis.destroy(); + for (var _b = 0, _c = this.resourceAreaWidthDraggings; _b < _c.length; _b++) { + var resourceAreaWidthDragging = _c[_b]; + resourceAreaWidthDragging.destroy(); + } + this.spreadsheetBodyStickyScroller.destroy(); + _super.prototype.destroy.call(this); + this.calendar.unregisterInteractiveComponent(this); + }; + // Now Indicator + // ------------------------------------------------------------------------------------------ + ResourceTimelineView.prototype.getNowIndicatorUnit = function (dateProfile) { + return this.timeAxis.getNowIndicatorUnit(dateProfile); + }; + ResourceTimelineView.prototype.renderNowIndicator = function (date) { + this.timeAxis.renderNowIndicator(date); + }; + ResourceTimelineView.prototype.unrenderNowIndicator = function () { + this.timeAxis.unrenderNowIndicator(); + }; + // Scrolling + // ------------------------------------------------------------------------------------------------------------------ + // this is useful for scrolling prev/next dates while resource is scrolled down + ResourceTimelineView.prototype.queryScroll = function () { + var scroll = _super.prototype.queryScroll.call(this); + if (this.props.resourceStore) { + __assign(scroll, this.queryResourceScroll()); + } + return scroll; + }; + ResourceTimelineView.prototype.applyScroll = function (scroll, isResize) { + _super.prototype.applyScroll.call(this, scroll, isResize); + if (this.props.resourceStore) { + this.applyResourceScroll(scroll); + } + // avoid updating stickyscroll too often + if (isResize || this.isStickyScrollDirty) { + this.isStickyScrollDirty = false; + this.spreadsheetBodyStickyScroller.updateSize(); + this.timeAxis.updateStickyScrollers(); + } + }; + ResourceTimelineView.prototype.computeDateScroll = function (duration) { + return this.timeAxis.computeDateScroll(duration); + }; + ResourceTimelineView.prototype.queryDateScroll = function () { + return this.timeAxis.queryDateScroll(); + }; + ResourceTimelineView.prototype.applyDateScroll = function (scroll) { + this.timeAxis.applyDateScroll(scroll); + }; + ResourceTimelineView.prototype.queryResourceScroll = function () { + var _a = this, rowComponents = _a.rowComponents, rowNodes = _a.rowNodes; + var scroll = {}; + var scrollerTop = this.timeAxis.layout.bodyScroller.el.getBoundingClientRect().top; // fixed position + for (var i = 0; i < rowComponents.length; i++) { + var rowComponent = rowComponents[i]; + var rowNode = rowNodes[i]; + var el = rowComponent.timeAxisTr; + var elBottom = el.getBoundingClientRect().bottom; // fixed position + if (elBottom > scrollerTop) { + scroll.rowId = rowNode.id; + scroll.bottom = elBottom - scrollerTop; + break; + } + } + // TODO: what about left scroll state for spreadsheet area? + return scroll; + }; + ResourceTimelineView.prototype.applyResourceScroll = function (scroll) { + var rowId = scroll.forcedRowId || scroll.rowId; + if (rowId) { + var rowComponent = this.rowComponentsById[rowId]; + if (rowComponent) { + var el = rowComponent.timeAxisTr; + if (el) { + var innerTop = this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.el.getBoundingClientRect().top; + var rowRect = el.getBoundingClientRect(); + var scrollTop = (scroll.forcedRowId ? + rowRect.top : // just use top edge + rowRect.bottom - scroll.bottom) - // pixels from bottom edge + innerTop; + this.timeAxis.layout.bodyScroller.enhancedScroll.setScrollTop(scrollTop); + this.spreadsheet.layout.bodyScroller.enhancedScroll.setScrollTop(scrollTop); + } + } + } + }; + // TODO: scrollToResource + // Hit System + // ------------------------------------------------------------------------------------------ + ResourceTimelineView.prototype.buildPositionCaches = function () { + this.timeAxis.slats.updateSize(); + this.rowPositions.build(); + }; + ResourceTimelineView.prototype.queryHit = function (positionLeft, positionTop) { + var rowPositions = this.rowPositions; + var slats = this.timeAxis.slats; + var rowIndex = rowPositions.topToIndex(positionTop); + if (rowIndex != null) { + var resource = this.rowNodes[rowIndex].resource; + if (resource) { // not a group + var slatHit = slats.positionToHit(positionLeft); + if (slatHit) { + return { + component: this, + dateSpan: { + range: slatHit.dateSpan.range, + allDay: slatHit.dateSpan.allDay, + resourceId: resource.id + }, + rect: { + left: slatHit.left, + right: slatHit.right, + top: rowPositions.tops[rowIndex], + bottom: rowPositions.bottoms[rowIndex] + }, + dayEl: slatHit.dayEl, + layer: 0 + }; + } + } + } + }; + // Resource Area + // ------------------------------------------------------------------------------------------------------------------ + ResourceTimelineView.prototype.setResourceAreaWidth = function (widthVal) { + this.resourceAreaWidth = widthVal; + applyStyleProp(this.resourceAreaHeadEl, 'width', widthVal || ''); + }; + ResourceTimelineView.prototype.initResourceAreaWidthDragging = function () { + var _this = this; + var resourceAreaDividerEls = Array.prototype.slice.call(this.el.querySelectorAll('.fc-col-resizer')); + var ElementDraggingImpl = this.calendar.pluginSystem.hooks.elementDraggingImpl; + if (ElementDraggingImpl) { + this.resourceAreaWidthDraggings = resourceAreaDividerEls.map(function (el) { + var dragging = new ElementDraggingImpl(el); + var dragStartWidth; + var viewWidth; + dragging.emitter.on('dragstart', function () { + dragStartWidth = _this.resourceAreaWidth; + if (typeof dragStartWidth !== 'number') { + dragStartWidth = _this.resourceAreaHeadEl.getBoundingClientRect().width; + } + viewWidth = _this.el.getBoundingClientRect().width; + }); + dragging.emitter.on('dragmove', function (pev) { + var newWidth = dragStartWidth + pev.deltaX * (_this.isRtl ? -1 : 1); + newWidth = Math.max(newWidth, MIN_RESOURCE_AREA_WIDTH); + newWidth = Math.min(newWidth, viewWidth - MIN_RESOURCE_AREA_WIDTH); + _this.setResourceAreaWidth(newWidth); + }); + dragging.setAutoScrollEnabled(false); // because gets weird with auto-scrolling time area + return dragging; + }); + } + }; + ResourceTimelineView.needsResourceData = true; // for ResourceViewProps + return ResourceTimelineView; +}(View)); +function hasResourceBusinessHours(resourceStore) { + for (var resourceId in resourceStore) { + var resource = resourceStore[resourceId]; + if (resource.businessHours) { + return true; + } + } + return false; +} +function hasNesting(nodes) { + for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) { + var node = nodes_1[_i]; + if (node.group) { + return true; + } + else if (node.resource) { + if (node.hasChildren) { + return true; + } + } + } + return false; +} + +var main = createPlugin({ + deps: [ResourceCommonPlugin, TimelinePlugin], + defaultView: 'resourceTimelineDay', + views: { + resourceTimeline: { + class: ResourceTimelineView, + resourceAreaWidth: '30%', + resourcesInitiallyExpanded: true, + eventResizableFromStart: true // TODO: not DRY with this same setting in the main timeline config + }, + resourceTimelineDay: { + type: 'resourceTimeline', + duration: { days: 1 } + }, + resourceTimelineWeek: { + type: 'resourceTimeline', + duration: { weeks: 1 } + }, + resourceTimelineMonth: { + type: 'resourceTimeline', + duration: { months: 1 } + }, + resourceTimelineYear: { + type: 'resourceTimeline', + duration: { years: 1 } + } + } +}); + +export default main; +export { ResourceTimelineView }; diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.js b/AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.js new file mode 100644 index 00000000..2631955c --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.js @@ -0,0 +1,1035 @@ +/*! +FullCalendar Resource Timeline Plugin v4.3.0 +Docs & License: https://fullcalendar.io/scheduler +(c) 2019 Adam Shaw +*/ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core'), require('@fullcalendar/timeline'), require('@fullcalendar/resource-common')) : + typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core', '@fullcalendar/timeline', '@fullcalendar/resource-common'], factory) : + (global = global || self, factory(global.FullCalendarResourceTimeline = {}, global.FullCalendar, global.FullCalendarTimeline, global.FullCalendarResourceCommon)); +}(this, function (exports, core, TimelinePlugin, ResourceCommonPlugin) { 'use strict'; + + var TimelinePlugin__default = 'default' in TimelinePlugin ? TimelinePlugin['default'] : TimelinePlugin; + var ResourceCommonPlugin__default = 'default' in ResourceCommonPlugin ? ResourceCommonPlugin['default'] : ResourceCommonPlugin; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + var Row = /** @class */ (function (_super) { + __extends(Row, _super); + function Row(context, spreadsheetParent, spreadsheetNextSibling, timeAxisParent, timeAxisNextSibling) { + var _this = _super.call(this, context) || this; + _this.isSizeDirty = false; + spreadsheetParent.insertBefore(_this.spreadsheetTr = document.createElement('tr'), spreadsheetNextSibling); + timeAxisParent.insertBefore(_this.timeAxisTr = document.createElement('tr'), timeAxisNextSibling); + return _this; + } + Row.prototype.destroy = function () { + core.removeElement(this.spreadsheetTr); + core.removeElement(this.timeAxisTr); + _super.prototype.destroy.call(this); + }; + Row.prototype.updateSize = function (isResize) { + this.isSizeDirty = false; + }; + return Row; + }(core.Component)); + + function updateExpanderIcon(el, isExpanded) { + var classList = el.classList; + if (isExpanded) { + classList.remove('fc-icon-plus-square'); + classList.add('fc-icon-minus-square'); + } + else { + classList.remove('fc-icon-minus-square'); + classList.add('fc-icon-plus-square'); + } + } + function clearExpanderIcon(el) { + var classList = el.classList; + classList.remove('fc-icon-minus-square'); + classList.remove('fc-icon-plus-square'); + } + function updateTrResourceId(tr, resourceId) { + tr.setAttribute('data-resource-id', resourceId); + } + + var GroupRow = /** @class */ (function (_super) { + __extends(GroupRow, _super); + function GroupRow() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this._renderCells = core.memoizeRendering(_this.renderCells, _this.unrenderCells); + _this._updateExpanderIcon = core.memoizeRendering(_this.updateExpanderIcon, null, [_this._renderCells]); + _this.onExpanderClick = function (ev) { + var props = _this.props; + _this.calendar.dispatch({ + type: 'SET_RESOURCE_ENTITY_EXPANDED', + id: props.id, + isExpanded: !props.isExpanded + }); + }; + return _this; + } + GroupRow.prototype.render = function (props) { + this._renderCells(props.group, props.spreadsheetColCnt); + this._updateExpanderIcon(props.isExpanded); + this.isSizeDirty = true; + }; + GroupRow.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this._renderCells.unrender(); // should unrender everything else + }; + GroupRow.prototype.renderCells = function (group, spreadsheetColCnt) { + var spreadsheetContentEl = this.renderSpreadsheetContent(group); + this.spreadsheetTr.appendChild(core.createElement('td', { + className: 'fc-divider', + colSpan: spreadsheetColCnt // span across all columns + }, this.spreadsheetHeightEl = core.createElement('div', null, spreadsheetContentEl)) // needed by setTrInnerHeight + ); + this.expanderIconEl = spreadsheetContentEl.querySelector('.fc-icon'); + this.expanderIconEl.parentElement.addEventListener('click', this.onExpanderClick); + // insert a single cell, with a single empty <div>. + // there will be no content + this.timeAxisTr.appendChild(core.createElement('td', { className: 'fc-divider' }, this.timeAxisHeightEl = document.createElement('div'))); + }; + GroupRow.prototype.unrenderCells = function () { + this.spreadsheetTr.innerHTML = ''; + this.timeAxisTr.innerHTML = ''; + }; + /* + Renders the content wrapper element that will be inserted into this row's TD cell. + */ + GroupRow.prototype.renderSpreadsheetContent = function (group) { + var text = this.renderCellText(group); + var contentEl = core.htmlToElement('<div class="fc-cell-content">' + + '<span class="fc-expander">' + + '<span class="fc-icon"></span>' + + '</span>' + + '<span class="fc-cell-text">' + + (text ? core.htmlEscape(text) : ' ') + + '</span>' + + '</div>'); + var filter = group.spec.render; + if (typeof filter === 'function') { + contentEl = filter(contentEl, group.value) || contentEl; + } + return contentEl; + }; + GroupRow.prototype.renderCellText = function (group) { + var text = group.value || ''; // might be null/undefined if an ad-hoc grouping + var filter = group.spec.text; + if (typeof filter === 'function') { + text = filter(text) || text; + } + return text; + }; + GroupRow.prototype.getHeightEls = function () { + return [this.spreadsheetHeightEl, this.timeAxisHeightEl]; + }; + GroupRow.prototype.updateExpanderIcon = function (isExpanded) { + updateExpanderIcon(this.expanderIconEl, isExpanded); + }; + return GroupRow; + }(Row)); + GroupRow.addEqualityFuncs({ + group: ResourceCommonPlugin.isGroupsEqual // HACK for ResourceTimelineView::renderRows + }); + + var SpreadsheetRow = /** @class */ (function (_super) { + __extends(SpreadsheetRow, _super); + function SpreadsheetRow(context, tr) { + var _this = _super.call(this, context) || this; + _this._renderRow = core.memoizeRendering(_this.renderRow, _this.unrenderRow); + _this._updateTrResourceId = core.memoizeRendering(updateTrResourceId, null, [_this._renderRow]); + _this._updateExpanderIcon = core.memoizeRendering(_this.updateExpanderIcon, null, [_this._renderRow]); + _this.onExpanderClick = function (ev) { + var props = _this.props; + _this.calendar.dispatch({ + type: 'SET_RESOURCE_ENTITY_EXPANDED', + id: props.id, + isExpanded: !props.isExpanded + }); + }; + _this.tr = tr; + return _this; + } + SpreadsheetRow.prototype.render = function (props) { + this._renderRow(props.resource, props.rowSpans, props.depth, props.colSpecs); + this._updateTrResourceId(this.tr, props.resource.id); // TODO: only use public ID? + this._updateExpanderIcon(props.hasChildren, props.isExpanded); + }; + SpreadsheetRow.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this._renderRow.unrender(); // should unrender everything else + }; + SpreadsheetRow.prototype.renderRow = function (resource, rowSpans, depth, colSpecs) { + var _a = this, tr = _a.tr, theme = _a.theme, calendar = _a.calendar, view = _a.view; + var resourceFields = ResourceCommonPlugin.buildResourceFields(resource); // slightly inefficient. already done up the call stack + var mainTd; + for (var i = 0; i < colSpecs.length; i++) { + var colSpec = colSpecs[i]; + var rowSpan = rowSpans[i]; + if (rowSpan === 0) { // not responsible for group-based rows. VRowGroup is + continue; + } + else if (rowSpan == null) { + rowSpan = 1; + } + var text = void 0; + if (colSpec.field) { + text = resourceFields[colSpec.field]; + } + else { + text = ResourceCommonPlugin.buildResourceTextFunc(colSpec.text, calendar)(resource); + } + var contentEl = core.htmlToElement('<div class="fc-cell-content">' + + (colSpec.isMain ? renderIconHtml(depth) : '') + + '<span class="fc-cell-text">' + + (text ? core.htmlEscape(text) : ' ') + + '</span>' + + '</div>'); + if (typeof colSpec.render === 'function') { // a filter function for the element + contentEl = colSpec.render(new ResourceCommonPlugin.ResourceApi(calendar, resource), contentEl) || contentEl; + } + if (rowSpan > 1) { + contentEl.classList.add('fc-sticky'); + } + var td = core.createElement('td', { + className: theme.getClass('widgetContent'), + rowspan: rowSpan + }, contentEl); + // the first cell of the row needs to have an inner div for setTrInnerHeight + if (colSpec.isMain) { + td.appendChild(this.heightEl = core.createElement('div', null, td.childNodes) // inner wrap + ); + mainTd = td; + } + tr.appendChild(td); + } + this.expanderIconEl = tr.querySelector('.fc-expander-space .fc-icon'); + // wait until very end + view.publiclyTrigger('resourceRender', [ + { + resource: new ResourceCommonPlugin.ResourceApi(calendar, resource), + el: mainTd, + view: view + } + ]); + }; + SpreadsheetRow.prototype.unrenderRow = function () { + this.tr.innerHTML = ''; + }; + SpreadsheetRow.prototype.updateExpanderIcon = function (hasChildren, isExpanded) { + var expanderIconEl = this.expanderIconEl; + var expanderEl = expanderIconEl.parentElement; + if (expanderIconEl && + expanderEl // why would this be null?? was the case in IE11 + ) { + if (hasChildren) { + expanderEl.addEventListener('click', this.onExpanderClick); + expanderEl.classList.add('fc-expander'); + updateExpanderIcon(expanderIconEl, isExpanded); + } + else { + expanderEl.removeEventListener('click', this.onExpanderClick); + expanderEl.classList.remove('fc-expander'); + clearExpanderIcon(expanderIconEl); + } + } + }; + return SpreadsheetRow; + }(core.Component)); + /* + Renders the HTML responsible for the subrow expander area, + as well as the space before it (used to align expanders of similar depths) + */ + function renderIconHtml(depth) { + var html = ''; + for (var i = 0; i < depth; i++) { + html += '<span class="fc-icon"></span>'; + } + html += + '<span class="fc-expander-space">' + + '<span class="fc-icon"></span>' + + '</span>'; + return html; + } + + var ResourceRow = /** @class */ (function (_super) { + __extends(ResourceRow, _super); + function ResourceRow(context, a, b, c, d, timeAxis) { + var _this = _super.call(this, context, a, b, c, d) || this; + _this._updateTrResourceId = core.memoizeRendering(updateTrResourceId); + _this.spreadsheetRow = new SpreadsheetRow(context, _this.spreadsheetTr); + _this.timeAxisTr.appendChild(core.createElement('td', { className: _this.theme.getClass('widgetContent') }, _this.innerContainerEl = document.createElement('div'))); + _this.lane = new TimelinePlugin.TimelineLane(context, _this.innerContainerEl, _this.innerContainerEl, timeAxis); + return _this; + } + ResourceRow.prototype.destroy = function () { + this.spreadsheetRow.destroy(); + this.lane.destroy(); + _super.prototype.destroy.call(this); + }; + ResourceRow.prototype.render = function (props) { + // spreadsheetRow handles calling updateTrResourceId for spreadsheetTr + this.spreadsheetRow.receiveProps({ + colSpecs: props.colSpecs, + id: props.id, + rowSpans: props.rowSpans, + depth: props.depth, + isExpanded: props.isExpanded, + hasChildren: props.hasChildren, + resource: props.resource + }); + this._updateTrResourceId(this.timeAxisTr, props.resource.id); + this.lane.receiveProps({ + dateProfile: props.dateProfile, + nextDayThreshold: props.nextDayThreshold, + businessHours: props.businessHours, + eventStore: props.eventStore, + eventUiBases: props.eventUiBases, + dateSelection: props.dateSelection, + eventSelection: props.eventSelection, + eventDrag: props.eventDrag, + eventResize: props.eventResize + }); + this.isSizeDirty = true; + }; + ResourceRow.prototype.updateSize = function (isResize) { + _super.prototype.updateSize.call(this, isResize); + this.lane.updateSize(isResize); + }; + ResourceRow.prototype.getHeightEls = function () { + return [this.spreadsheetRow.heightEl, this.innerContainerEl]; + }; + return ResourceRow; + }(Row)); + ResourceRow.addEqualityFuncs({ + rowSpans: core.isArraysEqual // HACK for isSizeDirty, ResourceTimelineView::renderRows + }); + + var COL_MIN_WIDTH = 30; + var SpreadsheetHeader = /** @class */ (function (_super) { + __extends(SpreadsheetHeader, _super); + function SpreadsheetHeader(context, parentEl) { + var _this = _super.call(this, context) || this; + _this.resizables = []; + _this.colWidths = []; + _this.emitter = new core.EmitterMixin(); + parentEl.appendChild(_this.tableEl = core.createElement('table', { + className: _this.theme.getClass('tableGrid') + })); + return _this; + } + SpreadsheetHeader.prototype.destroy = function () { + for (var _i = 0, _a = this.resizables; _i < _a.length; _i++) { + var resizable = _a[_i]; + resizable.destroy(); + } + core.removeElement(this.tableEl); + _super.prototype.destroy.call(this); + }; + SpreadsheetHeader.prototype.render = function (props) { + var theme = this.theme; + var colSpecs = props.colSpecs; + var html = '<colgroup>' + props.colTags + '</colgroup>' + + '<tbody>'; + if (props.superHeaderText) { + html += + '<tr class="fc-super">' + + '<th class="' + theme.getClass('widgetHeader') + '" colspan="' + colSpecs.length + '">' + + '<div class="fc-cell-content">' + + '<span class="fc-cell-text">' + + core.htmlEscape(props.superHeaderText) + + '</span>' + + '</div>' + + '</th>' + + '</tr>'; + } + html += '<tr>'; + for (var i = 0; i < colSpecs.length; i++) { + var o = colSpecs[i]; + var isLast = i === (colSpecs.length - 1); + html += + "<th class=\"" + theme.getClass('widgetHeader') + "\">" + + '<div>' + + '<div class="fc-cell-content">' + + (o.isMain ? + '<span class="fc-expander-space">' + + '<span class="fc-icon"></span>' + + '</span>' : + '') + + '<span class="fc-cell-text">' + + core.htmlEscape(o.labelText || '') + // what about normalizing this value ahead of time? + '</span>' + + '</div>' + + (!isLast ? '<div class="fc-col-resizer"></div>' : '') + + '</div>' + + '</th>'; + } + html += '</tr>'; + html += '</tbody>'; + this.tableEl.innerHTML = html; + this.thEls = Array.prototype.slice.call(this.tableEl.querySelectorAll('th')); + this.colEls = Array.prototype.slice.call(this.tableEl.querySelectorAll('col')); + this.resizerEls = Array.prototype.slice.call(this.tableEl.querySelectorAll('.fc-col-resizer')); + this.initColResizing(); + }; + SpreadsheetHeader.prototype.initColResizing = function () { + var _this = this; + var ElementDraggingImpl = this.calendar.pluginSystem.hooks.elementDraggingImpl; + if (ElementDraggingImpl) { + this.resizables = this.resizerEls.map(function (handleEl, colIndex) { + var dragging = new ElementDraggingImpl(handleEl); + var startWidth; + dragging.emitter.on('dragstart', function () { + startWidth = _this.colWidths[colIndex]; + if (typeof startWidth !== 'number') { + startWidth = _this.thEls[colIndex].getBoundingClientRect().width; + } + }); + dragging.emitter.on('dragmove', function (pev) { + _this.colWidths[colIndex] = Math.max(startWidth + pev.deltaX * (_this.isRtl ? -1 : 1), COL_MIN_WIDTH); + _this.emitter.trigger('colwidthchange', _this.colWidths); + }); + dragging.setAutoScrollEnabled(false); // because gets weird with auto-scrolling time area + return dragging; + }); + } + }; + return SpreadsheetHeader; + }(core.Component)); + + var Spreadsheet = /** @class */ (function (_super) { + __extends(Spreadsheet, _super); + function Spreadsheet(context, headParentEl, bodyParentEl) { + var _this = _super.call(this, context) || this; + _this._renderCells = core.memoizeRendering(_this.renderCells, _this.unrenderCells); + _this.layout = new TimelinePlugin.HeaderBodyLayout(headParentEl, bodyParentEl, 'clipped-scroll'); + var headerEnhancedScroller = _this.layout.headerScroller.enhancedScroll; + var bodyEnhancedScroller = _this.layout.bodyScroller.enhancedScroll; + _this.header = new SpreadsheetHeader(context, headerEnhancedScroller.canvas.contentEl); + _this.header.emitter.on('colwidthchange', function (colWidths) { + _this.applyColWidths(colWidths); + }); + bodyEnhancedScroller.canvas.contentEl + .appendChild(_this.bodyContainerEl = core.createElement('div', { className: 'fc-rows' }, '<table>' + + '<colgroup />' + + '<tbody />' + + '</table>')); + _this.bodyColGroup = _this.bodyContainerEl.querySelector('colgroup'); + _this.bodyTbody = _this.bodyContainerEl.querySelector('tbody'); + return _this; + } + Spreadsheet.prototype.destroy = function () { + this.header.destroy(); + this.layout.destroy(); + this._renderCells.unrender(); + _super.prototype.destroy.call(this); + }; + Spreadsheet.prototype.render = function (props) { + this._renderCells(props.superHeaderText, props.colSpecs); + }; + Spreadsheet.prototype.renderCells = function (superHeaderText, colSpecs) { + var colTags = this.renderColTags(colSpecs); + this.header.receiveProps({ + superHeaderText: superHeaderText, + colSpecs: colSpecs, + colTags: colTags + }); + this.bodyColGroup.innerHTML = colTags; + this.bodyColEls = Array.prototype.slice.call(this.bodyColGroup.querySelectorAll('col')); + this.applyColWidths(colSpecs.map(function (colSpec) { return colSpec.width; })); + }; + Spreadsheet.prototype.unrenderCells = function () { + this.bodyColGroup.innerHTML = ''; + }; + Spreadsheet.prototype.renderColTags = function (colSpecs) { + var html = ''; + for (var _i = 0, colSpecs_1 = colSpecs; _i < colSpecs_1.length; _i++) { + var o = colSpecs_1[_i]; + if (o.isMain) { + html += '<col class="fc-main-col"/>'; + } + else { + html += '<col/>'; + } + } + return html; + }; + Spreadsheet.prototype.updateSize = function (isResize, totalHeight, isAuto) { + this.layout.setHeight(totalHeight, isAuto); + }; + Spreadsheet.prototype.applyColWidths = function (colWidths) { + var _this = this; + colWidths.forEach(function (colWidth, colIndex) { + var headEl = _this.header.colEls[colIndex]; // bad to access child + var bodyEl = _this.bodyColEls[colIndex]; + var styleVal; + if (typeof colWidth === 'number') { + styleVal = colWidth + 'px'; + } + else if (typeof colWidth == null) { + styleVal = ''; + } + headEl.style.width = bodyEl.style.width = styleVal; + }); + }; + return Spreadsheet; + }(core.Component)); + + var MIN_RESOURCE_AREA_WIDTH = 30; // definitely bigger than scrollbars + var ResourceTimelineView = /** @class */ (function (_super) { + __extends(ResourceTimelineView, _super); + function ResourceTimelineView(context, viewSpec, dateProfileGenerator, parentEl) { + var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this; + _this.isStickyScrollDirty = false; + _this.rowNodes = []; + _this.rowComponents = []; + _this.rowComponentsById = {}; + _this.resourceAreaWidthDraggings = []; + _this.splitter = new ResourceCommonPlugin.ResourceSplitter(); // doesn't let it do businessHours tho + _this.hasResourceBusinessHours = core.memoize(hasResourceBusinessHours); + _this.buildRowNodes = core.memoize(ResourceCommonPlugin.buildRowNodes); + _this.hasNesting = core.memoize(hasNesting); + _this._updateHasNesting = core.memoizeRendering(_this.updateHasNesting); + var allColSpecs = _this.opt('resourceColumns') || []; + var labelText = _this.opt('resourceLabelText'); // TODO: view.override + var defaultLabelText = 'Resources'; // TODO: view.defaults + var superHeaderText = null; + if (!allColSpecs.length) { + allColSpecs.push({ + labelText: labelText || defaultLabelText, + text: ResourceCommonPlugin.buildResourceTextFunc(_this.opt('resourceText'), _this.calendar) + }); + } + else { + superHeaderText = labelText; + } + var plainColSpecs = []; + var groupColSpecs = []; + var groupSpecs = []; + var isVGrouping = false; + var isHGrouping = false; + for (var _i = 0, allColSpecs_1 = allColSpecs; _i < allColSpecs_1.length; _i++) { + var colSpec = allColSpecs_1[_i]; + if (colSpec.group) { + groupColSpecs.push(colSpec); + } + else { + plainColSpecs.push(colSpec); + } + } + plainColSpecs[0].isMain = true; + if (groupColSpecs.length) { + groupSpecs = groupColSpecs; + isVGrouping = true; + } + else { + var hGroupField = _this.opt('resourceGroupField'); + if (hGroupField) { + isHGrouping = true; + groupSpecs.push({ + field: hGroupField, + text: _this.opt('resourceGroupText'), + render: _this.opt('resourceGroupRender') + }); + } + } + var allOrderSpecs = core.parseFieldSpecs(_this.opt('resourceOrder')); + var plainOrderSpecs = []; + for (var _a = 0, allOrderSpecs_1 = allOrderSpecs; _a < allOrderSpecs_1.length; _a++) { + var orderSpec = allOrderSpecs_1[_a]; + var isGroup = false; + for (var _b = 0, groupSpecs_1 = groupSpecs; _b < groupSpecs_1.length; _b++) { + var groupSpec = groupSpecs_1[_b]; + if (groupSpec.field === orderSpec.field) { + groupSpec.order = orderSpec.order; // -1, 0, 1 + isGroup = true; + break; + } + } + if (!isGroup) { + plainOrderSpecs.push(orderSpec); + } + } + _this.superHeaderText = superHeaderText; + _this.isVGrouping = isVGrouping; + _this.isHGrouping = isHGrouping; + _this.groupSpecs = groupSpecs; + _this.colSpecs = groupColSpecs.concat(plainColSpecs); + _this.orderSpecs = plainOrderSpecs; + // START RENDERING... + _this.el.classList.add('fc-timeline'); + if (_this.opt('eventOverlap') === false) { + _this.el.classList.add('fc-no-overlap'); + } + _this.el.innerHTML = _this.renderSkeletonHtml(); + _this.resourceAreaHeadEl = _this.el.querySelector('thead .fc-resource-area'); + _this.setResourceAreaWidth(_this.opt('resourceAreaWidth')); + _this.initResourceAreaWidthDragging(); + _this.miscHeight = _this.el.getBoundingClientRect().height; + _this.spreadsheet = new Spreadsheet(_this.context, _this.resourceAreaHeadEl, _this.el.querySelector('tbody .fc-resource-area')); + _this.timeAxis = new TimelinePlugin.TimeAxis(_this.context, _this.el.querySelector('thead .fc-time-area'), _this.el.querySelector('tbody .fc-time-area')); + var timeAxisRowContainer = core.createElement('div', { className: 'fc-rows' }, '<table><tbody /></table>'); + _this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.contentEl.appendChild(timeAxisRowContainer); + _this.timeAxisTbody = timeAxisRowContainer.querySelector('tbody'); + _this.lane = new TimelinePlugin.TimelineLane(_this.context, null, _this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.bgEl, _this.timeAxis); + _this.bodyScrollJoiner = new TimelinePlugin.ScrollJoiner('vertical', [ + _this.spreadsheet.layout.bodyScroller, + _this.timeAxis.layout.bodyScroller + ]); + // after scrolljoiner + _this.spreadsheetBodyStickyScroller = new TimelinePlugin.StickyScroller(_this.spreadsheet.layout.bodyScroller.enhancedScroll, _this.isRtl, true // isVertical + ); + _this.spreadsheet.receiveProps({ + superHeaderText: _this.superHeaderText, + colSpecs: _this.colSpecs + }); + // Component... + context.calendar.registerInteractiveComponent(_this, { + el: _this.timeAxis.slats.el + }); + return _this; + } + ResourceTimelineView.prototype.renderSkeletonHtml = function () { + var theme = this.theme; + return "<table class=\"" + theme.getClass('tableGrid') + "\"> <thead class=\"fc-head\"> <tr> <td class=\"fc-resource-area " + theme.getClass('widgetHeader') + "\"></td> <td class=\"fc-divider fc-col-resizer " + theme.getClass('widgetHeader') + "\"></td> <td class=\"fc-time-area " + theme.getClass('widgetHeader') + "\"></td> </tr> </thead> <tbody class=\"fc-body\"> <tr> <td class=\"fc-resource-area " + theme.getClass('widgetContent') + "\"></td> <td class=\"fc-divider fc-col-resizer " + theme.getClass('widgetHeader') + "\"></td> <td class=\"fc-time-area " + theme.getClass('widgetContent') + "\"></td> </tr> </tbody> </table>"; + }; + ResourceTimelineView.prototype.render = function (props) { + _super.prototype.render.call(this, props); + var splitProps = this.splitter.splitProps(props); + var hasResourceBusinessHours = this.hasResourceBusinessHours(props.resourceStore); + this.timeAxis.receiveProps({ + dateProfile: props.dateProfile + }); + // for all-resource bg events / selections / business-hours + this.lane.receiveProps(__assign({}, splitProps[''], { dateProfile: props.dateProfile, nextDayThreshold: this.nextDayThreshold, businessHours: hasResourceBusinessHours ? null : props.businessHours })); + var newRowNodes = this.buildRowNodes(props.resourceStore, this.groupSpecs, this.orderSpecs, this.isVGrouping, props.resourceEntityExpansions, this.opt('resourcesInitiallyExpanded')); + this._updateHasNesting(this.hasNesting(newRowNodes)); + this.diffRows(newRowNodes); + this.renderRows(props.dateProfile, hasResourceBusinessHours ? props.businessHours : null, // CONFUSING, comment + splitProps); + }; + ResourceTimelineView.prototype.updateHasNesting = function (isNesting) { + var classList = this.el.classList; + if (isNesting) { + classList.remove('fc-flat'); + } + else { + classList.add('fc-flat'); + } + }; + ResourceTimelineView.prototype.diffRows = function (newNodes) { + var oldNodes = this.rowNodes; + var oldLen = oldNodes.length; + var oldIndexHash = {}; // id -> index + var oldI = 0; + var newI = 0; + for (oldI = 0; oldI < oldLen; oldI++) { + oldIndexHash[oldNodes[oldI].id] = oldI; + } + // iterate new nodes + for (oldI = 0, newI = 0; newI < newNodes.length; newI++) { + var newNode = newNodes[newI]; + var oldIFound = oldIndexHash[newNode.id]; + if (oldIFound != null && oldIFound >= oldI) { + this.removeRows(newI, oldIFound - oldI, oldNodes); // won't do anything if same index + oldI = oldIFound + 1; + } + else { + this.addRow(newI, newNode); + } + } + // old rows that weren't found need to be removed + this.removeRows(newI, oldLen - oldI, oldNodes); // won't do anything if same index + this.rowNodes = newNodes; + }; + /* + rowComponents is the in-progress result + */ + ResourceTimelineView.prototype.addRow = function (index, rowNode) { + var _a = this, rowComponents = _a.rowComponents, rowComponentsById = _a.rowComponentsById; + var nextComponent = rowComponents[index]; + var newComponent = this.buildChildComponent(rowNode, this.spreadsheet.bodyTbody, nextComponent ? nextComponent.spreadsheetTr : null, this.timeAxisTbody, nextComponent ? nextComponent.timeAxisTr : null); + rowComponents.splice(index, 0, newComponent); + rowComponentsById[rowNode.id] = newComponent; + }; + ResourceTimelineView.prototype.removeRows = function (startIndex, len, oldRowNodes) { + if (len) { + var _a = this, rowComponents = _a.rowComponents, rowComponentsById = _a.rowComponentsById; + for (var i = 0; i < len; i++) { + var rowComponent = rowComponents[startIndex + i]; + rowComponent.destroy(); + delete rowComponentsById[oldRowNodes[i].id]; + } + rowComponents.splice(startIndex, len); + } + }; + ResourceTimelineView.prototype.buildChildComponent = function (node, spreadsheetTbody, spreadsheetNext, timeAxisTbody, timeAxisNext) { + if (node.group) { + return new GroupRow(this.context, spreadsheetTbody, spreadsheetNext, timeAxisTbody, timeAxisNext); + } + else if (node.resource) { + return new ResourceRow(this.context, spreadsheetTbody, spreadsheetNext, timeAxisTbody, timeAxisNext, this.timeAxis); + } + }; + ResourceTimelineView.prototype.renderRows = function (dateProfile, fallbackBusinessHours, splitProps) { + var _a = this, rowNodes = _a.rowNodes, rowComponents = _a.rowComponents; + for (var i = 0; i < rowNodes.length; i++) { + var rowNode = rowNodes[i]; + var rowComponent = rowComponents[i]; + if (rowNode.group) { + rowComponent.receiveProps({ + spreadsheetColCnt: this.colSpecs.length, + id: rowNode.id, + isExpanded: rowNode.isExpanded, + group: rowNode.group + }); + } + else { + var resource = rowNode.resource; + rowComponent.receiveProps(__assign({}, splitProps[resource.id], { dateProfile: dateProfile, nextDayThreshold: this.nextDayThreshold, businessHours: resource.businessHours || fallbackBusinessHours, colSpecs: this.colSpecs, id: rowNode.id, rowSpans: rowNode.rowSpans, depth: rowNode.depth, isExpanded: rowNode.isExpanded, hasChildren: rowNode.hasChildren, resource: rowNode.resource })); + } + } + }; + ResourceTimelineView.prototype.updateSize = function (isResize, viewHeight, isAuto) { + // FYI: this ordering is really important + var calendar = this.calendar; + var isBaseSizing = isResize || calendar.isViewUpdated || calendar.isDatesUpdated || calendar.isEventsUpdated; + if (isBaseSizing) { + this.syncHeadHeights(); + this.timeAxis.updateSize(isResize, viewHeight - this.miscHeight, isAuto); + this.spreadsheet.updateSize(isResize, viewHeight - this.miscHeight, isAuto); + } + var rowSizingCnt = this.updateRowSizes(isResize); + this.lane.updateSize(isResize); // is efficient. uses flags + if (isBaseSizing || rowSizingCnt) { + this.bodyScrollJoiner.update(); + this.timeAxis.layout.scrollJoiner.update(); // hack + this.rowPositions = new core.PositionCache(this.timeAxis.slats.el, this.rowComponents.map(function (rowComponent) { + return rowComponent.timeAxisTr; + }), false, // isHorizontal + true // isVertical + ); + this.rowPositions.build(); + this.isStickyScrollDirty = true; + } + }; + ResourceTimelineView.prototype.syncHeadHeights = function () { + var spreadsheetHeadEl = this.spreadsheet.header.tableEl; + var timeAxisHeadEl = this.timeAxis.header.tableEl; + spreadsheetHeadEl.style.height = ''; + timeAxisHeadEl.style.height = ''; + var max = Math.max(spreadsheetHeadEl.getBoundingClientRect().height, timeAxisHeadEl.getBoundingClientRect().height); + spreadsheetHeadEl.style.height = + timeAxisHeadEl.style.height = max + 'px'; + }; + ResourceTimelineView.prototype.updateRowSizes = function (isResize) { + var dirtyRowComponents = this.rowComponents; + if (!isResize) { + dirtyRowComponents = dirtyRowComponents.filter(function (rowComponent) { + return rowComponent.isSizeDirty; + }); + } + var elArrays = dirtyRowComponents.map(function (rowComponent) { + return rowComponent.getHeightEls(); + }); + // reset to natural heights + for (var _i = 0, elArrays_1 = elArrays; _i < elArrays_1.length; _i++) { + var elArray = elArrays_1[_i]; + for (var _a = 0, elArray_1 = elArray; _a < elArray_1.length; _a++) { + var el = elArray_1[_a]; + el.style.height = ''; + } + } + // let rows update their contents' heights + for (var _b = 0, dirtyRowComponents_1 = dirtyRowComponents; _b < dirtyRowComponents_1.length; _b++) { + var rowComponent = dirtyRowComponents_1[_b]; + rowComponent.updateSize(isResize); // will reset isSizeDirty + } + var maxHeights = elArrays.map(function (elArray) { + var maxHeight = null; + for (var _i = 0, elArray_2 = elArray; _i < elArray_2.length; _i++) { + var el = elArray_2[_i]; + var height = el.getBoundingClientRect().height; + if (maxHeight === null || height > maxHeight) { + maxHeight = height; + } + } + return maxHeight; + }); + for (var i = 0; i < elArrays.length; i++) { + for (var _c = 0, _d = elArrays[i]; _c < _d.length; _c++) { + var el = _d[_c]; + el.style.height = maxHeights[i] + 'px'; + } + } + return dirtyRowComponents.length; + }; + ResourceTimelineView.prototype.destroy = function () { + for (var _i = 0, _a = this.rowComponents; _i < _a.length; _i++) { + var rowComponent = _a[_i]; + rowComponent.destroy(); + } + this.rowNodes = []; + this.rowComponents = []; + this.spreadsheet.destroy(); + this.timeAxis.destroy(); + for (var _b = 0, _c = this.resourceAreaWidthDraggings; _b < _c.length; _b++) { + var resourceAreaWidthDragging = _c[_b]; + resourceAreaWidthDragging.destroy(); + } + this.spreadsheetBodyStickyScroller.destroy(); + _super.prototype.destroy.call(this); + this.calendar.unregisterInteractiveComponent(this); + }; + // Now Indicator + // ------------------------------------------------------------------------------------------ + ResourceTimelineView.prototype.getNowIndicatorUnit = function (dateProfile) { + return this.timeAxis.getNowIndicatorUnit(dateProfile); + }; + ResourceTimelineView.prototype.renderNowIndicator = function (date) { + this.timeAxis.renderNowIndicator(date); + }; + ResourceTimelineView.prototype.unrenderNowIndicator = function () { + this.timeAxis.unrenderNowIndicator(); + }; + // Scrolling + // ------------------------------------------------------------------------------------------------------------------ + // this is useful for scrolling prev/next dates while resource is scrolled down + ResourceTimelineView.prototype.queryScroll = function () { + var scroll = _super.prototype.queryScroll.call(this); + if (this.props.resourceStore) { + __assign(scroll, this.queryResourceScroll()); + } + return scroll; + }; + ResourceTimelineView.prototype.applyScroll = function (scroll, isResize) { + _super.prototype.applyScroll.call(this, scroll, isResize); + if (this.props.resourceStore) { + this.applyResourceScroll(scroll); + } + // avoid updating stickyscroll too often + if (isResize || this.isStickyScrollDirty) { + this.isStickyScrollDirty = false; + this.spreadsheetBodyStickyScroller.updateSize(); + this.timeAxis.updateStickyScrollers(); + } + }; + ResourceTimelineView.prototype.computeDateScroll = function (duration) { + return this.timeAxis.computeDateScroll(duration); + }; + ResourceTimelineView.prototype.queryDateScroll = function () { + return this.timeAxis.queryDateScroll(); + }; + ResourceTimelineView.prototype.applyDateScroll = function (scroll) { + this.timeAxis.applyDateScroll(scroll); + }; + ResourceTimelineView.prototype.queryResourceScroll = function () { + var _a = this, rowComponents = _a.rowComponents, rowNodes = _a.rowNodes; + var scroll = {}; + var scrollerTop = this.timeAxis.layout.bodyScroller.el.getBoundingClientRect().top; // fixed position + for (var i = 0; i < rowComponents.length; i++) { + var rowComponent = rowComponents[i]; + var rowNode = rowNodes[i]; + var el = rowComponent.timeAxisTr; + var elBottom = el.getBoundingClientRect().bottom; // fixed position + if (elBottom > scrollerTop) { + scroll.rowId = rowNode.id; + scroll.bottom = elBottom - scrollerTop; + break; + } + } + // TODO: what about left scroll state for spreadsheet area? + return scroll; + }; + ResourceTimelineView.prototype.applyResourceScroll = function (scroll) { + var rowId = scroll.forcedRowId || scroll.rowId; + if (rowId) { + var rowComponent = this.rowComponentsById[rowId]; + if (rowComponent) { + var el = rowComponent.timeAxisTr; + if (el) { + var innerTop = this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.el.getBoundingClientRect().top; + var rowRect = el.getBoundingClientRect(); + var scrollTop = (scroll.forcedRowId ? + rowRect.top : // just use top edge + rowRect.bottom - scroll.bottom) - // pixels from bottom edge + innerTop; + this.timeAxis.layout.bodyScroller.enhancedScroll.setScrollTop(scrollTop); + this.spreadsheet.layout.bodyScroller.enhancedScroll.setScrollTop(scrollTop); + } + } + } + }; + // TODO: scrollToResource + // Hit System + // ------------------------------------------------------------------------------------------ + ResourceTimelineView.prototype.buildPositionCaches = function () { + this.timeAxis.slats.updateSize(); + this.rowPositions.build(); + }; + ResourceTimelineView.prototype.queryHit = function (positionLeft, positionTop) { + var rowPositions = this.rowPositions; + var slats = this.timeAxis.slats; + var rowIndex = rowPositions.topToIndex(positionTop); + if (rowIndex != null) { + var resource = this.rowNodes[rowIndex].resource; + if (resource) { // not a group + var slatHit = slats.positionToHit(positionLeft); + if (slatHit) { + return { + component: this, + dateSpan: { + range: slatHit.dateSpan.range, + allDay: slatHit.dateSpan.allDay, + resourceId: resource.id + }, + rect: { + left: slatHit.left, + right: slatHit.right, + top: rowPositions.tops[rowIndex], + bottom: rowPositions.bottoms[rowIndex] + }, + dayEl: slatHit.dayEl, + layer: 0 + }; + } + } + } + }; + // Resource Area + // ------------------------------------------------------------------------------------------------------------------ + ResourceTimelineView.prototype.setResourceAreaWidth = function (widthVal) { + this.resourceAreaWidth = widthVal; + core.applyStyleProp(this.resourceAreaHeadEl, 'width', widthVal || ''); + }; + ResourceTimelineView.prototype.initResourceAreaWidthDragging = function () { + var _this = this; + var resourceAreaDividerEls = Array.prototype.slice.call(this.el.querySelectorAll('.fc-col-resizer')); + var ElementDraggingImpl = this.calendar.pluginSystem.hooks.elementDraggingImpl; + if (ElementDraggingImpl) { + this.resourceAreaWidthDraggings = resourceAreaDividerEls.map(function (el) { + var dragging = new ElementDraggingImpl(el); + var dragStartWidth; + var viewWidth; + dragging.emitter.on('dragstart', function () { + dragStartWidth = _this.resourceAreaWidth; + if (typeof dragStartWidth !== 'number') { + dragStartWidth = _this.resourceAreaHeadEl.getBoundingClientRect().width; + } + viewWidth = _this.el.getBoundingClientRect().width; + }); + dragging.emitter.on('dragmove', function (pev) { + var newWidth = dragStartWidth + pev.deltaX * (_this.isRtl ? -1 : 1); + newWidth = Math.max(newWidth, MIN_RESOURCE_AREA_WIDTH); + newWidth = Math.min(newWidth, viewWidth - MIN_RESOURCE_AREA_WIDTH); + _this.setResourceAreaWidth(newWidth); + }); + dragging.setAutoScrollEnabled(false); // because gets weird with auto-scrolling time area + return dragging; + }); + } + }; + ResourceTimelineView.needsResourceData = true; // for ResourceViewProps + return ResourceTimelineView; + }(core.View)); + function hasResourceBusinessHours(resourceStore) { + for (var resourceId in resourceStore) { + var resource = resourceStore[resourceId]; + if (resource.businessHours) { + return true; + } + } + return false; + } + function hasNesting(nodes) { + for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) { + var node = nodes_1[_i]; + if (node.group) { + return true; + } + else if (node.resource) { + if (node.hasChildren) { + return true; + } + } + } + return false; + } + + var main = core.createPlugin({ + deps: [ResourceCommonPlugin__default, TimelinePlugin__default], + defaultView: 'resourceTimelineDay', + views: { + resourceTimeline: { + class: ResourceTimelineView, + resourceAreaWidth: '30%', + resourcesInitiallyExpanded: true, + eventResizableFromStart: true // TODO: not DRY with this same setting in the main timeline config + }, + resourceTimelineDay: { + type: 'resourceTimeline', + duration: { days: 1 } + }, + resourceTimelineWeek: { + type: 'resourceTimeline', + duration: { weeks: 1 } + }, + resourceTimelineMonth: { + type: 'resourceTimeline', + duration: { months: 1 } + }, + resourceTimelineYear: { + type: 'resourceTimeline', + duration: { years: 1 } + } + } + }); + + exports.ResourceTimelineView = ResourceTimelineView; + exports.default = main; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.min.css b/AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.min.css new file mode 100644 index 00000000..a365c608 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.min.css @@ -0,0 +1 @@ +.fc-timeline .fc-divider{width:3px;border-style:double}.fc-timeline .fc-head>tr>.fc-divider{border-bottom:0}.fc-timeline .fc-body>tr>.fc-divider{border-top:0}.fc-resource-area{width:30%}.fc-resource-area col{width:40%;min-width:70px}.fc-resource-area col.fc-main-col{width:60%}.fc-flat .fc-expander-space{display:none}.fc-ltr .fc-resource-area tr>*{text-align:left}.fc-rtl .fc-resource-area tr>*{text-align:right}.fc-resource-area .fc-cell-content{padding-left:4px;padding-right:4px}.fc-resource-area .fc-super th{text-align:center}.fc-resource-area th>div{position:relative}.fc-resource-area th .fc-cell-content{position:relative;z-index:1}.fc-resource-area th .fc-col-resizer{position:absolute;z-index:2;top:0;bottom:0;width:5px}.fc-timeline .fc-col-resizer{cursor:col-resize}.fc-ltr .fc-resource-area th .fc-col-resizer{right:-3px}.fc-rtl .fc-resource-area th .fc-col-resizer{left:-3px}.fc-body .fc-resource-area .fc-cell-content{padding-top:8px;padding-bottom:8px}.fc-no-overlap .fc-body .fc-resource-area .fc-cell-content{padding-top:6px;padding-bottom:6px}.fc-resource-area .fc-icon{display:inline-block;width:1em;text-align:center}.fc-resource-area .fc-expander{cursor:pointer;opacity:.65}.fc-time-area .fc-rows{position:relative;z-index:3}.fc-time-area .fc-rows td>div{position:relative}.fc-time-area .fc-rows .fc-bgevent-container,.fc-time-area .fc-rows .fc-highlight-container{z-index:1} \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.min.js b/AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.min.js new file mode 100644 index 00000000..c3467bff --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-timeline/main.min.js @@ -0,0 +1,6 @@ +/*! +FullCalendar Resource Timeline Plugin v4.3.0 +Docs & License: https://fullcalendar.io/scheduler +(c) 2019 Adam Shaw +*/ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@fullcalendar/core"),require("@fullcalendar/timeline"),require("@fullcalendar/resource-common")):"function"==typeof define&&define.amd?define(["exports","@fullcalendar/core","@fullcalendar/timeline","@fullcalendar/resource-common"],t):t((e=e||self).FullCalendarResourceTimeline={},e.FullCalendar,e.FullCalendarTimeline,e.FullCalendarResourceCommon)}(this,function(e,t,r,o){"use strict";var i="default"in r?r.default:r,s="default"in o?o.default:o,n=function(e,t){return(n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)};function l(e,t){function r(){this.constructor=e}n(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}var a=function(){return(a=Object.assign||function(e){for(var t,r=1,o=arguments.length;r<o;r++)for(var i in t=arguments[r])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},c=function(e){function r(t,r,o,i,s){var n=e.call(this,t)||this;return n.isSizeDirty=!1,r.insertBefore(n.spreadsheetTr=document.createElement("tr"),o),i.insertBefore(n.timeAxisTr=document.createElement("tr"),s),n}return l(r,e),r.prototype.destroy=function(){t.removeElement(this.spreadsheetTr),t.removeElement(this.timeAxisTr),e.prototype.destroy.call(this)},r.prototype.updateSize=function(e){this.isSizeDirty=!1},r}(t.Component);function d(e,t){var r=e.classList;t?(r.remove("fc-icon-plus-square"),r.add("fc-icon-minus-square")):(r.remove("fc-icon-minus-square"),r.add("fc-icon-plus-square"))}function p(e,t){e.setAttribute("data-resource-id",t)}var u=function(e){function r(){var r=null!==e&&e.apply(this,arguments)||this;return r._renderCells=t.memoizeRendering(r.renderCells,r.unrenderCells),r._updateExpanderIcon=t.memoizeRendering(r.updateExpanderIcon,null,[r._renderCells]),r.onExpanderClick=function(e){var t=r.props;r.calendar.dispatch({type:"SET_RESOURCE_ENTITY_EXPANDED",id:t.id,isExpanded:!t.isExpanded})},r}return l(r,e),r.prototype.render=function(e){this._renderCells(e.group,e.spreadsheetColCnt),this._updateExpanderIcon(e.isExpanded),this.isSizeDirty=!0},r.prototype.destroy=function(){e.prototype.destroy.call(this),this._renderCells.unrender()},r.prototype.renderCells=function(e,r){var o=this.renderSpreadsheetContent(e);this.spreadsheetTr.appendChild(t.createElement("td",{className:"fc-divider",colSpan:r},this.spreadsheetHeightEl=t.createElement("div",null,o))),this.expanderIconEl=o.querySelector(".fc-icon"),this.expanderIconEl.parentElement.addEventListener("click",this.onExpanderClick),this.timeAxisTr.appendChild(t.createElement("td",{className:"fc-divider"},this.timeAxisHeightEl=document.createElement("div")))},r.prototype.unrenderCells=function(){this.spreadsheetTr.innerHTML="",this.timeAxisTr.innerHTML=""},r.prototype.renderSpreadsheetContent=function(e){var r=this.renderCellText(e),o=t.htmlToElement('<div class="fc-cell-content"><span class="fc-expander"><span class="fc-icon"></span></span><span class="fc-cell-text">'+(r?t.htmlEscape(r):" ")+"</span></div>"),i=e.spec.render;return"function"==typeof i&&(o=i(o,e.value)||o),o},r.prototype.renderCellText=function(e){var t=e.value||"",r=e.spec.text;return"function"==typeof r&&(t=r(t)||t),t},r.prototype.getHeightEls=function(){return[this.spreadsheetHeightEl,this.timeAxisHeightEl]},r.prototype.updateExpanderIcon=function(e){d(this.expanderIconEl,e)},r}(c);u.addEqualityFuncs({group:o.isGroupsEqual});var h=function(e){function r(r,o){var i=e.call(this,r)||this;return i._renderRow=t.memoizeRendering(i.renderRow,i.unrenderRow),i._updateTrResourceId=t.memoizeRendering(p,null,[i._renderRow]),i._updateExpanderIcon=t.memoizeRendering(i.updateExpanderIcon,null,[i._renderRow]),i.onExpanderClick=function(e){var t=i.props;i.calendar.dispatch({type:"SET_RESOURCE_ENTITY_EXPANDED",id:t.id,isExpanded:!t.isExpanded})},i.tr=o,i}return l(r,e),r.prototype.render=function(e){this._renderRow(e.resource,e.rowSpans,e.depth,e.colSpecs),this._updateTrResourceId(this.tr,e.resource.id),this._updateExpanderIcon(e.hasChildren,e.isExpanded)},r.prototype.destroy=function(){e.prototype.destroy.call(this),this._renderRow.unrender()},r.prototype.renderRow=function(e,r,i,s){for(var n,l=this.tr,a=this.theme,c=this.calendar,d=this.view,p=o.buildResourceFields(e),u=0;u<s.length;u++){var h=s[u],f=r[u];if(0!==f){null==f&&(f=1);var m=void 0;m=h.field?p[h.field]:o.buildResourceTextFunc(h.text,c)(e);var g=t.htmlToElement('<div class="fc-cell-content">'+(h.isMain?y(i):"")+'<span class="fc-cell-text">'+(m?t.htmlEscape(m):" ")+"</span></div>");"function"==typeof h.render&&(g=h.render(new o.ResourceApi(c,e),g)||g),f>1&&g.classList.add("fc-sticky");var v=t.createElement("td",{className:a.getClass("widgetContent"),rowspan:f},g);h.isMain&&(v.appendChild(this.heightEl=t.createElement("div",null,v.childNodes)),n=v),l.appendChild(v)}}this.expanderIconEl=l.querySelector(".fc-expander-space .fc-icon"),d.publiclyTrigger("resourceRender",[{resource:new o.ResourceApi(c,e),el:n,view:d}])},r.prototype.unrenderRow=function(){this.tr.innerHTML=""},r.prototype.updateExpanderIcon=function(e,t){var r,o=this.expanderIconEl,i=o.parentElement;o&&i&&(e?(i.addEventListener("click",this.onExpanderClick),i.classList.add("fc-expander"),d(o,t)):(i.removeEventListener("click",this.onExpanderClick),i.classList.remove("fc-expander"),(r=o.classList).remove("fc-icon-minus-square"),r.remove("fc-icon-plus-square")))},r}(t.Component);function y(e){for(var t="",r=0;r<e;r++)t+='<span class="fc-icon"></span>';return t+='<span class="fc-expander-space"><span class="fc-icon"></span></span>'}var f=function(e){function o(o,i,s,n,l,a){var c=e.call(this,o,i,s,n,l)||this;return c._updateTrResourceId=t.memoizeRendering(p),c.spreadsheetRow=new h(o,c.spreadsheetTr),c.timeAxisTr.appendChild(t.createElement("td",{className:c.theme.getClass("widgetContent")},c.innerContainerEl=document.createElement("div"))),c.lane=new r.TimelineLane(o,c.innerContainerEl,c.innerContainerEl,a),c}return l(o,e),o.prototype.destroy=function(){this.spreadsheetRow.destroy(),this.lane.destroy(),e.prototype.destroy.call(this)},o.prototype.render=function(e){this.spreadsheetRow.receiveProps({colSpecs:e.colSpecs,id:e.id,rowSpans:e.rowSpans,depth:e.depth,isExpanded:e.isExpanded,hasChildren:e.hasChildren,resource:e.resource}),this._updateTrResourceId(this.timeAxisTr,e.resource.id),this.lane.receiveProps({dateProfile:e.dateProfile,nextDayThreshold:e.nextDayThreshold,businessHours:e.businessHours,eventStore:e.eventStore,eventUiBases:e.eventUiBases,dateSelection:e.dateSelection,eventSelection:e.eventSelection,eventDrag:e.eventDrag,eventResize:e.eventResize}),this.isSizeDirty=!0},o.prototype.updateSize=function(t){e.prototype.updateSize.call(this,t),this.lane.updateSize(t)},o.prototype.getHeightEls=function(){return[this.spreadsheetRow.heightEl,this.innerContainerEl]},o}(c);f.addEqualityFuncs({rowSpans:t.isArraysEqual});var m=function(e){function r(r,o){var i=e.call(this,r)||this;return i.resizables=[],i.colWidths=[],i.emitter=new t.EmitterMixin,o.appendChild(i.tableEl=t.createElement("table",{className:i.theme.getClass("tableGrid")})),i}return l(r,e),r.prototype.destroy=function(){for(var r=0,o=this.resizables;r<o.length;r++){o[r].destroy()}t.removeElement(this.tableEl),e.prototype.destroy.call(this)},r.prototype.render=function(e){var r=this.theme,o=e.colSpecs,i="<colgroup>"+e.colTags+"</colgroup><tbody>";e.superHeaderText&&(i+='<tr class="fc-super"><th class="'+r.getClass("widgetHeader")+'" colspan="'+o.length+'"><div class="fc-cell-content"><span class="fc-cell-text">'+t.htmlEscape(e.superHeaderText)+"</span></div></th></tr>"),i+="<tr>";for(var s=0;s<o.length;s++){var n=o[s],l=s===o.length-1;i+='<th class="'+r.getClass("widgetHeader")+'"><div><div class="fc-cell-content">'+(n.isMain?'<span class="fc-expander-space"><span class="fc-icon"></span></span>':"")+'<span class="fc-cell-text">'+t.htmlEscape(n.labelText||"")+"</span></div>"+(l?"":'<div class="fc-col-resizer"></div>')+"</div></th>"}i+="</tr>",i+="</tbody>",this.tableEl.innerHTML=i,this.thEls=Array.prototype.slice.call(this.tableEl.querySelectorAll("th")),this.colEls=Array.prototype.slice.call(this.tableEl.querySelectorAll("col")),this.resizerEls=Array.prototype.slice.call(this.tableEl.querySelectorAll(".fc-col-resizer")),this.initColResizing()},r.prototype.initColResizing=function(){var e=this,t=this.calendar.pluginSystem.hooks.elementDraggingImpl;t&&(this.resizables=this.resizerEls.map(function(r,o){var i,s=new t(r);return s.emitter.on("dragstart",function(){"number"!=typeof(i=e.colWidths[o])&&(i=e.thEls[o].getBoundingClientRect().width)}),s.emitter.on("dragmove",function(t){e.colWidths[o]=Math.max(i+t.deltaX*(e.isRtl?-1:1),30),e.emitter.trigger("colwidthchange",e.colWidths)}),s.setAutoScrollEnabled(!1),s}))},r}(t.Component),g=function(e){function o(o,i,s){var n=e.call(this,o)||this;n._renderCells=t.memoizeRendering(n.renderCells,n.unrenderCells),n.layout=new r.HeaderBodyLayout(i,s,"clipped-scroll");var l=n.layout.headerScroller.enhancedScroll,a=n.layout.bodyScroller.enhancedScroll;return n.header=new m(o,l.canvas.contentEl),n.header.emitter.on("colwidthchange",function(e){n.applyColWidths(e)}),a.canvas.contentEl.appendChild(n.bodyContainerEl=t.createElement("div",{className:"fc-rows"},"<table><colgroup /><tbody /></table>")),n.bodyColGroup=n.bodyContainerEl.querySelector("colgroup"),n.bodyTbody=n.bodyContainerEl.querySelector("tbody"),n}return l(o,e),o.prototype.destroy=function(){this.header.destroy(),this.layout.destroy(),this._renderCells.unrender(),e.prototype.destroy.call(this)},o.prototype.render=function(e){this._renderCells(e.superHeaderText,e.colSpecs)},o.prototype.renderCells=function(e,t){var r=this.renderColTags(t);this.header.receiveProps({superHeaderText:e,colSpecs:t,colTags:r}),this.bodyColGroup.innerHTML=r,this.bodyColEls=Array.prototype.slice.call(this.bodyColGroup.querySelectorAll("col")),this.applyColWidths(t.map(function(e){return e.width}))},o.prototype.unrenderCells=function(){this.bodyColGroup.innerHTML=""},o.prototype.renderColTags=function(e){for(var t="",r=0,o=e;r<o.length;r++){o[r].isMain?t+='<col class="fc-main-col"/>':t+="<col/>"}return t},o.prototype.updateSize=function(e,t,r){this.layout.setHeight(t,r)},o.prototype.applyColWidths=function(e){var t=this;e.forEach(function(e,r){var o,i=t.header.colEls[r],s=t.bodyColEls[r];"number"==typeof e?o=e+"px":null==typeof e&&(o=""),i.style.width=s.style.width=o})},o}(t.Component),v=function(e){function i(i,s,n,l){var a=e.call(this,i,s,n,l)||this;a.isStickyScrollDirty=!1,a.rowNodes=[],a.rowComponents=[],a.rowComponentsById={},a.resourceAreaWidthDraggings=[],a.splitter=new o.ResourceSplitter,a.hasResourceBusinessHours=t.memoize(S),a.buildRowNodes=t.memoize(o.buildRowNodes),a.hasNesting=t.memoize(x),a._updateHasNesting=t.memoizeRendering(a.updateHasNesting);var c=a.opt("resourceColumns")||[],d=a.opt("resourceLabelText"),p=null;c.length?p=d:c.push({labelText:d||"Resources",text:o.buildResourceTextFunc(a.opt("resourceText"),a.calendar)});for(var u=[],h=[],y=[],f=!1,m=!1,v=0,E=c;v<E.length;v++){var C=E[v];C.group?h.push(C):u.push(C)}if(u[0].isMain=!0,h.length)y=h,f=!0;else{var w=a.opt("resourceGroupField");w&&(m=!0,y.push({field:w,text:a.opt("resourceGroupText"),render:a.opt("resourceGroupRender")}))}for(var b=[],R=0,T=t.parseFieldSpecs(a.opt("resourceOrder"));R<T.length;R++){for(var A=T[R],H=!1,z=0,I=y;z<I.length;z++){var D=I[z];if(D.field===A.field){D.order=A.order,H=!0;break}}H||b.push(A)}a.superHeaderText=p,a.isVGrouping=f,a.isHGrouping=m,a.groupSpecs=y,a.colSpecs=h.concat(u),a.orderSpecs=b,a.el.classList.add("fc-timeline"),!1===a.opt("eventOverlap")&&a.el.classList.add("fc-no-overlap"),a.el.innerHTML=a.renderSkeletonHtml(),a.resourceAreaHeadEl=a.el.querySelector("thead .fc-resource-area"),a.setResourceAreaWidth(a.opt("resourceAreaWidth")),a.initResourceAreaWidthDragging(),a.miscHeight=a.el.getBoundingClientRect().height,a.spreadsheet=new g(a.context,a.resourceAreaHeadEl,a.el.querySelector("tbody .fc-resource-area")),a.timeAxis=new r.TimeAxis(a.context,a.el.querySelector("thead .fc-time-area"),a.el.querySelector("tbody .fc-time-area"));var _=t.createElement("div",{className:"fc-rows"},"<table><tbody /></table>");return a.timeAxis.layout.bodyScroller.enhancedScroll.canvas.contentEl.appendChild(_),a.timeAxisTbody=_.querySelector("tbody"),a.lane=new r.TimelineLane(a.context,null,a.timeAxis.layout.bodyScroller.enhancedScroll.canvas.bgEl,a.timeAxis),a.bodyScrollJoiner=new r.ScrollJoiner("vertical",[a.spreadsheet.layout.bodyScroller,a.timeAxis.layout.bodyScroller]),a.spreadsheetBodyStickyScroller=new r.StickyScroller(a.spreadsheet.layout.bodyScroller.enhancedScroll,a.isRtl,!0),a.spreadsheet.receiveProps({superHeaderText:a.superHeaderText,colSpecs:a.colSpecs}),i.calendar.registerInteractiveComponent(a,{el:a.timeAxis.slats.el}),a}return l(i,e),i.prototype.renderSkeletonHtml=function(){var e=this.theme;return'<table class="'+e.getClass("tableGrid")+'"> <thead class="fc-head"> <tr> <td class="fc-resource-area '+e.getClass("widgetHeader")+'"></td> <td class="fc-divider fc-col-resizer '+e.getClass("widgetHeader")+'"></td> <td class="fc-time-area '+e.getClass("widgetHeader")+'"></td> </tr> </thead> <tbody class="fc-body"> <tr> <td class="fc-resource-area '+e.getClass("widgetContent")+'"></td> <td class="fc-divider fc-col-resizer '+e.getClass("widgetHeader")+'"></td> <td class="fc-time-area '+e.getClass("widgetContent")+'"></td> </tr> </tbody> </table>'},i.prototype.render=function(t){e.prototype.render.call(this,t);var r=this.splitter.splitProps(t),o=this.hasResourceBusinessHours(t.resourceStore);this.timeAxis.receiveProps({dateProfile:t.dateProfile}),this.lane.receiveProps(a({},r[""],{dateProfile:t.dateProfile,nextDayThreshold:this.nextDayThreshold,businessHours:o?null:t.businessHours}));var i=this.buildRowNodes(t.resourceStore,this.groupSpecs,this.orderSpecs,this.isVGrouping,t.resourceEntityExpansions,this.opt("resourcesInitiallyExpanded"));this._updateHasNesting(this.hasNesting(i)),this.diffRows(i),this.renderRows(t.dateProfile,o?t.businessHours:null,r)},i.prototype.updateHasNesting=function(e){var t=this.el.classList;e?t.remove("fc-flat"):t.add("fc-flat")},i.prototype.diffRows=function(e){var t=this.rowNodes,r=t.length,o={},i=0,s=0;for(i=0;i<r;i++)o[t[i].id]=i;for(i=0,s=0;s<e.length;s++){var n=e[s],l=o[n.id];null!=l&&l>=i?(this.removeRows(s,l-i,t),i=l+1):this.addRow(s,n)}this.removeRows(s,r-i,t),this.rowNodes=e},i.prototype.addRow=function(e,t){var r=this.rowComponents,o=this.rowComponentsById,i=r[e],s=this.buildChildComponent(t,this.spreadsheet.bodyTbody,i?i.spreadsheetTr:null,this.timeAxisTbody,i?i.timeAxisTr:null);r.splice(e,0,s),o[t.id]=s},i.prototype.removeRows=function(e,t,r){if(t){for(var o=this.rowComponents,i=this.rowComponentsById,s=0;s<t;s++){o[e+s].destroy(),delete i[r[s].id]}o.splice(e,t)}},i.prototype.buildChildComponent=function(e,t,r,o,i){return e.group?new u(this.context,t,r,o,i):e.resource?new f(this.context,t,r,o,i,this.timeAxis):void 0},i.prototype.renderRows=function(e,t,r){for(var o=this.rowNodes,i=this.rowComponents,s=0;s<o.length;s++){var n=o[s],l=i[s];if(n.group)l.receiveProps({spreadsheetColCnt:this.colSpecs.length,id:n.id,isExpanded:n.isExpanded,group:n.group});else{var c=n.resource;l.receiveProps(a({},r[c.id],{dateProfile:e,nextDayThreshold:this.nextDayThreshold,businessHours:c.businessHours||t,colSpecs:this.colSpecs,id:n.id,rowSpans:n.rowSpans,depth:n.depth,isExpanded:n.isExpanded,hasChildren:n.hasChildren,resource:n.resource}))}}},i.prototype.updateSize=function(e,r,o){var i=this.calendar,s=e||i.isViewUpdated||i.isDatesUpdated||i.isEventsUpdated;s&&(this.syncHeadHeights(),this.timeAxis.updateSize(e,r-this.miscHeight,o),this.spreadsheet.updateSize(e,r-this.miscHeight,o));var n=this.updateRowSizes(e);this.lane.updateSize(e),(s||n)&&(this.bodyScrollJoiner.update(),this.timeAxis.layout.scrollJoiner.update(),this.rowPositions=new t.PositionCache(this.timeAxis.slats.el,this.rowComponents.map(function(e){return e.timeAxisTr}),!1,!0),this.rowPositions.build(),this.isStickyScrollDirty=!0)},i.prototype.syncHeadHeights=function(){var e=this.spreadsheet.header.tableEl,t=this.timeAxis.header.tableEl;e.style.height="",t.style.height="";var r=Math.max(e.getBoundingClientRect().height,t.getBoundingClientRect().height);e.style.height=t.style.height=r+"px"},i.prototype.updateRowSizes=function(e){var t=this.rowComponents;e||(t=t.filter(function(e){return e.isSizeDirty}));for(var r=t.map(function(e){return e.getHeightEls()}),o=0,i=r;o<i.length;o++)for(var s=0,n=i[o];s<n.length;s++){n[s].style.height=""}for(var l=0,a=t;l<a.length;l++){a[l].updateSize(e)}for(var c=r.map(function(e){for(var t=null,r=0,o=e;r<o.length;r++){var i=o[r].getBoundingClientRect().height;(null===t||i>t)&&(t=i)}return t}),d=0;d<r.length;d++)for(var p=0,u=r[d];p<u.length;p++){u[p].style.height=c[d]+"px"}return t.length},i.prototype.destroy=function(){for(var t=0,r=this.rowComponents;t<r.length;t++){r[t].destroy()}this.rowNodes=[],this.rowComponents=[],this.spreadsheet.destroy(),this.timeAxis.destroy();for(var o=0,i=this.resourceAreaWidthDraggings;o<i.length;o++){i[o].destroy()}this.spreadsheetBodyStickyScroller.destroy(),e.prototype.destroy.call(this),this.calendar.unregisterInteractiveComponent(this)},i.prototype.getNowIndicatorUnit=function(e){return this.timeAxis.getNowIndicatorUnit(e)},i.prototype.renderNowIndicator=function(e){this.timeAxis.renderNowIndicator(e)},i.prototype.unrenderNowIndicator=function(){this.timeAxis.unrenderNowIndicator()},i.prototype.queryScroll=function(){var t=e.prototype.queryScroll.call(this);return this.props.resourceStore&&a(t,this.queryResourceScroll()),t},i.prototype.applyScroll=function(t,r){e.prototype.applyScroll.call(this,t,r),this.props.resourceStore&&this.applyResourceScroll(t),(r||this.isStickyScrollDirty)&&(this.isStickyScrollDirty=!1,this.spreadsheetBodyStickyScroller.updateSize(),this.timeAxis.updateStickyScrollers())},i.prototype.computeDateScroll=function(e){return this.timeAxis.computeDateScroll(e)},i.prototype.queryDateScroll=function(){return this.timeAxis.queryDateScroll()},i.prototype.applyDateScroll=function(e){this.timeAxis.applyDateScroll(e)},i.prototype.queryResourceScroll=function(){for(var e=this.rowComponents,t=this.rowNodes,r={},o=this.timeAxis.layout.bodyScroller.el.getBoundingClientRect().top,i=0;i<e.length;i++){var s=e[i],n=t[i],l=s.timeAxisTr.getBoundingClientRect().bottom;if(l>o){r.rowId=n.id,r.bottom=l-o;break}}return r},i.prototype.applyResourceScroll=function(e){var t=e.forcedRowId||e.rowId;if(t){var r=this.rowComponentsById[t];if(r){var o=r.timeAxisTr;if(o){var i=this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.el.getBoundingClientRect().top,s=o.getBoundingClientRect(),n=(e.forcedRowId?s.top:s.bottom-e.bottom)-i;this.timeAxis.layout.bodyScroller.enhancedScroll.setScrollTop(n),this.spreadsheet.layout.bodyScroller.enhancedScroll.setScrollTop(n)}}}},i.prototype.buildPositionCaches=function(){this.timeAxis.slats.updateSize(),this.rowPositions.build()},i.prototype.queryHit=function(e,t){var r=this.rowPositions,o=this.timeAxis.slats,i=r.topToIndex(t);if(null!=i){var s=this.rowNodes[i].resource;if(s){var n=o.positionToHit(e);if(n)return{component:this,dateSpan:{range:n.dateSpan.range,allDay:n.dateSpan.allDay,resourceId:s.id},rect:{left:n.left,right:n.right,top:r.tops[i],bottom:r.bottoms[i]},dayEl:n.dayEl,layer:0}}}},i.prototype.setResourceAreaWidth=function(e){this.resourceAreaWidth=e,t.applyStyleProp(this.resourceAreaHeadEl,"width",e||"")},i.prototype.initResourceAreaWidthDragging=function(){var e=this,t=Array.prototype.slice.call(this.el.querySelectorAll(".fc-col-resizer")),r=this.calendar.pluginSystem.hooks.elementDraggingImpl;r&&(this.resourceAreaWidthDraggings=t.map(function(t){var o,i,s=new r(t);return s.emitter.on("dragstart",function(){"number"!=typeof(o=e.resourceAreaWidth)&&(o=e.resourceAreaHeadEl.getBoundingClientRect().width),i=e.el.getBoundingClientRect().width}),s.emitter.on("dragmove",function(t){var r=o+t.deltaX*(e.isRtl?-1:1);r=Math.max(r,30),r=Math.min(r,i-30),e.setResourceAreaWidth(r)}),s.setAutoScrollEnabled(!1),s}))},i.needsResourceData=!0,i}(t.View);function S(e){for(var t in e){if(e[t].businessHours)return!0}return!1}function x(e){for(var t=0,r=e;t<r.length;t++){var o=r[t];if(o.group)return!0;if(o.resource&&o.hasChildren)return!0}return!1}var E=t.createPlugin({deps:[s,i],defaultView:"resourceTimelineDay",views:{resourceTimeline:{class:v,resourceAreaWidth:"30%",resourcesInitiallyExpanded:!0,eventResizableFromStart:!0},resourceTimelineDay:{type:"resourceTimeline",duration:{days:1}},resourceTimelineWeek:{type:"resourceTimeline",duration:{weeks:1}},resourceTimelineMonth:{type:"resourceTimeline",duration:{months:1}},resourceTimelineYear:{type:"resourceTimeline",duration:{years:1}}}});e.ResourceTimelineView=v,e.default=E,Object.defineProperty(e,"__esModule",{value:!0})}); \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/resource-timeline/package.json b/AKPlan/static/AKPlan/fullcalendar/resource-timeline/package.json new file mode 100644 index 00000000..75c1775f --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/resource-timeline/package.json @@ -0,0 +1,37 @@ +{ + "name": "@fullcalendar/resource-timeline", + "version": "4.3.0", + "title": "FullCalendar Resource Timeline Plugin", + "description": "Display events and resources on a horizontal time axis", + "keywords": [ + "calendar", + "event", + "full-sized" + ], + "homepage": "https://fullcalendar.io/scheduler", + "docs": "https://fullcalendar.io/docs/timeline-view", + "bugs": "https://fullcalendar.io/reporting-bugs", + "repository": { + "type": "git", + "url": "https://github.com/fullcalendar/fullcalendar-scheduler.git", + "homepage": "https://github.com/fullcalendar/fullcalendar-scheduler" + }, + "license": "SEE LICENSE IN LICENSE.md", + "author": { + "name": "Adam Shaw", + "email": "arshaw@arshaw.com", + "url": "http://arshaw.com/" + }, + "copyright": "2019 Adam Shaw", + "dependencies": { + "@fullcalendar/resource-common": "~4.3.0", + "@fullcalendar/timeline": "~4.3.0" + }, + "peerDependencies": { + "@fullcalendar/core": "~4.3.0" + }, + "main": "main.js", + "module": "main.esm.js", + "unpkg": "main.min.js", + "types": "main.d.ts" +} diff --git a/AKPlan/static/AKPlan/fullcalendar/rrule/LICENSE.txt b/AKPlan/static/AKPlan/fullcalendar/rrule/LICENSE.txt new file mode 100644 index 00000000..2149cfbe --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/rrule/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2019 Adam Shaw + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/AKPlan/static/AKPlan/fullcalendar/rrule/README.md b/AKPlan/static/AKPlan/fullcalendar/rrule/README.md new file mode 100644 index 00000000..7b56bed7 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/rrule/README.md @@ -0,0 +1,8 @@ + +# FullCalendar RRule Plugin + +A connector to the RRule library, for recurring events + +[View the docs »](https://fullcalendar.io/docs/rrule-plugin) + +This package was created from the [FullCalendar monorepo »](https://github.com/fullcalendar/fullcalendar) diff --git a/AKPlan/static/AKPlan/fullcalendar/rrule/main.d.ts b/AKPlan/static/AKPlan/fullcalendar/rrule/main.d.ts new file mode 100644 index 00000000..8ce74e97 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/rrule/main.d.ts @@ -0,0 +1,9 @@ +// Generated by dts-bundle v0.7.3-fork.1 +// Dependencies for this module: +// ../../../../../@fullcalendar/core + +declare module '@fullcalendar/rrule' { + const _default: import("@fullcalendar/core").PluginDef; + export default _default; +} + diff --git a/AKPlan/static/AKPlan/fullcalendar/rrule/main.esm.js b/AKPlan/static/AKPlan/fullcalendar/rrule/main.esm.js new file mode 100644 index 00000000..b201264e --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/rrule/main.esm.js @@ -0,0 +1,121 @@ +/*! +FullCalendar RRule Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +import { rrulestr, RRule } from 'rrule'; +import { createPlugin, refineProps, createDuration } from '@fullcalendar/core'; + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ + +var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; + +var EVENT_DEF_PROPS = { + rrule: null, + duration: createDuration +}; +var recurring = { + parse: function (rawEvent, leftoverProps, dateEnv) { + if (rawEvent.rrule != null) { + var props = refineProps(rawEvent, EVENT_DEF_PROPS, {}, leftoverProps); + var parsed = parseRRule(props.rrule, dateEnv); + if (parsed) { + return { + typeData: parsed.rrule, + allDayGuess: parsed.allDayGuess, + duration: props.duration + }; + } + } + return null; + }, + expand: function (rrule, framingRange) { + // we WANT an inclusive start and in exclusive end, but the js rrule lib will only do either BOTH + // inclusive or BOTH exclusive, which is stupid: https://github.com/jakubroztocil/rrule/issues/84 + // Workaround: make inclusive, which will generate extra occurences, and then trim. + return rrule.between(framingRange.start, framingRange.end, true) + .filter(function (date) { + return date.valueOf() < framingRange.end.valueOf(); + }); + } +}; +var main = createPlugin({ + recurringTypes: [recurring] +}); +function parseRRule(input, dateEnv) { + var allDayGuess = null; + var rrule; + if (typeof input === 'string') { + rrule = rrulestr(input); + } + else if (typeof input === 'object' && input) { // non-null object + var refined = __assign({}, input); // copy + if (typeof refined.dtstart === 'string') { + var dtstartMeta = dateEnv.createMarkerMeta(refined.dtstart); + if (dtstartMeta) { + refined.dtstart = dtstartMeta.marker; + allDayGuess = dtstartMeta.isTimeUnspecified; + } + else { + delete refined.dtstart; + } + } + if (typeof refined.until === 'string') { + refined.until = dateEnv.createMarker(refined.until); + } + if (refined.freq != null) { + refined.freq = convertConstant(refined.freq); + } + if (refined.wkst != null) { + refined.wkst = convertConstant(refined.wkst); + } + else { + refined.wkst = (dateEnv.weekDow - 1 + 7) % 7; // convert Sunday-first to Monday-first + } + if (refined.byweekday != null) { + refined.byweekday = convertConstants(refined.byweekday); // the plural version + } + rrule = new RRule(refined); + } + if (rrule) { + return { rrule: rrule, allDayGuess: allDayGuess }; + } + return null; +} +function convertConstants(input) { + if (Array.isArray(input)) { + return input.map(convertConstant); + } + return convertConstant(input); +} +function convertConstant(input) { + if (typeof input === 'string') { + return RRule[input.toUpperCase()]; + } + return input; +} + +export default main; diff --git a/AKPlan/static/AKPlan/fullcalendar/rrule/main.js b/AKPlan/static/AKPlan/fullcalendar/rrule/main.js new file mode 100644 index 00000000..1ed7bd76 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/rrule/main.js @@ -0,0 +1,128 @@ +/*! +FullCalendar RRule Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('rrule'), require('@fullcalendar/core')) : + typeof define === 'function' && define.amd ? define(['exports', 'rrule', '@fullcalendar/core'], factory) : + (global = global || self, factory(global.FullCalendarRrule = {}, global.rrule, global.FullCalendar)); +}(this, function (exports, rrule, core) { 'use strict'; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + + var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + var EVENT_DEF_PROPS = { + rrule: null, + duration: core.createDuration + }; + var recurring = { + parse: function (rawEvent, leftoverProps, dateEnv) { + if (rawEvent.rrule != null) { + var props = core.refineProps(rawEvent, EVENT_DEF_PROPS, {}, leftoverProps); + var parsed = parseRRule(props.rrule, dateEnv); + if (parsed) { + return { + typeData: parsed.rrule, + allDayGuess: parsed.allDayGuess, + duration: props.duration + }; + } + } + return null; + }, + expand: function (rrule, framingRange) { + // we WANT an inclusive start and in exclusive end, but the js rrule lib will only do either BOTH + // inclusive or BOTH exclusive, which is stupid: https://github.com/jakubroztocil/rrule/issues/84 + // Workaround: make inclusive, which will generate extra occurences, and then trim. + return rrule.between(framingRange.start, framingRange.end, true) + .filter(function (date) { + return date.valueOf() < framingRange.end.valueOf(); + }); + } + }; + var main = core.createPlugin({ + recurringTypes: [recurring] + }); + function parseRRule(input, dateEnv) { + var allDayGuess = null; + var rrule$1; + if (typeof input === 'string') { + rrule$1 = rrule.rrulestr(input); + } + else if (typeof input === 'object' && input) { // non-null object + var refined = __assign({}, input); // copy + if (typeof refined.dtstart === 'string') { + var dtstartMeta = dateEnv.createMarkerMeta(refined.dtstart); + if (dtstartMeta) { + refined.dtstart = dtstartMeta.marker; + allDayGuess = dtstartMeta.isTimeUnspecified; + } + else { + delete refined.dtstart; + } + } + if (typeof refined.until === 'string') { + refined.until = dateEnv.createMarker(refined.until); + } + if (refined.freq != null) { + refined.freq = convertConstant(refined.freq); + } + if (refined.wkst != null) { + refined.wkst = convertConstant(refined.wkst); + } + else { + refined.wkst = (dateEnv.weekDow - 1 + 7) % 7; // convert Sunday-first to Monday-first + } + if (refined.byweekday != null) { + refined.byweekday = convertConstants(refined.byweekday); // the plural version + } + rrule$1 = new rrule.RRule(refined); + } + if (rrule$1) { + return { rrule: rrule$1, allDayGuess: allDayGuess }; + } + return null; + } + function convertConstants(input) { + if (Array.isArray(input)) { + return input.map(convertConstant); + } + return convertConstant(input); + } + function convertConstant(input) { + if (typeof input === 'string') { + return rrule.RRule[input.toUpperCase()]; + } + return input; + } + + exports.default = main; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/rrule/main.min.js b/AKPlan/static/AKPlan/fullcalendar/rrule/main.min.js new file mode 100644 index 00000000..44fff76b --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/rrule/main.min.js @@ -0,0 +1,6 @@ +/*! +FullCalendar RRule Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ +!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("rrule"),require("@fullcalendar/core")):"function"==typeof define&&define.amd?define(["exports","rrule","@fullcalendar/core"],r):r((e=e||self).FullCalendarRrule={},e.rrule,e.FullCalendar)}(this,function(e,r,t){"use strict";var n=function(){return(n=Object.assign||function(e){for(var r,t=1,n=arguments.length;t<n;t++)for(var u in r=arguments[t])Object.prototype.hasOwnProperty.call(r,u)&&(e[u]=r[u]);return e}).apply(this,arguments)},u={rrule:null,duration:t.createDuration},l={parse:function(e,l,a){if(null!=e.rrule){var f=t.refineProps(e,u,{},l),o=function(e,t){var u,l=null;if("string"==typeof e)u=r.rrulestr(e);else if("object"==typeof e&&e){var a=n({},e);if("string"==typeof a.dtstart){var f=t.createMarkerMeta(a.dtstart);f?(a.dtstart=f.marker,l=f.isTimeUnspecified):delete a.dtstart}"string"==typeof a.until&&(a.until=t.createMarker(a.until)),null!=a.freq&&(a.freq=i(a.freq)),null!=a.wkst?a.wkst=i(a.wkst):a.wkst=(t.weekDow-1+7)%7,null!=a.byweekday&&(a.byweekday=function(e){if(Array.isArray(e))return e.map(i);return i(e)}(a.byweekday)),u=new r.RRule(a)}if(u)return{rrule:u,allDayGuess:l};return null}(f.rrule,a);if(o)return{typeData:o.rrule,allDayGuess:o.allDayGuess,duration:f.duration}}return null},expand:function(e,r){return e.between(r.start,r.end,!0).filter(function(e){return e.valueOf()<r.end.valueOf()})}},a=t.createPlugin({recurringTypes:[l]});function i(e){return"string"==typeof e?r.RRule[e.toUpperCase()]:e}e.default=a,Object.defineProperty(e,"__esModule",{value:!0})}); \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/rrule/package.json b/AKPlan/static/AKPlan/fullcalendar/rrule/package.json new file mode 100644 index 00000000..cf9706bc --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/rrule/package.json @@ -0,0 +1,34 @@ +{ + "name": "@fullcalendar/rrule", + "version": "4.3.0", + "title": "FullCalendar RRule Plugin", + "description": "A connector to the RRule library, for recurring events", + "keywords": [ + "calendar", + "event", + "full-sized" + ], + "homepage": "https://fullcalendar.io/", + "docs": "https://fullcalendar.io/docs/rrule-plugin", + "bugs": "https://fullcalendar.io/reporting-bugs", + "repository": { + "type": "git", + "url": "https://github.com/fullcalendar/fullcalendar.git", + "homepage": "https://github.com/fullcalendar/fullcalendar" + }, + "license": "MIT", + "author": { + "name": "Adam Shaw", + "email": "arshaw@arshaw.com", + "url": "http://arshaw.com/" + }, + "copyright": "2019 Adam Shaw", + "peerDependencies": { + "@fullcalendar/core": "~4.3.0", + "rrule": "^2.6.0" + }, + "main": "main.js", + "module": "main.esm.js", + "unpkg": "main.min.js", + "types": "main.d.ts" +} diff --git a/AKPlan/static/AKPlan/fullcalendar/timegrid/LICENSE.txt b/AKPlan/static/AKPlan/fullcalendar/timegrid/LICENSE.txt new file mode 100644 index 00000000..2149cfbe --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/timegrid/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2019 Adam Shaw + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/AKPlan/static/AKPlan/fullcalendar/timegrid/README.md b/AKPlan/static/AKPlan/fullcalendar/timegrid/README.md new file mode 100644 index 00000000..ac13676c --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/timegrid/README.md @@ -0,0 +1,8 @@ + +# FullCalendar Time Grid Plugin + +Display your events on a grid of time slots + +[View the docs »](https://fullcalendar.io/docs/timegrid-view) + +This package was created from the [FullCalendar monorepo »](https://github.com/fullcalendar/fullcalendar) diff --git a/AKPlan/static/AKPlan/fullcalendar/timegrid/main.css b/AKPlan/static/AKPlan/fullcalendar/timegrid/main.css new file mode 100644 index 00000000..b8ee6448 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/timegrid/main.css @@ -0,0 +1,309 @@ +@charset "UTF-8"; +/* TimeGridView all-day area +--------------------------------------------------------------------------------------------------*/ +.fc-timeGrid-view .fc-day-grid { + position: relative; + z-index: 2; + /* so the "more.." popover will be over the time grid */ +} + +.fc-timeGrid-view .fc-day-grid .fc-row { + min-height: 3em; + /* all-day section will never get shorter than this */ +} + +.fc-timeGrid-view .fc-day-grid .fc-row .fc-content-skeleton { + padding-bottom: 1em; + /* give space underneath events for clicking/selecting days */ +} + +/* TimeGrid axis running down the side (for both the all-day area and the slot area) +--------------------------------------------------------------------------------------------------*/ +.fc .fc-axis { + /* .fc to overcome default cell styles */ + vertical-align: middle; + padding: 0 4px; + white-space: nowrap; +} + +.fc-ltr .fc-axis { + text-align: right; +} + +.fc-rtl .fc-axis { + text-align: left; +} + +/* TimeGrid Structure +--------------------------------------------------------------------------------------------------*/ +.fc-time-grid-container, +.fc-time-grid { + /* so slats/bg/content/etc positions get scoped within here */ + position: relative; + z-index: 1; +} + +.fc-time-grid { + min-height: 100%; + /* so if height setting is 'auto', .fc-bg stretches to fill height */ +} + +.fc-time-grid table { + /* don't put outer borders on slats/bg/content/etc */ + border: 0 hidden transparent; +} + +.fc-time-grid > .fc-bg { + z-index: 1; +} + +.fc-time-grid .fc-slats, +.fc-time-grid > hr { + /* the <hr> TimeGridView injects when grid is shorter than scroller */ + position: relative; + z-index: 2; +} + +.fc-time-grid .fc-content-col { + position: relative; + /* because now-indicator lives directly inside */ +} + +.fc-time-grid .fc-content-skeleton { + position: absolute; + z-index: 3; + top: 0; + left: 0; + right: 0; +} + +/* divs within a cell within the fc-content-skeleton */ +.fc-time-grid .fc-business-container { + position: relative; + z-index: 1; +} + +.fc-time-grid .fc-bgevent-container { + position: relative; + z-index: 2; +} + +.fc-time-grid .fc-highlight-container { + position: relative; + z-index: 3; +} + +.fc-time-grid .fc-event-container { + position: relative; + z-index: 4; +} + +.fc-time-grid .fc-now-indicator-line { + z-index: 5; +} + +.fc-time-grid .fc-mirror-container { + /* also is fc-event-container */ + position: relative; + z-index: 6; +} + +/* TimeGrid Slats (lines that run horizontally) +--------------------------------------------------------------------------------------------------*/ +.fc-time-grid .fc-slats td { + height: 1.5em; + border-bottom: 0; + /* each cell is responsible for its top border */ +} + +.fc-time-grid .fc-slats .fc-minor td { + border-top-style: dotted; +} + +/* TimeGrid Highlighting Slots +--------------------------------------------------------------------------------------------------*/ +.fc-time-grid .fc-highlight-container { + /* a div within a cell within the fc-highlight-skeleton */ + position: relative; + /* scopes the left/right of the fc-highlight to be in the column */ +} + +.fc-time-grid .fc-highlight { + position: absolute; + left: 0; + right: 0; + /* top and bottom will be in by JS */ +} + +/* TimeGrid Event Containment +--------------------------------------------------------------------------------------------------*/ +.fc-ltr .fc-time-grid .fc-event-container { + /* space on the sides of events for LTR (default) */ + margin: 0 2.5% 0 2px; +} + +.fc-rtl .fc-time-grid .fc-event-container { + /* space on the sides of events for RTL */ + margin: 0 2px 0 2.5%; +} + +.fc-time-grid .fc-event, +.fc-time-grid .fc-bgevent { + position: absolute; + z-index: 1; + /* scope inner z-index's */ +} + +.fc-time-grid .fc-bgevent { + /* background events always span full width */ + left: 0; + right: 0; +} + +/* TimeGrid Event Styling +---------------------------------------------------------------------------------------------------- +We use the full "fc-time-grid-event" class instead of using descendants because the event won't +be a descendant of the grid when it is being dragged. +*/ +.fc-time-grid-event { + margin-bottom: 1px; +} + +.fc-time-grid-event-inset { + -webkit-box-shadow: 0px 0px 0px 1px #fff; + box-shadow: 0px 0px 0px 1px #fff; +} + +.fc-time-grid-event.fc-not-start { + /* events that are continuing from another day */ + /* replace space made by the top border with padding */ + border-top-width: 0; + padding-top: 1px; + /* remove top rounded corners */ + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.fc-time-grid-event.fc-not-end { + /* replace space made by the top border with padding */ + border-bottom-width: 0; + padding-bottom: 1px; + /* remove bottom rounded corners */ + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +.fc-time-grid-event .fc-content { + overflow: hidden; + max-height: 100%; +} + +.fc-time-grid-event .fc-time, +.fc-time-grid-event .fc-title { + padding: 0 1px; +} + +.fc-time-grid-event .fc-time { + font-size: 0.85em; + white-space: nowrap; +} + +/* short mode, where time and title are on the same line */ +.fc-time-grid-event.fc-short .fc-content { + /* don't wrap to second line (now that contents will be inline) */ + white-space: nowrap; +} + +.fc-time-grid-event.fc-short .fc-time, +.fc-time-grid-event.fc-short .fc-title { + /* put the time and title on the same line */ + display: inline-block; + vertical-align: top; +} + +.fc-time-grid-event.fc-short .fc-time span { + display: none; + /* don't display the full time text... */ +} + +.fc-time-grid-event.fc-short .fc-time:before { + content: attr(data-start); + /* ...instead, display only the start time */ +} + +.fc-time-grid-event.fc-short .fc-time:after { + content: "Â -Â "; + /* seperate with a dash, wrapped in nbsp's */ +} + +.fc-time-grid-event.fc-short .fc-title { + font-size: 0.85em; + /* make the title text the same size as the time */ + padding: 0; + /* undo padding from above */ +} + +/* resizer (cursor device) */ +.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer { + left: 0; + right: 0; + bottom: 0; + height: 8px; + overflow: hidden; + line-height: 8px; + font-size: 11px; + font-family: monospace; + text-align: center; + cursor: s-resize; +} + +.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer:after { + content: "="; +} + +/* resizer (touch device) */ +.fc-time-grid-event.fc-selected .fc-resizer { + /* 10x10 dot */ + border-radius: 5px; + border-width: 1px; + width: 8px; + height: 8px; + border-style: solid; + border-color: inherit; + background: #fff; + /* horizontally center */ + left: 50%; + margin-left: -5px; + /* center on the bottom edge */ + bottom: -5px; +} + +/* Now Indicator +--------------------------------------------------------------------------------------------------*/ +.fc-time-grid .fc-now-indicator-line { + border-top-width: 1px; + left: 0; + right: 0; +} + +/* arrow on axis */ +.fc-time-grid .fc-now-indicator-arrow { + margin-top: -5px; + /* vertically center on top coordinate */ +} + +.fc-ltr .fc-time-grid .fc-now-indicator-arrow { + left: 0; + /* triangle pointing right... */ + border-width: 5px 0 5px 6px; + border-top-color: transparent; + border-bottom-color: transparent; +} + +.fc-rtl .fc-time-grid .fc-now-indicator-arrow { + right: 0; + /* triangle pointing left... */ + border-width: 5px 6px 5px 0; + border-top-color: transparent; + border-bottom-color: transparent; +} diff --git a/AKPlan/static/AKPlan/fullcalendar/timegrid/main.d.ts b/AKPlan/static/AKPlan/fullcalendar/timegrid/main.d.ts new file mode 100644 index 00000000..2ec73d9e --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/timegrid/main.d.ts @@ -0,0 +1,220 @@ +// Generated by dts-bundle v0.7.3-fork.1 +// Dependencies for this module: +// ../../../../../@fullcalendar/core +// ../../../../../@fullcalendar/daygrid + +declare module '@fullcalendar/timegrid' { + import AbstractTimeGridView from '@fullcalendar/timegrid/AbstractTimeGridView'; + import TimeGridView, { buildDayTable } from '@fullcalendar/timegrid/TimeGridView'; + import { TimeGridSeg } from '@fullcalendar/timegrid/TimeGrid'; + import { TimeGridSlicer, buildDayRanges } from '@fullcalendar/timegrid/SimpleTimeGrid'; + export { TimeGridView, AbstractTimeGridView, buildDayTable, buildDayRanges, TimeGridSlicer, TimeGridSeg }; + export { default as TimeGrid } from '@fullcalendar/timegrid/TimeGrid'; + const _default: import("@fullcalendar/core").PluginDef; + export default _default; +} + +declare module '@fullcalendar/timegrid/AbstractTimeGridView' { + import { ScrollComponent, View, ViewSpec, DateProfileGenerator, ComponentContext, Duration } from '@fullcalendar/core'; + import { DayGrid } from '@fullcalendar/daygrid'; + import TimeGrid from '@fullcalendar/timegrid/TimeGrid'; + import AllDaySplitter from '@fullcalendar/timegrid/AllDaySplitter'; + export { TimeGridView as default, TimeGridView }; + abstract class TimeGridView extends View { + timeGrid: TimeGrid; + dayGrid: DayGrid; + scroller: ScrollComponent; + axisWidth: any; + protected splitter: AllDaySplitter; + constructor(context: ComponentContext, viewSpec: ViewSpec, dateProfileGenerator: DateProfileGenerator, parentEl: HTMLElement); + destroy(): void; + renderSkeletonHtml(): string; + getNowIndicatorUnit(): string; + unrenderNowIndicator(): void; + updateSize(isResize: boolean, viewHeight: number, isAuto: boolean): void; + updateBaseSize(isResize: any, viewHeight: any, isAuto: any): void; + computeScrollerHeight(viewHeight: any): number; + computeDateScroll(duration: Duration): { + top: any; + }; + queryDateScroll(): { + top: number; + }; + applyDateScroll(scroll: any): void; + renderHeadIntroHtml: () => string; + axisStyleAttr(): string; + renderTimeGridBgIntroHtml: () => string; + renderTimeGridIntroHtml: () => string; + renderDayGridBgIntroHtml: () => string; + renderDayGridIntroHtml: () => string; + } +} + +declare module '@fullcalendar/timegrid/TimeGridView' { + import { DateProfileGenerator, DateProfile, ComponentContext, ViewSpec, DayHeader, DayTable, ViewProps } from '@fullcalendar/core'; + import { SimpleDayGrid } from '@fullcalendar/daygrid'; + import SimpleTimeGrid from '@fullcalendar/timegrid/SimpleTimeGrid'; + import AbstractTimeGridView from '@fullcalendar/timegrid/AbstractTimeGridView'; + export { TimeGridView as default, TimeGridView }; + class TimeGridView extends AbstractTimeGridView { + header: DayHeader; + simpleDayGrid: SimpleDayGrid; + simpleTimeGrid: SimpleTimeGrid; + constructor(_context: ComponentContext, viewSpec: ViewSpec, dateProfileGenerator: DateProfileGenerator, parentEl: HTMLElement); + destroy(): void; + render(props: ViewProps): void; + renderNowIndicator(date: any): void; + } + export function buildDayTable(dateProfile: DateProfile, dateProfileGenerator: DateProfileGenerator): DayTable; +} + +declare module '@fullcalendar/timegrid/TimeGrid' { + import { PositionCache, Duration, DateMarker, DateFormatter, ComponentContext, DateComponent, Seg, EventSegUiInteractionState, DateProfile } from '@fullcalendar/core'; + export interface RenderProps { + renderBgIntroHtml: () => string; + renderIntroHtml: () => string; + } + export interface TimeGridSeg extends Seg { + col: number; + start: DateMarker; + end: DateMarker; + } + export interface TimeGridCell { + date: DateMarker; + htmlAttrs?: string; + } + export interface TimeGridProps { + dateProfile: DateProfile; + cells: TimeGridCell[]; + businessHourSegs: TimeGridSeg[]; + bgEventSegs: TimeGridSeg[]; + fgEventSegs: TimeGridSeg[]; + dateSelectionSegs: TimeGridSeg[]; + eventSelection: string; + eventDrag: EventSegUiInteractionState | null; + eventResize: EventSegUiInteractionState | null; + } + export { TimeGrid as default, TimeGrid }; + class TimeGrid extends DateComponent<TimeGridProps> { + renderProps: RenderProps; + slotDuration: Duration; + snapDuration: Duration; + snapsPerSlot: any; + labelFormat: DateFormatter; + labelInterval: Duration; + colCnt: number; + colEls: HTMLElement[]; + slatContainerEl: HTMLElement; + slatEls: HTMLElement[]; + nowIndicatorEls: HTMLElement[]; + colPositions: PositionCache; + slatPositions: PositionCache; + isSlatSizesDirty: boolean; + isColSizesDirty: boolean; + rootBgContainerEl: HTMLElement; + bottomRuleEl: HTMLElement; + contentSkeletonEl: HTMLElement; + colContainerEls: HTMLElement[]; + fgContainerEls: HTMLElement[]; + bgContainerEls: HTMLElement[]; + mirrorContainerEls: HTMLElement[]; + highlightContainerEls: HTMLElement[]; + businessContainerEls: HTMLElement[]; + constructor(context: ComponentContext, el: HTMLElement, renderProps: RenderProps); + processOptions(): void; + computeLabelInterval(slotDuration: any): any; + render(props: TimeGridProps): void; + destroy(): void; + updateSize(isResize: boolean): void; + _renderSlats(dateProfile: DateProfile): void; + renderSlatRowHtml(dateProfile: DateProfile): string; + _renderColumns(cells: TimeGridCell[], dateProfile: DateProfile): void; + _unrenderColumns(): void; + renderContentSkeleton(): void; + unrenderContentSkeleton(): void; + groupSegsByCol(segs: any): any[]; + attachSegsByCol(segsByCol: any, containerEls: HTMLElement[]): void; + getNowIndicatorUnit(): string; + renderNowIndicator(segs: TimeGridSeg[], date: any): void; + unrenderNowIndicator(): void; + getTotalSlatHeight(): number; + computeDateTop(when: DateMarker, startOfDayDate?: DateMarker): any; + computeTimeTop(duration: Duration): any; + computeSegVerticals(segs: any): void; + assignSegVerticals(segs: any): void; + generateSegVerticalCss(seg: any): { + top: any; + bottom: number; + }; + buildPositionCaches(): void; + buildColPositions(): void; + buildSlatPositions(): void; + positionToHit(positionLeft: any, positionTop: any): { + col: any; + dateSpan: { + range: { + start: Date; + end: Date; + }; + allDay: boolean; + }; + dayEl: HTMLElement; + relativeRect: { + left: any; + right: any; + top: any; + bottom: any; + }; + }; + _renderEventDrag(state: EventSegUiInteractionState): void; + _unrenderEventDrag(state: EventSegUiInteractionState): void; + _renderEventResize(state: EventSegUiInteractionState): void; + _unrenderEventResize(state: EventSegUiInteractionState): void; + _renderDateSelection(segs: Seg[]): void; + _unrenderDateSelection(segs: Seg[]): void; + } +} + +declare module '@fullcalendar/timegrid/SimpleTimeGrid' { + import { DateComponent, DateProfile, EventStore, EventUiHash, EventInteractionState, DateSpan, DateRange, DayTable, DateEnv, DateMarker, Slicer, Hit, ComponentContext } from '@fullcalendar/core'; + import TimeGrid, { TimeGridSeg } from '@fullcalendar/timegrid/TimeGrid'; + export interface SimpleTimeGridProps { + dateProfile: DateProfile | null; + dayTable: DayTable; + businessHours: EventStore; + eventStore: EventStore; + eventUiBases: EventUiHash; + dateSelection: DateSpan | null; + eventSelection: string; + eventDrag: EventInteractionState | null; + eventResize: EventInteractionState | null; + } + export { SimpleTimeGrid as default, SimpleTimeGrid }; + class SimpleTimeGrid extends DateComponent<SimpleTimeGridProps> { + timeGrid: TimeGrid; + constructor(context: ComponentContext, timeGrid: TimeGrid); + destroy(): void; + render(props: SimpleTimeGridProps): void; + renderNowIndicator(date: DateMarker): void; + buildPositionCaches(): void; + queryHit(positionLeft: number, positionTop: number): Hit; + } + export function buildDayRanges(dayTable: DayTable, dateProfile: DateProfile, dateEnv: DateEnv): DateRange[]; + export class TimeGridSlicer extends Slicer<TimeGridSeg, [DateRange[]]> { + sliceRange(range: DateRange, dayRanges: DateRange[]): TimeGridSeg[]; + } +} + +declare module '@fullcalendar/timegrid/AllDaySplitter' { + import { Splitter, EventDef, DateSpan } from '@fullcalendar/core'; + export { AllDaySplitter as default, AllDaySplitter }; + class AllDaySplitter extends Splitter { + getKeyInfo(): { + allDay: {}; + timed: {}; + }; + getKeysForDateSpan(dateSpan: DateSpan): string[]; + getKeysForEventDef(eventDef: EventDef): string[]; + } +} + diff --git a/AKPlan/static/AKPlan/fullcalendar/timegrid/main.esm.js b/AKPlan/static/AKPlan/fullcalendar/timegrid/main.esm.js new file mode 100644 index 00000000..0c5178c1 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/timegrid/main.esm.js @@ -0,0 +1,1345 @@ +/*! +FullCalendar Time Grid Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +import { createFormatter, removeElement, cssToStr, isMultiDayRange, htmlEscape, compareByFieldSpecs, applyStyle, FgEventRenderer, buildSegCompareObj, FillRenderer, memoizeRendering, createDuration, wholeDivideDurations, findElements, PositionCache, startOfDay, asRoughMs, formatIsoTimeString, addDurations, htmlToElement, createElement, multiplyDuration, DateComponent, hasBgRendering, Splitter, diffDays, buildGotoAnchorHtml, getAllDayHtml, ScrollComponent, matchCellWidths, uncompensateScroll, compensateScroll, subtractInnerElHeight, View, memoize, intersectRanges, Slicer, DayHeader, DaySeries, DayTable, createPlugin } from '@fullcalendar/core'; +import { DayBgRow, DayGrid, SimpleDayGrid } from '@fullcalendar/daygrid'; + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} + +var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; + +/* +Only handles foreground segs. +Does not own rendering. Use for low-level util methods by TimeGrid. +*/ +var TimeGridEventRenderer = /** @class */ (function (_super) { + __extends(TimeGridEventRenderer, _super); + function TimeGridEventRenderer(timeGrid) { + var _this = _super.call(this, timeGrid.context) || this; + _this.timeGrid = timeGrid; + _this.fullTimeFormat = createFormatter({ + hour: 'numeric', + minute: '2-digit', + separator: _this.context.options.defaultRangeSeparator + }); + return _this; + } + // Given an array of foreground segments, render a DOM element for each, computes position, + // and attaches to the column inner-container elements. + TimeGridEventRenderer.prototype.attachSegs = function (segs, mirrorInfo) { + var segsByCol = this.timeGrid.groupSegsByCol(segs); + // order the segs within each column + // TODO: have groupSegsByCol do this? + for (var col = 0; col < segsByCol.length; col++) { + segsByCol[col] = this.sortEventSegs(segsByCol[col]); + } + this.segsByCol = segsByCol; + this.timeGrid.attachSegsByCol(segsByCol, this.timeGrid.fgContainerEls); + }; + TimeGridEventRenderer.prototype.detachSegs = function (segs) { + segs.forEach(function (seg) { + removeElement(seg.el); + }); + this.segsByCol = null; + }; + TimeGridEventRenderer.prototype.computeSegSizes = function (allSegs) { + var _a = this, timeGrid = _a.timeGrid, segsByCol = _a.segsByCol; + var colCnt = timeGrid.colCnt; + timeGrid.computeSegVerticals(allSegs); // horizontals relies on this + if (segsByCol) { + for (var col = 0; col < colCnt; col++) { + this.computeSegHorizontals(segsByCol[col]); // compute horizontal coordinates, z-index's, and reorder the array + } + } + }; + TimeGridEventRenderer.prototype.assignSegSizes = function (allSegs) { + var _a = this, timeGrid = _a.timeGrid, segsByCol = _a.segsByCol; + var colCnt = timeGrid.colCnt; + timeGrid.assignSegVerticals(allSegs); // horizontals relies on this + if (segsByCol) { + for (var col = 0; col < colCnt; col++) { + this.assignSegCss(segsByCol[col]); + } + } + }; + // Computes a default event time formatting string if `eventTimeFormat` is not explicitly defined + TimeGridEventRenderer.prototype.computeEventTimeFormat = function () { + return { + hour: 'numeric', + minute: '2-digit', + meridiem: false + }; + }; + // Computes a default `displayEventEnd` value if one is not expliclty defined + TimeGridEventRenderer.prototype.computeDisplayEventEnd = function () { + return true; + }; + // Renders the HTML for a single event segment's default rendering + TimeGridEventRenderer.prototype.renderSegHtml = function (seg, mirrorInfo) { + var view = this.context.view; + var eventRange = seg.eventRange; + var eventDef = eventRange.def; + var eventUi = eventRange.ui; + var allDay = eventDef.allDay; + var isDraggable = view.computeEventDraggable(eventDef, eventUi); + var isResizableFromStart = seg.isStart && view.computeEventStartResizable(eventDef, eventUi); + var isResizableFromEnd = seg.isEnd && view.computeEventEndResizable(eventDef, eventUi); + var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd, mirrorInfo); + var skinCss = cssToStr(this.getSkinCss(eventUi)); + var timeText; + var fullTimeText; // more verbose time text. for the print stylesheet + var startTimeText; // just the start time text + classes.unshift('fc-time-grid-event'); + // if the event appears to span more than one day... + if (isMultiDayRange(eventRange.range)) { + // Don't display time text on segments that run entirely through a day. + // That would appear as midnight-midnight and would look dumb. + // Otherwise, display the time text for the *segment's* times (like 6pm-midnight or midnight-10am) + if (seg.isStart || seg.isEnd) { + var unzonedStart = seg.start; + var unzonedEnd = seg.end; + timeText = this._getTimeText(unzonedStart, unzonedEnd, allDay); // TODO: give the timezones + fullTimeText = this._getTimeText(unzonedStart, unzonedEnd, allDay, this.fullTimeFormat); + startTimeText = this._getTimeText(unzonedStart, unzonedEnd, allDay, null, false); // displayEnd=false + } + } + else { + // Display the normal time text for the *event's* times + timeText = this.getTimeText(eventRange); + fullTimeText = this.getTimeText(eventRange, this.fullTimeFormat); + startTimeText = this.getTimeText(eventRange, null, false); // displayEnd=false + } + return '<a class="' + classes.join(' ') + '"' + + (eventDef.url ? + ' href="' + htmlEscape(eventDef.url) + '"' : + '') + + (skinCss ? + ' style="' + skinCss + '"' : + '') + + '>' + + '<div class="fc-content">' + + (timeText ? + '<div class="fc-time"' + + ' data-start="' + htmlEscape(startTimeText) + '"' + + ' data-full="' + htmlEscape(fullTimeText) + '"' + + '>' + + '<span>' + htmlEscape(timeText) + '</span>' + + '</div>' : + '') + + (eventDef.title ? + '<div class="fc-title">' + + htmlEscape(eventDef.title) + + '</div>' : + '') + + '</div>' + + /* TODO: write CSS for this + (isResizableFromStart ? + '<div class="fc-resizer fc-start-resizer"></div>' : + '' + ) + + */ + (isResizableFromEnd ? + '<div class="fc-resizer fc-end-resizer"></div>' : + '') + + '</a>'; + }; + // Given an array of segments that are all in the same column, sets the backwardCoord and forwardCoord on each. + // Assumed the segs are already ordered. + // NOTE: Also reorders the given array by date! + TimeGridEventRenderer.prototype.computeSegHorizontals = function (segs) { + var levels; + var level0; + var i; + levels = buildSlotSegLevels(segs); + computeForwardSlotSegs(levels); + if ((level0 = levels[0])) { + for (i = 0; i < level0.length; i++) { + computeSlotSegPressures(level0[i]); + } + for (i = 0; i < level0.length; i++) { + this.computeSegForwardBack(level0[i], 0, 0); + } + } + }; + // Calculate seg.forwardCoord and seg.backwardCoord for the segment, where both values range + // from 0 to 1. If the calendar is left-to-right, the seg.backwardCoord maps to "left" and + // seg.forwardCoord maps to "right" (via percentage). Vice-versa if the calendar is right-to-left. + // + // The segment might be part of a "series", which means consecutive segments with the same pressure + // who's width is unknown until an edge has been hit. `seriesBackwardPressure` is the number of + // segments behind this one in the current series, and `seriesBackwardCoord` is the starting + // coordinate of the first segment in the series. + TimeGridEventRenderer.prototype.computeSegForwardBack = function (seg, seriesBackwardPressure, seriesBackwardCoord) { + var forwardSegs = seg.forwardSegs; + var i; + if (seg.forwardCoord === undefined) { // not already computed + if (!forwardSegs.length) { + // if there are no forward segments, this segment should butt up against the edge + seg.forwardCoord = 1; + } + else { + // sort highest pressure first + this.sortForwardSegs(forwardSegs); + // this segment's forwardCoord will be calculated from the backwardCoord of the + // highest-pressure forward segment. + this.computeSegForwardBack(forwardSegs[0], seriesBackwardPressure + 1, seriesBackwardCoord); + seg.forwardCoord = forwardSegs[0].backwardCoord; + } + // calculate the backwardCoord from the forwardCoord. consider the series + seg.backwardCoord = seg.forwardCoord - + (seg.forwardCoord - seriesBackwardCoord) / // available width for series + (seriesBackwardPressure + 1); // # of segments in the series + // use this segment's coordinates to computed the coordinates of the less-pressurized + // forward segments + for (i = 0; i < forwardSegs.length; i++) { + this.computeSegForwardBack(forwardSegs[i], 0, seg.forwardCoord); + } + } + }; + TimeGridEventRenderer.prototype.sortForwardSegs = function (forwardSegs) { + var objs = forwardSegs.map(buildTimeGridSegCompareObj); + var specs = [ + // put higher-pressure first + { field: 'forwardPressure', order: -1 }, + // put segments that are closer to initial edge first (and favor ones with no coords yet) + { field: 'backwardCoord', order: 1 } + ].concat(this.context.view.eventOrderSpecs); + objs.sort(function (obj0, obj1) { + return compareByFieldSpecs(obj0, obj1, specs); + }); + return objs.map(function (c) { + return c._seg; + }); + }; + // Given foreground event segments that have already had their position coordinates computed, + // assigns position-related CSS values to their elements. + TimeGridEventRenderer.prototype.assignSegCss = function (segs) { + for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { + var seg = segs_1[_i]; + applyStyle(seg.el, this.generateSegCss(seg)); + if (seg.level > 0) { + seg.el.classList.add('fc-time-grid-event-inset'); + } + // if the event is short that the title will be cut off, + // attach a className that condenses the title into the time area. + if (seg.eventRange.def.title && seg.bottom - seg.top < 30) { + seg.el.classList.add('fc-short'); // TODO: "condensed" is a better name + } + } + }; + // Generates an object with CSS properties/values that should be applied to an event segment element. + // Contains important positioning-related properties that should be applied to any event element, customized or not. + TimeGridEventRenderer.prototype.generateSegCss = function (seg) { + var shouldOverlap = this.context.options.slotEventOverlap; + var backwardCoord = seg.backwardCoord; // the left side if LTR. the right side if RTL. floating-point + var forwardCoord = seg.forwardCoord; // the right side if LTR. the left side if RTL. floating-point + var props = this.timeGrid.generateSegVerticalCss(seg); // get top/bottom first + var isRtl = this.timeGrid.isRtl; + var left; // amount of space from left edge, a fraction of the total width + var right; // amount of space from right edge, a fraction of the total width + if (shouldOverlap) { + // double the width, but don't go beyond the maximum forward coordinate (1.0) + forwardCoord = Math.min(1, backwardCoord + (forwardCoord - backwardCoord) * 2); + } + if (isRtl) { + left = 1 - forwardCoord; + right = backwardCoord; + } + else { + left = backwardCoord; + right = 1 - forwardCoord; + } + props.zIndex = seg.level + 1; // convert from 0-base to 1-based + props.left = left * 100 + '%'; + props.right = right * 100 + '%'; + if (shouldOverlap && seg.forwardPressure) { + // add padding to the edge so that forward stacked events don't cover the resizer's icon + props[isRtl ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width + } + return props; + }; + return TimeGridEventRenderer; +}(FgEventRenderer)); +// Builds an array of segments "levels". The first level will be the leftmost tier of segments if the calendar is +// left-to-right, or the rightmost if the calendar is right-to-left. Assumes the segments are already ordered by date. +function buildSlotSegLevels(segs) { + var levels = []; + var i; + var seg; + var j; + for (i = 0; i < segs.length; i++) { + seg = segs[i]; + // go through all the levels and stop on the first level where there are no collisions + for (j = 0; j < levels.length; j++) { + if (!computeSlotSegCollisions(seg, levels[j]).length) { + break; + } + } + seg.level = j; + (levels[j] || (levels[j] = [])).push(seg); + } + return levels; +} +// For every segment, figure out the other segments that are in subsequent +// levels that also occupy the same vertical space. Accumulate in seg.forwardSegs +function computeForwardSlotSegs(levels) { + var i; + var level; + var j; + var seg; + var k; + for (i = 0; i < levels.length; i++) { + level = levels[i]; + for (j = 0; j < level.length; j++) { + seg = level[j]; + seg.forwardSegs = []; + for (k = i + 1; k < levels.length; k++) { + computeSlotSegCollisions(seg, levels[k], seg.forwardSegs); + } + } + } +} +// Figure out which path forward (via seg.forwardSegs) results in the longest path until +// the furthest edge is reached. The number of segments in this path will be seg.forwardPressure +function computeSlotSegPressures(seg) { + var forwardSegs = seg.forwardSegs; + var forwardPressure = 0; + var i; + var forwardSeg; + if (seg.forwardPressure === undefined) { // not already computed + for (i = 0; i < forwardSegs.length; i++) { + forwardSeg = forwardSegs[i]; + // figure out the child's maximum forward path + computeSlotSegPressures(forwardSeg); + // either use the existing maximum, or use the child's forward pressure + // plus one (for the forwardSeg itself) + forwardPressure = Math.max(forwardPressure, 1 + forwardSeg.forwardPressure); + } + seg.forwardPressure = forwardPressure; + } +} +// Find all the segments in `otherSegs` that vertically collide with `seg`. +// Append into an optionally-supplied `results` array and return. +function computeSlotSegCollisions(seg, otherSegs, results) { + if (results === void 0) { results = []; } + for (var i = 0; i < otherSegs.length; i++) { + if (isSlotSegCollision(seg, otherSegs[i])) { + results.push(otherSegs[i]); + } + } + return results; +} +// Do these segments occupy the same vertical space? +function isSlotSegCollision(seg1, seg2) { + return seg1.bottom > seg2.top && seg1.top < seg2.bottom; +} +function buildTimeGridSegCompareObj(seg) { + var obj = buildSegCompareObj(seg); + obj.forwardPressure = seg.forwardPressure; + obj.backwardCoord = seg.backwardCoord; + return obj; +} + +var TimeGridMirrorRenderer = /** @class */ (function (_super) { + __extends(TimeGridMirrorRenderer, _super); + function TimeGridMirrorRenderer() { + return _super !== null && _super.apply(this, arguments) || this; + } + TimeGridMirrorRenderer.prototype.attachSegs = function (segs, mirrorInfo) { + this.segsByCol = this.timeGrid.groupSegsByCol(segs); + this.timeGrid.attachSegsByCol(this.segsByCol, this.timeGrid.mirrorContainerEls); + this.sourceSeg = mirrorInfo.sourceSeg; + }; + TimeGridMirrorRenderer.prototype.generateSegCss = function (seg) { + var props = _super.prototype.generateSegCss.call(this, seg); + var sourceSeg = this.sourceSeg; + if (sourceSeg && sourceSeg.col === seg.col) { + var sourceSegProps = _super.prototype.generateSegCss.call(this, sourceSeg); + props.left = sourceSegProps.left; + props.right = sourceSegProps.right; + props.marginLeft = sourceSegProps.marginLeft; + props.marginRight = sourceSegProps.marginRight; + } + return props; + }; + return TimeGridMirrorRenderer; +}(TimeGridEventRenderer)); + +var TimeGridFillRenderer = /** @class */ (function (_super) { + __extends(TimeGridFillRenderer, _super); + function TimeGridFillRenderer(timeGrid) { + var _this = _super.call(this, timeGrid.context) || this; + _this.timeGrid = timeGrid; + return _this; + } + TimeGridFillRenderer.prototype.attachSegs = function (type, segs) { + var timeGrid = this.timeGrid; + var containerEls; + // TODO: more efficient lookup + if (type === 'bgEvent') { + containerEls = timeGrid.bgContainerEls; + } + else if (type === 'businessHours') { + containerEls = timeGrid.businessContainerEls; + } + else if (type === 'highlight') { + containerEls = timeGrid.highlightContainerEls; + } + timeGrid.attachSegsByCol(timeGrid.groupSegsByCol(segs), containerEls); + return segs.map(function (seg) { + return seg.el; + }); + }; + TimeGridFillRenderer.prototype.computeSegSizes = function (segs) { + this.timeGrid.computeSegVerticals(segs); + }; + TimeGridFillRenderer.prototype.assignSegSizes = function (segs) { + this.timeGrid.assignSegVerticals(segs); + }; + return TimeGridFillRenderer; +}(FillRenderer)); + +/* A component that renders one or more columns of vertical time slots +----------------------------------------------------------------------------------------------------------------------*/ +// potential nice values for the slot-duration and interval-duration +// from largest to smallest +var AGENDA_STOCK_SUB_DURATIONS = [ + { hours: 1 }, + { minutes: 30 }, + { minutes: 15 }, + { seconds: 30 }, + { seconds: 15 } +]; +var TimeGrid = /** @class */ (function (_super) { + __extends(TimeGrid, _super); + function TimeGrid(context, el, renderProps) { + var _this = _super.call(this, context, el) || this; + _this.isSlatSizesDirty = false; + _this.isColSizesDirty = false; + _this.renderSlats = memoizeRendering(_this._renderSlats); + var eventRenderer = _this.eventRenderer = new TimeGridEventRenderer(_this); + var fillRenderer = _this.fillRenderer = new TimeGridFillRenderer(_this); + _this.mirrorRenderer = new TimeGridMirrorRenderer(_this); + var renderColumns = _this.renderColumns = memoizeRendering(_this._renderColumns, _this._unrenderColumns); + _this.renderBusinessHours = memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'businessHours'), fillRenderer.unrender.bind(fillRenderer, 'businessHours'), [renderColumns]); + _this.renderDateSelection = memoizeRendering(_this._renderDateSelection, _this._unrenderDateSelection, [renderColumns]); + _this.renderFgEvents = memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer), [renderColumns]); + _this.renderBgEvents = memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'bgEvent'), fillRenderer.unrender.bind(fillRenderer, 'bgEvent'), [renderColumns]); + _this.renderEventSelection = memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]); + _this.renderEventDrag = memoizeRendering(_this._renderEventDrag, _this._unrenderEventDrag, [renderColumns]); + _this.renderEventResize = memoizeRendering(_this._renderEventResize, _this._unrenderEventResize, [renderColumns]); + _this.processOptions(); + el.innerHTML = + '<div class="fc-bg"></div>' + + '<div class="fc-slats"></div>' + + '<hr class="fc-divider ' + _this.theme.getClass('widgetHeader') + '" style="display:none" />'; + _this.rootBgContainerEl = el.querySelector('.fc-bg'); + _this.slatContainerEl = el.querySelector('.fc-slats'); + _this.bottomRuleEl = el.querySelector('.fc-divider'); + _this.renderProps = renderProps; + return _this; + } + /* Options + ------------------------------------------------------------------------------------------------------------------*/ + // Parses various options into properties of this object + TimeGrid.prototype.processOptions = function () { + var slotDuration = this.opt('slotDuration'); + var snapDuration = this.opt('snapDuration'); + var snapsPerSlot; + var input; + slotDuration = createDuration(slotDuration); + snapDuration = snapDuration ? createDuration(snapDuration) : slotDuration; + snapsPerSlot = wholeDivideDurations(slotDuration, snapDuration); + if (snapsPerSlot === null) { + snapDuration = slotDuration; + snapsPerSlot = 1; + // TODO: say warning? + } + this.slotDuration = slotDuration; + this.snapDuration = snapDuration; + this.snapsPerSlot = snapsPerSlot; + // might be an array value (for TimelineView). + // if so, getting the most granular entry (the last one probably). + input = this.opt('slotLabelFormat'); + if (Array.isArray(input)) { + input = input[input.length - 1]; + } + this.labelFormat = createFormatter(input || { + hour: 'numeric', + minute: '2-digit', + omitZeroMinute: true, + meridiem: 'short' + }); + input = this.opt('slotLabelInterval'); + this.labelInterval = input ? + createDuration(input) : + this.computeLabelInterval(slotDuration); + }; + // Computes an automatic value for slotLabelInterval + TimeGrid.prototype.computeLabelInterval = function (slotDuration) { + var i; + var labelInterval; + var slotsPerLabel; + // find the smallest stock label interval that results in more than one slots-per-label + for (i = AGENDA_STOCK_SUB_DURATIONS.length - 1; i >= 0; i--) { + labelInterval = createDuration(AGENDA_STOCK_SUB_DURATIONS[i]); + slotsPerLabel = wholeDivideDurations(labelInterval, slotDuration); + if (slotsPerLabel !== null && slotsPerLabel > 1) { + return labelInterval; + } + } + return slotDuration; // fall back + }; + /* Rendering + ------------------------------------------------------------------------------------------------------------------*/ + TimeGrid.prototype.render = function (props) { + var cells = props.cells; + this.colCnt = cells.length; + this.renderSlats(props.dateProfile); + this.renderColumns(props.cells, props.dateProfile); + this.renderBusinessHours(props.businessHourSegs); + this.renderDateSelection(props.dateSelectionSegs); + this.renderFgEvents(props.fgEventSegs); + this.renderBgEvents(props.bgEventSegs); + this.renderEventSelection(props.eventSelection); + this.renderEventDrag(props.eventDrag); + this.renderEventResize(props.eventResize); + }; + TimeGrid.prototype.destroy = function () { + _super.prototype.destroy.call(this); + // should unrender everything else too + this.renderSlats.unrender(); + this.renderColumns.unrender(); + }; + TimeGrid.prototype.updateSize = function (isResize) { + var _a = this, fillRenderer = _a.fillRenderer, eventRenderer = _a.eventRenderer, mirrorRenderer = _a.mirrorRenderer; + if (isResize || this.isSlatSizesDirty) { + this.buildSlatPositions(); + this.isSlatSizesDirty = false; + } + if (isResize || this.isColSizesDirty) { + this.buildColPositions(); + this.isColSizesDirty = false; + } + fillRenderer.computeSizes(isResize); + eventRenderer.computeSizes(isResize); + mirrorRenderer.computeSizes(isResize); + fillRenderer.assignSizes(isResize); + eventRenderer.assignSizes(isResize); + mirrorRenderer.assignSizes(isResize); + }; + TimeGrid.prototype._renderSlats = function (dateProfile) { + var theme = this.theme; + this.slatContainerEl.innerHTML = + '<table class="' + theme.getClass('tableGrid') + '">' + + this.renderSlatRowHtml(dateProfile) + + '</table>'; + this.slatEls = findElements(this.slatContainerEl, 'tr'); + this.slatPositions = new PositionCache(this.el, this.slatEls, false, true // vertical + ); + this.isSlatSizesDirty = true; + }; + // Generates the HTML for the horizontal "slats" that run width-wise. Has a time axis on a side. Depends on RTL. + TimeGrid.prototype.renderSlatRowHtml = function (dateProfile) { + var _a = this, dateEnv = _a.dateEnv, theme = _a.theme, isRtl = _a.isRtl; + var html = ''; + var dayStart = startOfDay(dateProfile.renderRange.start); + var slotTime = dateProfile.minTime; + var slotIterator = createDuration(0); + var slotDate; // will be on the view's first day, but we only care about its time + var isLabeled; + var axisHtml; + // Calculate the time for each slot + while (asRoughMs(slotTime) < asRoughMs(dateProfile.maxTime)) { + slotDate = dateEnv.add(dayStart, slotTime); + isLabeled = wholeDivideDurations(slotIterator, this.labelInterval) !== null; + axisHtml = + '<td class="fc-axis fc-time ' + theme.getClass('widgetContent') + '">' + + (isLabeled ? + '<span>' + // for matchCellWidths + htmlEscape(dateEnv.format(slotDate, this.labelFormat)) + + '</span>' : + '') + + '</td>'; + html += + '<tr data-time="' + formatIsoTimeString(slotDate) + '"' + + (isLabeled ? '' : ' class="fc-minor"') + + '>' + + (!isRtl ? axisHtml : '') + + '<td class="' + theme.getClass('widgetContent') + '"></td>' + + (isRtl ? axisHtml : '') + + '</tr>'; + slotTime = addDurations(slotTime, this.slotDuration); + slotIterator = addDurations(slotIterator, this.slotDuration); + } + return html; + }; + TimeGrid.prototype._renderColumns = function (cells, dateProfile) { + var _a = this, theme = _a.theme, dateEnv = _a.dateEnv, view = _a.view; + var bgRow = new DayBgRow(this.context); + this.rootBgContainerEl.innerHTML = + '<table class="' + theme.getClass('tableGrid') + '">' + + bgRow.renderHtml({ + cells: cells, + dateProfile: dateProfile, + renderIntroHtml: this.renderProps.renderBgIntroHtml + }) + + '</table>'; + this.colEls = findElements(this.el, '.fc-day, .fc-disabled-day'); + for (var col = 0; col < this.colCnt; col++) { + this.publiclyTrigger('dayRender', [ + { + date: dateEnv.toDate(cells[col].date), + el: this.colEls[col], + view: view + } + ]); + } + if (this.isRtl) { + this.colEls.reverse(); + } + this.colPositions = new PositionCache(this.el, this.colEls, true, // horizontal + false); + this.renderContentSkeleton(); + this.isColSizesDirty = true; + }; + TimeGrid.prototype._unrenderColumns = function () { + this.unrenderContentSkeleton(); + }; + /* Content Skeleton + ------------------------------------------------------------------------------------------------------------------*/ + // Renders the DOM that the view's content will live in + TimeGrid.prototype.renderContentSkeleton = function () { + var parts = []; + var skeletonEl; + parts.push(this.renderProps.renderIntroHtml()); + for (var i = 0; i < this.colCnt; i++) { + parts.push('<td>' + + '<div class="fc-content-col">' + + '<div class="fc-event-container fc-mirror-container"></div>' + + '<div class="fc-event-container"></div>' + + '<div class="fc-highlight-container"></div>' + + '<div class="fc-bgevent-container"></div>' + + '<div class="fc-business-container"></div>' + + '</div>' + + '</td>'); + } + if (this.isRtl) { + parts.reverse(); + } + skeletonEl = this.contentSkeletonEl = htmlToElement('<div class="fc-content-skeleton">' + + '<table>' + + '<tr>' + parts.join('') + '</tr>' + + '</table>' + + '</div>'); + this.colContainerEls = findElements(skeletonEl, '.fc-content-col'); + this.mirrorContainerEls = findElements(skeletonEl, '.fc-mirror-container'); + this.fgContainerEls = findElements(skeletonEl, '.fc-event-container:not(.fc-mirror-container)'); + this.bgContainerEls = findElements(skeletonEl, '.fc-bgevent-container'); + this.highlightContainerEls = findElements(skeletonEl, '.fc-highlight-container'); + this.businessContainerEls = findElements(skeletonEl, '.fc-business-container'); + if (this.isRtl) { + this.colContainerEls.reverse(); + this.mirrorContainerEls.reverse(); + this.fgContainerEls.reverse(); + this.bgContainerEls.reverse(); + this.highlightContainerEls.reverse(); + this.businessContainerEls.reverse(); + } + this.el.appendChild(skeletonEl); + }; + TimeGrid.prototype.unrenderContentSkeleton = function () { + removeElement(this.contentSkeletonEl); + }; + // Given a flat array of segments, return an array of sub-arrays, grouped by each segment's col + TimeGrid.prototype.groupSegsByCol = function (segs) { + var segsByCol = []; + var i; + for (i = 0; i < this.colCnt; i++) { + segsByCol.push([]); + } + for (i = 0; i < segs.length; i++) { + segsByCol[segs[i].col].push(segs[i]); + } + return segsByCol; + }; + // Given segments grouped by column, insert the segments' elements into a parallel array of container + // elements, each living within a column. + TimeGrid.prototype.attachSegsByCol = function (segsByCol, containerEls) { + var col; + var segs; + var i; + for (col = 0; col < this.colCnt; col++) { // iterate each column grouping + segs = segsByCol[col]; + for (i = 0; i < segs.length; i++) { + containerEls[col].appendChild(segs[i].el); + } + } + }; + /* Now Indicator + ------------------------------------------------------------------------------------------------------------------*/ + TimeGrid.prototype.getNowIndicatorUnit = function () { + return 'minute'; // will refresh on the minute + }; + TimeGrid.prototype.renderNowIndicator = function (segs, date) { + // HACK: if date columns not ready for some reason (scheduler) + if (!this.colContainerEls) { + return; + } + var top = this.computeDateTop(date); + var nodes = []; + var i; + // render lines within the columns + for (i = 0; i < segs.length; i++) { + var lineEl = createElement('div', { className: 'fc-now-indicator fc-now-indicator-line' }); + lineEl.style.top = top + 'px'; + this.colContainerEls[segs[i].col].appendChild(lineEl); + nodes.push(lineEl); + } + // render an arrow over the axis + if (segs.length > 0) { // is the current time in view? + var arrowEl = createElement('div', { className: 'fc-now-indicator fc-now-indicator-arrow' }); + arrowEl.style.top = top + 'px'; + this.contentSkeletonEl.appendChild(arrowEl); + nodes.push(arrowEl); + } + this.nowIndicatorEls = nodes; + }; + TimeGrid.prototype.unrenderNowIndicator = function () { + if (this.nowIndicatorEls) { + this.nowIndicatorEls.forEach(removeElement); + this.nowIndicatorEls = null; + } + }; + /* Coordinates + ------------------------------------------------------------------------------------------------------------------*/ + TimeGrid.prototype.getTotalSlatHeight = function () { + return this.slatContainerEl.getBoundingClientRect().height; + }; + // Computes the top coordinate, relative to the bounds of the grid, of the given date. + // A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight. + TimeGrid.prototype.computeDateTop = function (when, startOfDayDate) { + if (!startOfDayDate) { + startOfDayDate = startOfDay(when); + } + return this.computeTimeTop(createDuration(when.valueOf() - startOfDayDate.valueOf())); + }; + // Computes the top coordinate, relative to the bounds of the grid, of the given time (a Duration). + TimeGrid.prototype.computeTimeTop = function (duration) { + var len = this.slatEls.length; + var dateProfile = this.props.dateProfile; + var slatCoverage = (duration.milliseconds - asRoughMs(dateProfile.minTime)) / asRoughMs(this.slotDuration); // floating-point value of # of slots covered + var slatIndex; + var slatRemainder; + // compute a floating-point number for how many slats should be progressed through. + // from 0 to number of slats (inclusive) + // constrained because minTime/maxTime might be customized. + slatCoverage = Math.max(0, slatCoverage); + slatCoverage = Math.min(len, slatCoverage); + // an integer index of the furthest whole slat + // from 0 to number slats (*exclusive*, so len-1) + slatIndex = Math.floor(slatCoverage); + slatIndex = Math.min(slatIndex, len - 1); + // how much further through the slatIndex slat (from 0.0-1.0) must be covered in addition. + // could be 1.0 if slatCoverage is covering *all* the slots + slatRemainder = slatCoverage - slatIndex; + return this.slatPositions.tops[slatIndex] + + this.slatPositions.getHeight(slatIndex) * slatRemainder; + }; + // For each segment in an array, computes and assigns its top and bottom properties + TimeGrid.prototype.computeSegVerticals = function (segs) { + var eventMinHeight = this.opt('timeGridEventMinHeight'); + var i; + var seg; + var dayDate; + for (i = 0; i < segs.length; i++) { + seg = segs[i]; + dayDate = this.props.cells[seg.col].date; + seg.top = this.computeDateTop(seg.start, dayDate); + seg.bottom = Math.max(seg.top + eventMinHeight, this.computeDateTop(seg.end, dayDate)); + } + }; + // Given segments that already have their top/bottom properties computed, applies those values to + // the segments' elements. + TimeGrid.prototype.assignSegVerticals = function (segs) { + var i; + var seg; + for (i = 0; i < segs.length; i++) { + seg = segs[i]; + applyStyle(seg.el, this.generateSegVerticalCss(seg)); + } + }; + // Generates an object with CSS properties for the top/bottom coordinates of a segment element + TimeGrid.prototype.generateSegVerticalCss = function (seg) { + return { + top: seg.top, + bottom: -seg.bottom // flipped because needs to be space beyond bottom edge of event container + }; + }; + /* Sizing + ------------------------------------------------------------------------------------------------------------------*/ + TimeGrid.prototype.buildPositionCaches = function () { + this.buildColPositions(); + this.buildSlatPositions(); + }; + TimeGrid.prototype.buildColPositions = function () { + this.colPositions.build(); + }; + TimeGrid.prototype.buildSlatPositions = function () { + this.slatPositions.build(); + }; + /* Hit System + ------------------------------------------------------------------------------------------------------------------*/ + TimeGrid.prototype.positionToHit = function (positionLeft, positionTop) { + var _a = this, dateEnv = _a.dateEnv, snapsPerSlot = _a.snapsPerSlot, slatPositions = _a.slatPositions, colPositions = _a.colPositions; + var colIndex = colPositions.leftToIndex(positionLeft); + var slatIndex = slatPositions.topToIndex(positionTop); + if (colIndex != null && slatIndex != null) { + var slatTop = slatPositions.tops[slatIndex]; + var slatHeight = slatPositions.getHeight(slatIndex); + var partial = (positionTop - slatTop) / slatHeight; // floating point number between 0 and 1 + var localSnapIndex = Math.floor(partial * snapsPerSlot); // the snap # relative to start of slat + var snapIndex = slatIndex * snapsPerSlot + localSnapIndex; + var dayDate = this.props.cells[colIndex].date; + var time = addDurations(this.props.dateProfile.minTime, multiplyDuration(this.snapDuration, snapIndex)); + var start = dateEnv.add(dayDate, time); + var end = dateEnv.add(start, this.snapDuration); + return { + col: colIndex, + dateSpan: { + range: { start: start, end: end }, + allDay: false + }, + dayEl: this.colEls[colIndex], + relativeRect: { + left: colPositions.lefts[colIndex], + right: colPositions.rights[colIndex], + top: slatTop, + bottom: slatTop + slatHeight + } + }; + } + }; + /* Event Drag Visualization + ------------------------------------------------------------------------------------------------------------------*/ + TimeGrid.prototype._renderEventDrag = function (state) { + if (state) { + this.eventRenderer.hideByHash(state.affectedInstances); + if (state.isEvent) { + this.mirrorRenderer.renderSegs(state.segs, { isDragging: true, sourceSeg: state.sourceSeg }); + } + else { + this.fillRenderer.renderSegs('highlight', state.segs); + } + } + }; + TimeGrid.prototype._unrenderEventDrag = function (state) { + if (state) { + this.eventRenderer.showByHash(state.affectedInstances); + this.mirrorRenderer.unrender(state.segs, { isDragging: true, sourceSeg: state.sourceSeg }); + this.fillRenderer.unrender('highlight'); + } + }; + /* Event Resize Visualization + ------------------------------------------------------------------------------------------------------------------*/ + TimeGrid.prototype._renderEventResize = function (state) { + if (state) { + this.eventRenderer.hideByHash(state.affectedInstances); + this.mirrorRenderer.renderSegs(state.segs, { isResizing: true, sourceSeg: state.sourceSeg }); + } + }; + TimeGrid.prototype._unrenderEventResize = function (state) { + if (state) { + this.eventRenderer.showByHash(state.affectedInstances); + this.mirrorRenderer.unrender(state.segs, { isResizing: true, sourceSeg: state.sourceSeg }); + } + }; + /* Selection + ------------------------------------------------------------------------------------------------------------------*/ + // Renders a visual indication of a selection. Overrides the default, which was to simply render a highlight. + TimeGrid.prototype._renderDateSelection = function (segs) { + if (segs) { + if (this.opt('selectMirror')) { + this.mirrorRenderer.renderSegs(segs, { isSelecting: true }); + } + else { + this.fillRenderer.renderSegs('highlight', segs); + } + } + }; + TimeGrid.prototype._unrenderDateSelection = function (segs) { + this.mirrorRenderer.unrender(segs, { isSelecting: true }); + this.fillRenderer.unrender('highlight'); + }; + return TimeGrid; +}(DateComponent)); + +var AllDaySplitter = /** @class */ (function (_super) { + __extends(AllDaySplitter, _super); + function AllDaySplitter() { + return _super !== null && _super.apply(this, arguments) || this; + } + AllDaySplitter.prototype.getKeyInfo = function () { + return { + allDay: {}, + timed: {} + }; + }; + AllDaySplitter.prototype.getKeysForDateSpan = function (dateSpan) { + if (dateSpan.allDay) { + return ['allDay']; + } + else { + return ['timed']; + } + }; + AllDaySplitter.prototype.getKeysForEventDef = function (eventDef) { + if (!eventDef.allDay) { + return ['timed']; + } + else if (hasBgRendering(eventDef)) { + return ['timed', 'allDay']; + } + else { + return ['allDay']; + } + }; + return AllDaySplitter; +}(Splitter)); + +var TIMEGRID_ALL_DAY_EVENT_LIMIT = 5; +var WEEK_HEADER_FORMAT = createFormatter({ week: 'short' }); +/* An abstract class for all timegrid-related views. Displays one more columns with time slots running vertically. +----------------------------------------------------------------------------------------------------------------------*/ +// Is a manager for the TimeGrid subcomponent and possibly the DayGrid subcomponent (if allDaySlot is on). +// Responsible for managing width/height. +var TimeGridView = /** @class */ (function (_super) { + __extends(TimeGridView, _super); + function TimeGridView(context, viewSpec, dateProfileGenerator, parentEl) { + var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this; + _this.splitter = new AllDaySplitter(); + /* Header Render Methods + ------------------------------------------------------------------------------------------------------------------*/ + // Generates the HTML that will go before the day-of week header cells + _this.renderHeadIntroHtml = function () { + var _a = _this, theme = _a.theme, dateEnv = _a.dateEnv; + var range = _this.props.dateProfile.renderRange; + var dayCnt = diffDays(range.start, range.end); + var weekText; + if (_this.opt('weekNumbers')) { + weekText = dateEnv.format(range.start, WEEK_HEADER_FORMAT); + return '' + + '<th class="fc-axis fc-week-number ' + theme.getClass('widgetHeader') + '" ' + _this.axisStyleAttr() + '>' + + buildGotoAnchorHtml(// aside from link, important for matchCellWidths + _this, { date: range.start, type: 'week', forceOff: dayCnt > 1 }, htmlEscape(weekText) // inner HTML + ) + + '</th>'; + } + else { + return '<th class="fc-axis ' + theme.getClass('widgetHeader') + '" ' + _this.axisStyleAttr() + '></th>'; + } + }; + /* Time Grid Render Methods + ------------------------------------------------------------------------------------------------------------------*/ + // Generates the HTML that goes before the bg of the TimeGrid slot area. Long vertical column. + _this.renderTimeGridBgIntroHtml = function () { + var theme = _this.theme; + return '<td class="fc-axis ' + theme.getClass('widgetContent') + '" ' + _this.axisStyleAttr() + '></td>'; + }; + // Generates the HTML that goes before all other types of cells. + // Affects content-skeleton, mirror-skeleton, highlight-skeleton for both the time-grid and day-grid. + _this.renderTimeGridIntroHtml = function () { + return '<td class="fc-axis" ' + _this.axisStyleAttr() + '></td>'; + }; + /* Day Grid Render Methods + ------------------------------------------------------------------------------------------------------------------*/ + // Generates the HTML that goes before the all-day cells + _this.renderDayGridBgIntroHtml = function () { + var theme = _this.theme; + return '' + + '<td class="fc-axis ' + theme.getClass('widgetContent') + '" ' + _this.axisStyleAttr() + '>' + + '<span>' + // needed for matchCellWidths + getAllDayHtml(_this) + + '</span>' + + '</td>'; + }; + // Generates the HTML that goes before all other types of cells. + // Affects content-skeleton, mirror-skeleton, highlight-skeleton for both the time-grid and day-grid. + _this.renderDayGridIntroHtml = function () { + return '<td class="fc-axis" ' + _this.axisStyleAttr() + '></td>'; + }; + _this.el.classList.add('fc-timeGrid-view'); + _this.el.innerHTML = _this.renderSkeletonHtml(); + _this.scroller = new ScrollComponent('hidden', // overflow x + 'auto' // overflow y + ); + var timeGridWrapEl = _this.scroller.el; + _this.el.querySelector('.fc-body > tr > td').appendChild(timeGridWrapEl); + timeGridWrapEl.classList.add('fc-time-grid-container'); + var timeGridEl = createElement('div', { className: 'fc-time-grid' }); + timeGridWrapEl.appendChild(timeGridEl); + _this.timeGrid = new TimeGrid(_this.context, timeGridEl, { + renderBgIntroHtml: _this.renderTimeGridBgIntroHtml, + renderIntroHtml: _this.renderTimeGridIntroHtml + }); + if (_this.opt('allDaySlot')) { // should we display the "all-day" area? + _this.dayGrid = new DayGrid(// the all-day subcomponent of this view + _this.context, _this.el.querySelector('.fc-day-grid'), { + renderNumberIntroHtml: _this.renderDayGridIntroHtml, + renderBgIntroHtml: _this.renderDayGridBgIntroHtml, + renderIntroHtml: _this.renderDayGridIntroHtml, + colWeekNumbersVisible: false, + cellWeekNumbersVisible: false + }); + // have the day-grid extend it's coordinate area over the <hr> dividing the two grids + var dividerEl = _this.el.querySelector('.fc-divider'); + _this.dayGrid.bottomCoordPadding = dividerEl.getBoundingClientRect().height; + } + return _this; + } + TimeGridView.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.timeGrid.destroy(); + if (this.dayGrid) { + this.dayGrid.destroy(); + } + this.scroller.destroy(); + }; + /* Rendering + ------------------------------------------------------------------------------------------------------------------*/ + // Builds the HTML skeleton for the view. + // The day-grid and time-grid components will render inside containers defined by this HTML. + TimeGridView.prototype.renderSkeletonHtml = function () { + var theme = this.theme; + return '' + + '<table class="' + theme.getClass('tableGrid') + '">' + + (this.opt('columnHeader') ? + '<thead class="fc-head">' + + '<tr>' + + '<td class="fc-head-container ' + theme.getClass('widgetHeader') + '"> </td>' + + '</tr>' + + '</thead>' : + '') + + '<tbody class="fc-body">' + + '<tr>' + + '<td class="' + theme.getClass('widgetContent') + '">' + + (this.opt('allDaySlot') ? + '<div class="fc-day-grid"></div>' + + '<hr class="fc-divider ' + theme.getClass('widgetHeader') + '" />' : + '') + + '</td>' + + '</tr>' + + '</tbody>' + + '</table>'; + }; + /* Now Indicator + ------------------------------------------------------------------------------------------------------------------*/ + TimeGridView.prototype.getNowIndicatorUnit = function () { + return this.timeGrid.getNowIndicatorUnit(); + }; + // subclasses should implement + // renderNowIndicator(date: DateMarker) { + // } + TimeGridView.prototype.unrenderNowIndicator = function () { + this.timeGrid.unrenderNowIndicator(); + }; + /* Dimensions + ------------------------------------------------------------------------------------------------------------------*/ + TimeGridView.prototype.updateSize = function (isResize, viewHeight, isAuto) { + _super.prototype.updateSize.call(this, isResize, viewHeight, isAuto); // will call updateBaseSize. important that executes first + this.timeGrid.updateSize(isResize); + if (this.dayGrid) { + this.dayGrid.updateSize(isResize); + } + }; + // Adjusts the vertical dimensions of the view to the specified values + TimeGridView.prototype.updateBaseSize = function (isResize, viewHeight, isAuto) { + var _this = this; + var eventLimit; + var scrollerHeight; + var scrollbarWidths; + // make all axis cells line up + this.axisWidth = matchCellWidths(findElements(this.el, '.fc-axis')); + // hack to give the view some height prior to timeGrid's columns being rendered + // TODO: separate setting height from scroller VS timeGrid. + if (!this.timeGrid.colEls) { + if (!isAuto) { + scrollerHeight = this.computeScrollerHeight(viewHeight); + this.scroller.setHeight(scrollerHeight); + } + return; + } + // set of fake row elements that must compensate when scroller has scrollbars + var noScrollRowEls = findElements(this.el, '.fc-row').filter(function (node) { + return !_this.scroller.el.contains(node); + }); + // reset all dimensions back to the original state + this.timeGrid.bottomRuleEl.style.display = 'none'; // will be shown later if this <hr> is necessary + this.scroller.clear(); // sets height to 'auto' and clears overflow + noScrollRowEls.forEach(uncompensateScroll); + // limit number of events in the all-day area + if (this.dayGrid) { + this.dayGrid.removeSegPopover(); // kill the "more" popover if displayed + eventLimit = this.opt('eventLimit'); + if (eventLimit && typeof eventLimit !== 'number') { + eventLimit = TIMEGRID_ALL_DAY_EVENT_LIMIT; // make sure "auto" goes to a real number + } + if (eventLimit) { + this.dayGrid.limitRows(eventLimit); + } + } + if (!isAuto) { // should we force dimensions of the scroll container? + scrollerHeight = this.computeScrollerHeight(viewHeight); + this.scroller.setHeight(scrollerHeight); + scrollbarWidths = this.scroller.getScrollbarWidths(); + if (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars? + // make the all-day and header rows lines up + noScrollRowEls.forEach(function (rowEl) { + compensateScroll(rowEl, scrollbarWidths); + }); + // the scrollbar compensation might have changed text flow, which might affect height, so recalculate + // and reapply the desired height to the scroller. + scrollerHeight = this.computeScrollerHeight(viewHeight); + this.scroller.setHeight(scrollerHeight); + } + // guarantees the same scrollbar widths + this.scroller.lockOverflow(scrollbarWidths); + // if there's any space below the slats, show the horizontal rule. + // this won't cause any new overflow, because lockOverflow already called. + if (this.timeGrid.getTotalSlatHeight() < scrollerHeight) { + this.timeGrid.bottomRuleEl.style.display = ''; + } + } + }; + // given a desired total height of the view, returns what the height of the scroller should be + TimeGridView.prototype.computeScrollerHeight = function (viewHeight) { + return viewHeight - + subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller + }; + /* Scroll + ------------------------------------------------------------------------------------------------------------------*/ + // Computes the initial pre-configured scroll state prior to allowing the user to change it + TimeGridView.prototype.computeDateScroll = function (duration) { + var top = this.timeGrid.computeTimeTop(duration); + // zoom can give weird floating-point values. rather scroll a little bit further + top = Math.ceil(top); + if (top) { + top++; // to overcome top border that slots beyond the first have. looks better + } + return { top: top }; + }; + TimeGridView.prototype.queryDateScroll = function () { + return { top: this.scroller.getScrollTop() }; + }; + TimeGridView.prototype.applyDateScroll = function (scroll) { + if (scroll.top !== undefined) { + this.scroller.setScrollTop(scroll.top); + } + }; + // Generates an HTML attribute string for setting the width of the axis, if it is known + TimeGridView.prototype.axisStyleAttr = function () { + if (this.axisWidth != null) { + return 'style="width:' + this.axisWidth + 'px"'; + } + return ''; + }; + return TimeGridView; +}(View)); +TimeGridView.prototype.usesMinMaxTime = true; // indicates that minTime/maxTime affects rendering + +var SimpleTimeGrid = /** @class */ (function (_super) { + __extends(SimpleTimeGrid, _super); + function SimpleTimeGrid(context, timeGrid) { + var _this = _super.call(this, context, timeGrid.el) || this; + _this.buildDayRanges = memoize(buildDayRanges); + _this.slicer = new TimeGridSlicer(); + _this.timeGrid = timeGrid; + context.calendar.registerInteractiveComponent(_this, { + el: _this.timeGrid.el + }); + return _this; + } + SimpleTimeGrid.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.calendar.unregisterInteractiveComponent(this); + }; + SimpleTimeGrid.prototype.render = function (props) { + var dateProfile = props.dateProfile, dayTable = props.dayTable; + var dayRanges = this.dayRanges = this.buildDayRanges(dayTable, dateProfile, this.dateEnv); + this.timeGrid.receiveProps(__assign({}, this.slicer.sliceProps(props, dateProfile, null, this.timeGrid, dayRanges), { dateProfile: dateProfile, cells: dayTable.cells[0] })); + }; + SimpleTimeGrid.prototype.renderNowIndicator = function (date) { + this.timeGrid.renderNowIndicator(this.slicer.sliceNowDate(date, this.timeGrid, this.dayRanges), date); + }; + SimpleTimeGrid.prototype.buildPositionCaches = function () { + this.timeGrid.buildPositionCaches(); + }; + SimpleTimeGrid.prototype.queryHit = function (positionLeft, positionTop) { + var rawHit = this.timeGrid.positionToHit(positionLeft, positionTop); + if (rawHit) { + return { + component: this.timeGrid, + dateSpan: rawHit.dateSpan, + dayEl: rawHit.dayEl, + rect: { + left: rawHit.relativeRect.left, + right: rawHit.relativeRect.right, + top: rawHit.relativeRect.top, + bottom: rawHit.relativeRect.bottom + }, + layer: 0 + }; + } + }; + return SimpleTimeGrid; +}(DateComponent)); +function buildDayRanges(dayTable, dateProfile, dateEnv) { + var ranges = []; + for (var _i = 0, _a = dayTable.headerDates; _i < _a.length; _i++) { + var date = _a[_i]; + ranges.push({ + start: dateEnv.add(date, dateProfile.minTime), + end: dateEnv.add(date, dateProfile.maxTime) + }); + } + return ranges; +} +var TimeGridSlicer = /** @class */ (function (_super) { + __extends(TimeGridSlicer, _super); + function TimeGridSlicer() { + return _super !== null && _super.apply(this, arguments) || this; + } + TimeGridSlicer.prototype.sliceRange = function (range, dayRanges) { + var segs = []; + for (var col = 0; col < dayRanges.length; col++) { + var segRange = intersectRanges(range, dayRanges[col]); + if (segRange) { + segs.push({ + start: segRange.start, + end: segRange.end, + isStart: segRange.start.valueOf() === range.start.valueOf(), + isEnd: segRange.end.valueOf() === range.end.valueOf(), + col: col + }); + } + } + return segs; + }; + return TimeGridSlicer; +}(Slicer)); + +var TimeGridView$1 = /** @class */ (function (_super) { + __extends(TimeGridView, _super); + function TimeGridView(_context, viewSpec, dateProfileGenerator, parentEl) { + var _this = _super.call(this, _context, viewSpec, dateProfileGenerator, parentEl) || this; + _this.buildDayTable = memoize(buildDayTable); + if (_this.opt('columnHeader')) { + _this.header = new DayHeader(_this.context, _this.el.querySelector('.fc-head-container')); + } + _this.simpleTimeGrid = new SimpleTimeGrid(_this.context, _this.timeGrid); + if (_this.dayGrid) { + _this.simpleDayGrid = new SimpleDayGrid(_this.context, _this.dayGrid); + } + return _this; + } + TimeGridView.prototype.destroy = function () { + _super.prototype.destroy.call(this); + if (this.header) { + this.header.destroy(); + } + this.simpleTimeGrid.destroy(); + if (this.simpleDayGrid) { + this.simpleDayGrid.destroy(); + } + }; + TimeGridView.prototype.render = function (props) { + _super.prototype.render.call(this, props); // for flags for updateSize + var dateProfile = this.props.dateProfile; + var dayTable = this.buildDayTable(dateProfile, this.dateProfileGenerator); + var splitProps = this.splitter.splitProps(props); + if (this.header) { + this.header.receiveProps({ + dateProfile: dateProfile, + dates: dayTable.headerDates, + datesRepDistinctDays: true, + renderIntroHtml: this.renderHeadIntroHtml + }); + } + this.simpleTimeGrid.receiveProps(__assign({}, splitProps['timed'], { dateProfile: dateProfile, + dayTable: dayTable })); + if (this.simpleDayGrid) { + this.simpleDayGrid.receiveProps(__assign({}, splitProps['allDay'], { dateProfile: dateProfile, + dayTable: dayTable, nextDayThreshold: this.nextDayThreshold, isRigid: false })); + } + }; + TimeGridView.prototype.renderNowIndicator = function (date) { + this.simpleTimeGrid.renderNowIndicator(date); + }; + return TimeGridView; +}(TimeGridView)); +function buildDayTable(dateProfile, dateProfileGenerator) { + var daySeries = new DaySeries(dateProfile.renderRange, dateProfileGenerator); + return new DayTable(daySeries, false); +} + +var main = createPlugin({ + defaultView: 'timeGridWeek', + views: { + timeGrid: { + class: TimeGridView$1, + allDaySlot: true, + slotDuration: '00:30:00', + slotEventOverlap: true // a bad name. confused with overlap/constraint system + }, + timeGridDay: { + type: 'timeGrid', + duration: { days: 1 } + }, + timeGridWeek: { + type: 'timeGrid', + duration: { weeks: 1 } + } + } +}); + +export default main; +export { TimeGridView as AbstractTimeGridView, TimeGrid, TimeGridSlicer, TimeGridView$1 as TimeGridView, buildDayRanges, buildDayTable }; diff --git a/AKPlan/static/AKPlan/fullcalendar/timegrid/main.js b/AKPlan/static/AKPlan/fullcalendar/timegrid/main.js new file mode 100644 index 00000000..470925e8 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/timegrid/main.js @@ -0,0 +1,1357 @@ +/*! +FullCalendar Time Grid Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core'), require('@fullcalendar/daygrid')) : + typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core', '@fullcalendar/daygrid'], factory) : + (global = global || self, factory(global.FullCalendarTimeGrid = {}, global.FullCalendar, global.FullCalendarDayGrid)); +}(this, function (exports, core, daygrid) { 'use strict'; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + /* + Only handles foreground segs. + Does not own rendering. Use for low-level util methods by TimeGrid. + */ + var TimeGridEventRenderer = /** @class */ (function (_super) { + __extends(TimeGridEventRenderer, _super); + function TimeGridEventRenderer(timeGrid) { + var _this = _super.call(this, timeGrid.context) || this; + _this.timeGrid = timeGrid; + _this.fullTimeFormat = core.createFormatter({ + hour: 'numeric', + minute: '2-digit', + separator: _this.context.options.defaultRangeSeparator + }); + return _this; + } + // Given an array of foreground segments, render a DOM element for each, computes position, + // and attaches to the column inner-container elements. + TimeGridEventRenderer.prototype.attachSegs = function (segs, mirrorInfo) { + var segsByCol = this.timeGrid.groupSegsByCol(segs); + // order the segs within each column + // TODO: have groupSegsByCol do this? + for (var col = 0; col < segsByCol.length; col++) { + segsByCol[col] = this.sortEventSegs(segsByCol[col]); + } + this.segsByCol = segsByCol; + this.timeGrid.attachSegsByCol(segsByCol, this.timeGrid.fgContainerEls); + }; + TimeGridEventRenderer.prototype.detachSegs = function (segs) { + segs.forEach(function (seg) { + core.removeElement(seg.el); + }); + this.segsByCol = null; + }; + TimeGridEventRenderer.prototype.computeSegSizes = function (allSegs) { + var _a = this, timeGrid = _a.timeGrid, segsByCol = _a.segsByCol; + var colCnt = timeGrid.colCnt; + timeGrid.computeSegVerticals(allSegs); // horizontals relies on this + if (segsByCol) { + for (var col = 0; col < colCnt; col++) { + this.computeSegHorizontals(segsByCol[col]); // compute horizontal coordinates, z-index's, and reorder the array + } + } + }; + TimeGridEventRenderer.prototype.assignSegSizes = function (allSegs) { + var _a = this, timeGrid = _a.timeGrid, segsByCol = _a.segsByCol; + var colCnt = timeGrid.colCnt; + timeGrid.assignSegVerticals(allSegs); // horizontals relies on this + if (segsByCol) { + for (var col = 0; col < colCnt; col++) { + this.assignSegCss(segsByCol[col]); + } + } + }; + // Computes a default event time formatting string if `eventTimeFormat` is not explicitly defined + TimeGridEventRenderer.prototype.computeEventTimeFormat = function () { + return { + hour: 'numeric', + minute: '2-digit', + meridiem: false + }; + }; + // Computes a default `displayEventEnd` value if one is not expliclty defined + TimeGridEventRenderer.prototype.computeDisplayEventEnd = function () { + return true; + }; + // Renders the HTML for a single event segment's default rendering + TimeGridEventRenderer.prototype.renderSegHtml = function (seg, mirrorInfo) { + var view = this.context.view; + var eventRange = seg.eventRange; + var eventDef = eventRange.def; + var eventUi = eventRange.ui; + var allDay = eventDef.allDay; + var isDraggable = view.computeEventDraggable(eventDef, eventUi); + var isResizableFromStart = seg.isStart && view.computeEventStartResizable(eventDef, eventUi); + var isResizableFromEnd = seg.isEnd && view.computeEventEndResizable(eventDef, eventUi); + var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd, mirrorInfo); + var skinCss = core.cssToStr(this.getSkinCss(eventUi)); + var timeText; + var fullTimeText; // more verbose time text. for the print stylesheet + var startTimeText; // just the start time text + classes.unshift('fc-time-grid-event'); + // if the event appears to span more than one day... + if (core.isMultiDayRange(eventRange.range)) { + // Don't display time text on segments that run entirely through a day. + // That would appear as midnight-midnight and would look dumb. + // Otherwise, display the time text for the *segment's* times (like 6pm-midnight or midnight-10am) + if (seg.isStart || seg.isEnd) { + var unzonedStart = seg.start; + var unzonedEnd = seg.end; + timeText = this._getTimeText(unzonedStart, unzonedEnd, allDay); // TODO: give the timezones + fullTimeText = this._getTimeText(unzonedStart, unzonedEnd, allDay, this.fullTimeFormat); + startTimeText = this._getTimeText(unzonedStart, unzonedEnd, allDay, null, false); // displayEnd=false + } + } + else { + // Display the normal time text for the *event's* times + timeText = this.getTimeText(eventRange); + fullTimeText = this.getTimeText(eventRange, this.fullTimeFormat); + startTimeText = this.getTimeText(eventRange, null, false); // displayEnd=false + } + return '<a class="' + classes.join(' ') + '"' + + (eventDef.url ? + ' href="' + core.htmlEscape(eventDef.url) + '"' : + '') + + (skinCss ? + ' style="' + skinCss + '"' : + '') + + '>' + + '<div class="fc-content">' + + (timeText ? + '<div class="fc-time"' + + ' data-start="' + core.htmlEscape(startTimeText) + '"' + + ' data-full="' + core.htmlEscape(fullTimeText) + '"' + + '>' + + '<span>' + core.htmlEscape(timeText) + '</span>' + + '</div>' : + '') + + (eventDef.title ? + '<div class="fc-title">' + + core.htmlEscape(eventDef.title) + + '</div>' : + '') + + '</div>' + + /* TODO: write CSS for this + (isResizableFromStart ? + '<div class="fc-resizer fc-start-resizer"></div>' : + '' + ) + + */ + (isResizableFromEnd ? + '<div class="fc-resizer fc-end-resizer"></div>' : + '') + + '</a>'; + }; + // Given an array of segments that are all in the same column, sets the backwardCoord and forwardCoord on each. + // Assumed the segs are already ordered. + // NOTE: Also reorders the given array by date! + TimeGridEventRenderer.prototype.computeSegHorizontals = function (segs) { + var levels; + var level0; + var i; + levels = buildSlotSegLevels(segs); + computeForwardSlotSegs(levels); + if ((level0 = levels[0])) { + for (i = 0; i < level0.length; i++) { + computeSlotSegPressures(level0[i]); + } + for (i = 0; i < level0.length; i++) { + this.computeSegForwardBack(level0[i], 0, 0); + } + } + }; + // Calculate seg.forwardCoord and seg.backwardCoord for the segment, where both values range + // from 0 to 1. If the calendar is left-to-right, the seg.backwardCoord maps to "left" and + // seg.forwardCoord maps to "right" (via percentage). Vice-versa if the calendar is right-to-left. + // + // The segment might be part of a "series", which means consecutive segments with the same pressure + // who's width is unknown until an edge has been hit. `seriesBackwardPressure` is the number of + // segments behind this one in the current series, and `seriesBackwardCoord` is the starting + // coordinate of the first segment in the series. + TimeGridEventRenderer.prototype.computeSegForwardBack = function (seg, seriesBackwardPressure, seriesBackwardCoord) { + var forwardSegs = seg.forwardSegs; + var i; + if (seg.forwardCoord === undefined) { // not already computed + if (!forwardSegs.length) { + // if there are no forward segments, this segment should butt up against the edge + seg.forwardCoord = 1; + } + else { + // sort highest pressure first + this.sortForwardSegs(forwardSegs); + // this segment's forwardCoord will be calculated from the backwardCoord of the + // highest-pressure forward segment. + this.computeSegForwardBack(forwardSegs[0], seriesBackwardPressure + 1, seriesBackwardCoord); + seg.forwardCoord = forwardSegs[0].backwardCoord; + } + // calculate the backwardCoord from the forwardCoord. consider the series + seg.backwardCoord = seg.forwardCoord - + (seg.forwardCoord - seriesBackwardCoord) / // available width for series + (seriesBackwardPressure + 1); // # of segments in the series + // use this segment's coordinates to computed the coordinates of the less-pressurized + // forward segments + for (i = 0; i < forwardSegs.length; i++) { + this.computeSegForwardBack(forwardSegs[i], 0, seg.forwardCoord); + } + } + }; + TimeGridEventRenderer.prototype.sortForwardSegs = function (forwardSegs) { + var objs = forwardSegs.map(buildTimeGridSegCompareObj); + var specs = [ + // put higher-pressure first + { field: 'forwardPressure', order: -1 }, + // put segments that are closer to initial edge first (and favor ones with no coords yet) + { field: 'backwardCoord', order: 1 } + ].concat(this.context.view.eventOrderSpecs); + objs.sort(function (obj0, obj1) { + return core.compareByFieldSpecs(obj0, obj1, specs); + }); + return objs.map(function (c) { + return c._seg; + }); + }; + // Given foreground event segments that have already had their position coordinates computed, + // assigns position-related CSS values to their elements. + TimeGridEventRenderer.prototype.assignSegCss = function (segs) { + for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { + var seg = segs_1[_i]; + core.applyStyle(seg.el, this.generateSegCss(seg)); + if (seg.level > 0) { + seg.el.classList.add('fc-time-grid-event-inset'); + } + // if the event is short that the title will be cut off, + // attach a className that condenses the title into the time area. + if (seg.eventRange.def.title && seg.bottom - seg.top < 30) { + seg.el.classList.add('fc-short'); // TODO: "condensed" is a better name + } + } + }; + // Generates an object with CSS properties/values that should be applied to an event segment element. + // Contains important positioning-related properties that should be applied to any event element, customized or not. + TimeGridEventRenderer.prototype.generateSegCss = function (seg) { + var shouldOverlap = this.context.options.slotEventOverlap; + var backwardCoord = seg.backwardCoord; // the left side if LTR. the right side if RTL. floating-point + var forwardCoord = seg.forwardCoord; // the right side if LTR. the left side if RTL. floating-point + var props = this.timeGrid.generateSegVerticalCss(seg); // get top/bottom first + var isRtl = this.timeGrid.isRtl; + var left; // amount of space from left edge, a fraction of the total width + var right; // amount of space from right edge, a fraction of the total width + if (shouldOverlap) { + // double the width, but don't go beyond the maximum forward coordinate (1.0) + forwardCoord = Math.min(1, backwardCoord + (forwardCoord - backwardCoord) * 2); + } + if (isRtl) { + left = 1 - forwardCoord; + right = backwardCoord; + } + else { + left = backwardCoord; + right = 1 - forwardCoord; + } + props.zIndex = seg.level + 1; // convert from 0-base to 1-based + props.left = left * 100 + '%'; + props.right = right * 100 + '%'; + if (shouldOverlap && seg.forwardPressure) { + // add padding to the edge so that forward stacked events don't cover the resizer's icon + props[isRtl ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width + } + return props; + }; + return TimeGridEventRenderer; + }(core.FgEventRenderer)); + // Builds an array of segments "levels". The first level will be the leftmost tier of segments if the calendar is + // left-to-right, or the rightmost if the calendar is right-to-left. Assumes the segments are already ordered by date. + function buildSlotSegLevels(segs) { + var levels = []; + var i; + var seg; + var j; + for (i = 0; i < segs.length; i++) { + seg = segs[i]; + // go through all the levels and stop on the first level where there are no collisions + for (j = 0; j < levels.length; j++) { + if (!computeSlotSegCollisions(seg, levels[j]).length) { + break; + } + } + seg.level = j; + (levels[j] || (levels[j] = [])).push(seg); + } + return levels; + } + // For every segment, figure out the other segments that are in subsequent + // levels that also occupy the same vertical space. Accumulate in seg.forwardSegs + function computeForwardSlotSegs(levels) { + var i; + var level; + var j; + var seg; + var k; + for (i = 0; i < levels.length; i++) { + level = levels[i]; + for (j = 0; j < level.length; j++) { + seg = level[j]; + seg.forwardSegs = []; + for (k = i + 1; k < levels.length; k++) { + computeSlotSegCollisions(seg, levels[k], seg.forwardSegs); + } + } + } + } + // Figure out which path forward (via seg.forwardSegs) results in the longest path until + // the furthest edge is reached. The number of segments in this path will be seg.forwardPressure + function computeSlotSegPressures(seg) { + var forwardSegs = seg.forwardSegs; + var forwardPressure = 0; + var i; + var forwardSeg; + if (seg.forwardPressure === undefined) { // not already computed + for (i = 0; i < forwardSegs.length; i++) { + forwardSeg = forwardSegs[i]; + // figure out the child's maximum forward path + computeSlotSegPressures(forwardSeg); + // either use the existing maximum, or use the child's forward pressure + // plus one (for the forwardSeg itself) + forwardPressure = Math.max(forwardPressure, 1 + forwardSeg.forwardPressure); + } + seg.forwardPressure = forwardPressure; + } + } + // Find all the segments in `otherSegs` that vertically collide with `seg`. + // Append into an optionally-supplied `results` array and return. + function computeSlotSegCollisions(seg, otherSegs, results) { + if (results === void 0) { results = []; } + for (var i = 0; i < otherSegs.length; i++) { + if (isSlotSegCollision(seg, otherSegs[i])) { + results.push(otherSegs[i]); + } + } + return results; + } + // Do these segments occupy the same vertical space? + function isSlotSegCollision(seg1, seg2) { + return seg1.bottom > seg2.top && seg1.top < seg2.bottom; + } + function buildTimeGridSegCompareObj(seg) { + var obj = core.buildSegCompareObj(seg); + obj.forwardPressure = seg.forwardPressure; + obj.backwardCoord = seg.backwardCoord; + return obj; + } + + var TimeGridMirrorRenderer = /** @class */ (function (_super) { + __extends(TimeGridMirrorRenderer, _super); + function TimeGridMirrorRenderer() { + return _super !== null && _super.apply(this, arguments) || this; + } + TimeGridMirrorRenderer.prototype.attachSegs = function (segs, mirrorInfo) { + this.segsByCol = this.timeGrid.groupSegsByCol(segs); + this.timeGrid.attachSegsByCol(this.segsByCol, this.timeGrid.mirrorContainerEls); + this.sourceSeg = mirrorInfo.sourceSeg; + }; + TimeGridMirrorRenderer.prototype.generateSegCss = function (seg) { + var props = _super.prototype.generateSegCss.call(this, seg); + var sourceSeg = this.sourceSeg; + if (sourceSeg && sourceSeg.col === seg.col) { + var sourceSegProps = _super.prototype.generateSegCss.call(this, sourceSeg); + props.left = sourceSegProps.left; + props.right = sourceSegProps.right; + props.marginLeft = sourceSegProps.marginLeft; + props.marginRight = sourceSegProps.marginRight; + } + return props; + }; + return TimeGridMirrorRenderer; + }(TimeGridEventRenderer)); + + var TimeGridFillRenderer = /** @class */ (function (_super) { + __extends(TimeGridFillRenderer, _super); + function TimeGridFillRenderer(timeGrid) { + var _this = _super.call(this, timeGrid.context) || this; + _this.timeGrid = timeGrid; + return _this; + } + TimeGridFillRenderer.prototype.attachSegs = function (type, segs) { + var timeGrid = this.timeGrid; + var containerEls; + // TODO: more efficient lookup + if (type === 'bgEvent') { + containerEls = timeGrid.bgContainerEls; + } + else if (type === 'businessHours') { + containerEls = timeGrid.businessContainerEls; + } + else if (type === 'highlight') { + containerEls = timeGrid.highlightContainerEls; + } + timeGrid.attachSegsByCol(timeGrid.groupSegsByCol(segs), containerEls); + return segs.map(function (seg) { + return seg.el; + }); + }; + TimeGridFillRenderer.prototype.computeSegSizes = function (segs) { + this.timeGrid.computeSegVerticals(segs); + }; + TimeGridFillRenderer.prototype.assignSegSizes = function (segs) { + this.timeGrid.assignSegVerticals(segs); + }; + return TimeGridFillRenderer; + }(core.FillRenderer)); + + /* A component that renders one or more columns of vertical time slots + ----------------------------------------------------------------------------------------------------------------------*/ + // potential nice values for the slot-duration and interval-duration + // from largest to smallest + var AGENDA_STOCK_SUB_DURATIONS = [ + { hours: 1 }, + { minutes: 30 }, + { minutes: 15 }, + { seconds: 30 }, + { seconds: 15 } + ]; + var TimeGrid = /** @class */ (function (_super) { + __extends(TimeGrid, _super); + function TimeGrid(context, el, renderProps) { + var _this = _super.call(this, context, el) || this; + _this.isSlatSizesDirty = false; + _this.isColSizesDirty = false; + _this.renderSlats = core.memoizeRendering(_this._renderSlats); + var eventRenderer = _this.eventRenderer = new TimeGridEventRenderer(_this); + var fillRenderer = _this.fillRenderer = new TimeGridFillRenderer(_this); + _this.mirrorRenderer = new TimeGridMirrorRenderer(_this); + var renderColumns = _this.renderColumns = core.memoizeRendering(_this._renderColumns, _this._unrenderColumns); + _this.renderBusinessHours = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'businessHours'), fillRenderer.unrender.bind(fillRenderer, 'businessHours'), [renderColumns]); + _this.renderDateSelection = core.memoizeRendering(_this._renderDateSelection, _this._unrenderDateSelection, [renderColumns]); + _this.renderFgEvents = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer), [renderColumns]); + _this.renderBgEvents = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'bgEvent'), fillRenderer.unrender.bind(fillRenderer, 'bgEvent'), [renderColumns]); + _this.renderEventSelection = core.memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]); + _this.renderEventDrag = core.memoizeRendering(_this._renderEventDrag, _this._unrenderEventDrag, [renderColumns]); + _this.renderEventResize = core.memoizeRendering(_this._renderEventResize, _this._unrenderEventResize, [renderColumns]); + _this.processOptions(); + el.innerHTML = + '<div class="fc-bg"></div>' + + '<div class="fc-slats"></div>' + + '<hr class="fc-divider ' + _this.theme.getClass('widgetHeader') + '" style="display:none" />'; + _this.rootBgContainerEl = el.querySelector('.fc-bg'); + _this.slatContainerEl = el.querySelector('.fc-slats'); + _this.bottomRuleEl = el.querySelector('.fc-divider'); + _this.renderProps = renderProps; + return _this; + } + /* Options + ------------------------------------------------------------------------------------------------------------------*/ + // Parses various options into properties of this object + TimeGrid.prototype.processOptions = function () { + var slotDuration = this.opt('slotDuration'); + var snapDuration = this.opt('snapDuration'); + var snapsPerSlot; + var input; + slotDuration = core.createDuration(slotDuration); + snapDuration = snapDuration ? core.createDuration(snapDuration) : slotDuration; + snapsPerSlot = core.wholeDivideDurations(slotDuration, snapDuration); + if (snapsPerSlot === null) { + snapDuration = slotDuration; + snapsPerSlot = 1; + // TODO: say warning? + } + this.slotDuration = slotDuration; + this.snapDuration = snapDuration; + this.snapsPerSlot = snapsPerSlot; + // might be an array value (for TimelineView). + // if so, getting the most granular entry (the last one probably). + input = this.opt('slotLabelFormat'); + if (Array.isArray(input)) { + input = input[input.length - 1]; + } + this.labelFormat = core.createFormatter(input || { + hour: 'numeric', + minute: '2-digit', + omitZeroMinute: true, + meridiem: 'short' + }); + input = this.opt('slotLabelInterval'); + this.labelInterval = input ? + core.createDuration(input) : + this.computeLabelInterval(slotDuration); + }; + // Computes an automatic value for slotLabelInterval + TimeGrid.prototype.computeLabelInterval = function (slotDuration) { + var i; + var labelInterval; + var slotsPerLabel; + // find the smallest stock label interval that results in more than one slots-per-label + for (i = AGENDA_STOCK_SUB_DURATIONS.length - 1; i >= 0; i--) { + labelInterval = core.createDuration(AGENDA_STOCK_SUB_DURATIONS[i]); + slotsPerLabel = core.wholeDivideDurations(labelInterval, slotDuration); + if (slotsPerLabel !== null && slotsPerLabel > 1) { + return labelInterval; + } + } + return slotDuration; // fall back + }; + /* Rendering + ------------------------------------------------------------------------------------------------------------------*/ + TimeGrid.prototype.render = function (props) { + var cells = props.cells; + this.colCnt = cells.length; + this.renderSlats(props.dateProfile); + this.renderColumns(props.cells, props.dateProfile); + this.renderBusinessHours(props.businessHourSegs); + this.renderDateSelection(props.dateSelectionSegs); + this.renderFgEvents(props.fgEventSegs); + this.renderBgEvents(props.bgEventSegs); + this.renderEventSelection(props.eventSelection); + this.renderEventDrag(props.eventDrag); + this.renderEventResize(props.eventResize); + }; + TimeGrid.prototype.destroy = function () { + _super.prototype.destroy.call(this); + // should unrender everything else too + this.renderSlats.unrender(); + this.renderColumns.unrender(); + }; + TimeGrid.prototype.updateSize = function (isResize) { + var _a = this, fillRenderer = _a.fillRenderer, eventRenderer = _a.eventRenderer, mirrorRenderer = _a.mirrorRenderer; + if (isResize || this.isSlatSizesDirty) { + this.buildSlatPositions(); + this.isSlatSizesDirty = false; + } + if (isResize || this.isColSizesDirty) { + this.buildColPositions(); + this.isColSizesDirty = false; + } + fillRenderer.computeSizes(isResize); + eventRenderer.computeSizes(isResize); + mirrorRenderer.computeSizes(isResize); + fillRenderer.assignSizes(isResize); + eventRenderer.assignSizes(isResize); + mirrorRenderer.assignSizes(isResize); + }; + TimeGrid.prototype._renderSlats = function (dateProfile) { + var theme = this.theme; + this.slatContainerEl.innerHTML = + '<table class="' + theme.getClass('tableGrid') + '">' + + this.renderSlatRowHtml(dateProfile) + + '</table>'; + this.slatEls = core.findElements(this.slatContainerEl, 'tr'); + this.slatPositions = new core.PositionCache(this.el, this.slatEls, false, true // vertical + ); + this.isSlatSizesDirty = true; + }; + // Generates the HTML for the horizontal "slats" that run width-wise. Has a time axis on a side. Depends on RTL. + TimeGrid.prototype.renderSlatRowHtml = function (dateProfile) { + var _a = this, dateEnv = _a.dateEnv, theme = _a.theme, isRtl = _a.isRtl; + var html = ''; + var dayStart = core.startOfDay(dateProfile.renderRange.start); + var slotTime = dateProfile.minTime; + var slotIterator = core.createDuration(0); + var slotDate; // will be on the view's first day, but we only care about its time + var isLabeled; + var axisHtml; + // Calculate the time for each slot + while (core.asRoughMs(slotTime) < core.asRoughMs(dateProfile.maxTime)) { + slotDate = dateEnv.add(dayStart, slotTime); + isLabeled = core.wholeDivideDurations(slotIterator, this.labelInterval) !== null; + axisHtml = + '<td class="fc-axis fc-time ' + theme.getClass('widgetContent') + '">' + + (isLabeled ? + '<span>' + // for matchCellWidths + core.htmlEscape(dateEnv.format(slotDate, this.labelFormat)) + + '</span>' : + '') + + '</td>'; + html += + '<tr data-time="' + core.formatIsoTimeString(slotDate) + '"' + + (isLabeled ? '' : ' class="fc-minor"') + + '>' + + (!isRtl ? axisHtml : '') + + '<td class="' + theme.getClass('widgetContent') + '"></td>' + + (isRtl ? axisHtml : '') + + '</tr>'; + slotTime = core.addDurations(slotTime, this.slotDuration); + slotIterator = core.addDurations(slotIterator, this.slotDuration); + } + return html; + }; + TimeGrid.prototype._renderColumns = function (cells, dateProfile) { + var _a = this, theme = _a.theme, dateEnv = _a.dateEnv, view = _a.view; + var bgRow = new daygrid.DayBgRow(this.context); + this.rootBgContainerEl.innerHTML = + '<table class="' + theme.getClass('tableGrid') + '">' + + bgRow.renderHtml({ + cells: cells, + dateProfile: dateProfile, + renderIntroHtml: this.renderProps.renderBgIntroHtml + }) + + '</table>'; + this.colEls = core.findElements(this.el, '.fc-day, .fc-disabled-day'); + for (var col = 0; col < this.colCnt; col++) { + this.publiclyTrigger('dayRender', [ + { + date: dateEnv.toDate(cells[col].date), + el: this.colEls[col], + view: view + } + ]); + } + if (this.isRtl) { + this.colEls.reverse(); + } + this.colPositions = new core.PositionCache(this.el, this.colEls, true, // horizontal + false); + this.renderContentSkeleton(); + this.isColSizesDirty = true; + }; + TimeGrid.prototype._unrenderColumns = function () { + this.unrenderContentSkeleton(); + }; + /* Content Skeleton + ------------------------------------------------------------------------------------------------------------------*/ + // Renders the DOM that the view's content will live in + TimeGrid.prototype.renderContentSkeleton = function () { + var parts = []; + var skeletonEl; + parts.push(this.renderProps.renderIntroHtml()); + for (var i = 0; i < this.colCnt; i++) { + parts.push('<td>' + + '<div class="fc-content-col">' + + '<div class="fc-event-container fc-mirror-container"></div>' + + '<div class="fc-event-container"></div>' + + '<div class="fc-highlight-container"></div>' + + '<div class="fc-bgevent-container"></div>' + + '<div class="fc-business-container"></div>' + + '</div>' + + '</td>'); + } + if (this.isRtl) { + parts.reverse(); + } + skeletonEl = this.contentSkeletonEl = core.htmlToElement('<div class="fc-content-skeleton">' + + '<table>' + + '<tr>' + parts.join('') + '</tr>' + + '</table>' + + '</div>'); + this.colContainerEls = core.findElements(skeletonEl, '.fc-content-col'); + this.mirrorContainerEls = core.findElements(skeletonEl, '.fc-mirror-container'); + this.fgContainerEls = core.findElements(skeletonEl, '.fc-event-container:not(.fc-mirror-container)'); + this.bgContainerEls = core.findElements(skeletonEl, '.fc-bgevent-container'); + this.highlightContainerEls = core.findElements(skeletonEl, '.fc-highlight-container'); + this.businessContainerEls = core.findElements(skeletonEl, '.fc-business-container'); + if (this.isRtl) { + this.colContainerEls.reverse(); + this.mirrorContainerEls.reverse(); + this.fgContainerEls.reverse(); + this.bgContainerEls.reverse(); + this.highlightContainerEls.reverse(); + this.businessContainerEls.reverse(); + } + this.el.appendChild(skeletonEl); + }; + TimeGrid.prototype.unrenderContentSkeleton = function () { + core.removeElement(this.contentSkeletonEl); + }; + // Given a flat array of segments, return an array of sub-arrays, grouped by each segment's col + TimeGrid.prototype.groupSegsByCol = function (segs) { + var segsByCol = []; + var i; + for (i = 0; i < this.colCnt; i++) { + segsByCol.push([]); + } + for (i = 0; i < segs.length; i++) { + segsByCol[segs[i].col].push(segs[i]); + } + return segsByCol; + }; + // Given segments grouped by column, insert the segments' elements into a parallel array of container + // elements, each living within a column. + TimeGrid.prototype.attachSegsByCol = function (segsByCol, containerEls) { + var col; + var segs; + var i; + for (col = 0; col < this.colCnt; col++) { // iterate each column grouping + segs = segsByCol[col]; + for (i = 0; i < segs.length; i++) { + containerEls[col].appendChild(segs[i].el); + } + } + }; + /* Now Indicator + ------------------------------------------------------------------------------------------------------------------*/ + TimeGrid.prototype.getNowIndicatorUnit = function () { + return 'minute'; // will refresh on the minute + }; + TimeGrid.prototype.renderNowIndicator = function (segs, date) { + // HACK: if date columns not ready for some reason (scheduler) + if (!this.colContainerEls) { + return; + } + var top = this.computeDateTop(date); + var nodes = []; + var i; + // render lines within the columns + for (i = 0; i < segs.length; i++) { + var lineEl = core.createElement('div', { className: 'fc-now-indicator fc-now-indicator-line' }); + lineEl.style.top = top + 'px'; + this.colContainerEls[segs[i].col].appendChild(lineEl); + nodes.push(lineEl); + } + // render an arrow over the axis + if (segs.length > 0) { // is the current time in view? + var arrowEl = core.createElement('div', { className: 'fc-now-indicator fc-now-indicator-arrow' }); + arrowEl.style.top = top + 'px'; + this.contentSkeletonEl.appendChild(arrowEl); + nodes.push(arrowEl); + } + this.nowIndicatorEls = nodes; + }; + TimeGrid.prototype.unrenderNowIndicator = function () { + if (this.nowIndicatorEls) { + this.nowIndicatorEls.forEach(core.removeElement); + this.nowIndicatorEls = null; + } + }; + /* Coordinates + ------------------------------------------------------------------------------------------------------------------*/ + TimeGrid.prototype.getTotalSlatHeight = function () { + return this.slatContainerEl.getBoundingClientRect().height; + }; + // Computes the top coordinate, relative to the bounds of the grid, of the given date. + // A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight. + TimeGrid.prototype.computeDateTop = function (when, startOfDayDate) { + if (!startOfDayDate) { + startOfDayDate = core.startOfDay(when); + } + return this.computeTimeTop(core.createDuration(when.valueOf() - startOfDayDate.valueOf())); + }; + // Computes the top coordinate, relative to the bounds of the grid, of the given time (a Duration). + TimeGrid.prototype.computeTimeTop = function (duration) { + var len = this.slatEls.length; + var dateProfile = this.props.dateProfile; + var slatCoverage = (duration.milliseconds - core.asRoughMs(dateProfile.minTime)) / core.asRoughMs(this.slotDuration); // floating-point value of # of slots covered + var slatIndex; + var slatRemainder; + // compute a floating-point number for how many slats should be progressed through. + // from 0 to number of slats (inclusive) + // constrained because minTime/maxTime might be customized. + slatCoverage = Math.max(0, slatCoverage); + slatCoverage = Math.min(len, slatCoverage); + // an integer index of the furthest whole slat + // from 0 to number slats (*exclusive*, so len-1) + slatIndex = Math.floor(slatCoverage); + slatIndex = Math.min(slatIndex, len - 1); + // how much further through the slatIndex slat (from 0.0-1.0) must be covered in addition. + // could be 1.0 if slatCoverage is covering *all* the slots + slatRemainder = slatCoverage - slatIndex; + return this.slatPositions.tops[slatIndex] + + this.slatPositions.getHeight(slatIndex) * slatRemainder; + }; + // For each segment in an array, computes and assigns its top and bottom properties + TimeGrid.prototype.computeSegVerticals = function (segs) { + var eventMinHeight = this.opt('timeGridEventMinHeight'); + var i; + var seg; + var dayDate; + for (i = 0; i < segs.length; i++) { + seg = segs[i]; + dayDate = this.props.cells[seg.col].date; + seg.top = this.computeDateTop(seg.start, dayDate); + seg.bottom = Math.max(seg.top + eventMinHeight, this.computeDateTop(seg.end, dayDate)); + } + }; + // Given segments that already have their top/bottom properties computed, applies those values to + // the segments' elements. + TimeGrid.prototype.assignSegVerticals = function (segs) { + var i; + var seg; + for (i = 0; i < segs.length; i++) { + seg = segs[i]; + core.applyStyle(seg.el, this.generateSegVerticalCss(seg)); + } + }; + // Generates an object with CSS properties for the top/bottom coordinates of a segment element + TimeGrid.prototype.generateSegVerticalCss = function (seg) { + return { + top: seg.top, + bottom: -seg.bottom // flipped because needs to be space beyond bottom edge of event container + }; + }; + /* Sizing + ------------------------------------------------------------------------------------------------------------------*/ + TimeGrid.prototype.buildPositionCaches = function () { + this.buildColPositions(); + this.buildSlatPositions(); + }; + TimeGrid.prototype.buildColPositions = function () { + this.colPositions.build(); + }; + TimeGrid.prototype.buildSlatPositions = function () { + this.slatPositions.build(); + }; + /* Hit System + ------------------------------------------------------------------------------------------------------------------*/ + TimeGrid.prototype.positionToHit = function (positionLeft, positionTop) { + var _a = this, dateEnv = _a.dateEnv, snapsPerSlot = _a.snapsPerSlot, slatPositions = _a.slatPositions, colPositions = _a.colPositions; + var colIndex = colPositions.leftToIndex(positionLeft); + var slatIndex = slatPositions.topToIndex(positionTop); + if (colIndex != null && slatIndex != null) { + var slatTop = slatPositions.tops[slatIndex]; + var slatHeight = slatPositions.getHeight(slatIndex); + var partial = (positionTop - slatTop) / slatHeight; // floating point number between 0 and 1 + var localSnapIndex = Math.floor(partial * snapsPerSlot); // the snap # relative to start of slat + var snapIndex = slatIndex * snapsPerSlot + localSnapIndex; + var dayDate = this.props.cells[colIndex].date; + var time = core.addDurations(this.props.dateProfile.minTime, core.multiplyDuration(this.snapDuration, snapIndex)); + var start = dateEnv.add(dayDate, time); + var end = dateEnv.add(start, this.snapDuration); + return { + col: colIndex, + dateSpan: { + range: { start: start, end: end }, + allDay: false + }, + dayEl: this.colEls[colIndex], + relativeRect: { + left: colPositions.lefts[colIndex], + right: colPositions.rights[colIndex], + top: slatTop, + bottom: slatTop + slatHeight + } + }; + } + }; + /* Event Drag Visualization + ------------------------------------------------------------------------------------------------------------------*/ + TimeGrid.prototype._renderEventDrag = function (state) { + if (state) { + this.eventRenderer.hideByHash(state.affectedInstances); + if (state.isEvent) { + this.mirrorRenderer.renderSegs(state.segs, { isDragging: true, sourceSeg: state.sourceSeg }); + } + else { + this.fillRenderer.renderSegs('highlight', state.segs); + } + } + }; + TimeGrid.prototype._unrenderEventDrag = function (state) { + if (state) { + this.eventRenderer.showByHash(state.affectedInstances); + this.mirrorRenderer.unrender(state.segs, { isDragging: true, sourceSeg: state.sourceSeg }); + this.fillRenderer.unrender('highlight'); + } + }; + /* Event Resize Visualization + ------------------------------------------------------------------------------------------------------------------*/ + TimeGrid.prototype._renderEventResize = function (state) { + if (state) { + this.eventRenderer.hideByHash(state.affectedInstances); + this.mirrorRenderer.renderSegs(state.segs, { isResizing: true, sourceSeg: state.sourceSeg }); + } + }; + TimeGrid.prototype._unrenderEventResize = function (state) { + if (state) { + this.eventRenderer.showByHash(state.affectedInstances); + this.mirrorRenderer.unrender(state.segs, { isResizing: true, sourceSeg: state.sourceSeg }); + } + }; + /* Selection + ------------------------------------------------------------------------------------------------------------------*/ + // Renders a visual indication of a selection. Overrides the default, which was to simply render a highlight. + TimeGrid.prototype._renderDateSelection = function (segs) { + if (segs) { + if (this.opt('selectMirror')) { + this.mirrorRenderer.renderSegs(segs, { isSelecting: true }); + } + else { + this.fillRenderer.renderSegs('highlight', segs); + } + } + }; + TimeGrid.prototype._unrenderDateSelection = function (segs) { + this.mirrorRenderer.unrender(segs, { isSelecting: true }); + this.fillRenderer.unrender('highlight'); + }; + return TimeGrid; + }(core.DateComponent)); + + var AllDaySplitter = /** @class */ (function (_super) { + __extends(AllDaySplitter, _super); + function AllDaySplitter() { + return _super !== null && _super.apply(this, arguments) || this; + } + AllDaySplitter.prototype.getKeyInfo = function () { + return { + allDay: {}, + timed: {} + }; + }; + AllDaySplitter.prototype.getKeysForDateSpan = function (dateSpan) { + if (dateSpan.allDay) { + return ['allDay']; + } + else { + return ['timed']; + } + }; + AllDaySplitter.prototype.getKeysForEventDef = function (eventDef) { + if (!eventDef.allDay) { + return ['timed']; + } + else if (core.hasBgRendering(eventDef)) { + return ['timed', 'allDay']; + } + else { + return ['allDay']; + } + }; + return AllDaySplitter; + }(core.Splitter)); + + var TIMEGRID_ALL_DAY_EVENT_LIMIT = 5; + var WEEK_HEADER_FORMAT = core.createFormatter({ week: 'short' }); + /* An abstract class for all timegrid-related views. Displays one more columns with time slots running vertically. + ----------------------------------------------------------------------------------------------------------------------*/ + // Is a manager for the TimeGrid subcomponent and possibly the DayGrid subcomponent (if allDaySlot is on). + // Responsible for managing width/height. + var TimeGridView = /** @class */ (function (_super) { + __extends(TimeGridView, _super); + function TimeGridView(context, viewSpec, dateProfileGenerator, parentEl) { + var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this; + _this.splitter = new AllDaySplitter(); + /* Header Render Methods + ------------------------------------------------------------------------------------------------------------------*/ + // Generates the HTML that will go before the day-of week header cells + _this.renderHeadIntroHtml = function () { + var _a = _this, theme = _a.theme, dateEnv = _a.dateEnv; + var range = _this.props.dateProfile.renderRange; + var dayCnt = core.diffDays(range.start, range.end); + var weekText; + if (_this.opt('weekNumbers')) { + weekText = dateEnv.format(range.start, WEEK_HEADER_FORMAT); + return '' + + '<th class="fc-axis fc-week-number ' + theme.getClass('widgetHeader') + '" ' + _this.axisStyleAttr() + '>' + + core.buildGotoAnchorHtml(// aside from link, important for matchCellWidths + _this, { date: range.start, type: 'week', forceOff: dayCnt > 1 }, core.htmlEscape(weekText) // inner HTML + ) + + '</th>'; + } + else { + return '<th class="fc-axis ' + theme.getClass('widgetHeader') + '" ' + _this.axisStyleAttr() + '></th>'; + } + }; + /* Time Grid Render Methods + ------------------------------------------------------------------------------------------------------------------*/ + // Generates the HTML that goes before the bg of the TimeGrid slot area. Long vertical column. + _this.renderTimeGridBgIntroHtml = function () { + var theme = _this.theme; + return '<td class="fc-axis ' + theme.getClass('widgetContent') + '" ' + _this.axisStyleAttr() + '></td>'; + }; + // Generates the HTML that goes before all other types of cells. + // Affects content-skeleton, mirror-skeleton, highlight-skeleton for both the time-grid and day-grid. + _this.renderTimeGridIntroHtml = function () { + return '<td class="fc-axis" ' + _this.axisStyleAttr() + '></td>'; + }; + /* Day Grid Render Methods + ------------------------------------------------------------------------------------------------------------------*/ + // Generates the HTML that goes before the all-day cells + _this.renderDayGridBgIntroHtml = function () { + var theme = _this.theme; + return '' + + '<td class="fc-axis ' + theme.getClass('widgetContent') + '" ' + _this.axisStyleAttr() + '>' + + '<span>' + // needed for matchCellWidths + core.getAllDayHtml(_this) + + '</span>' + + '</td>'; + }; + // Generates the HTML that goes before all other types of cells. + // Affects content-skeleton, mirror-skeleton, highlight-skeleton for both the time-grid and day-grid. + _this.renderDayGridIntroHtml = function () { + return '<td class="fc-axis" ' + _this.axisStyleAttr() + '></td>'; + }; + _this.el.classList.add('fc-timeGrid-view'); + _this.el.innerHTML = _this.renderSkeletonHtml(); + _this.scroller = new core.ScrollComponent('hidden', // overflow x + 'auto' // overflow y + ); + var timeGridWrapEl = _this.scroller.el; + _this.el.querySelector('.fc-body > tr > td').appendChild(timeGridWrapEl); + timeGridWrapEl.classList.add('fc-time-grid-container'); + var timeGridEl = core.createElement('div', { className: 'fc-time-grid' }); + timeGridWrapEl.appendChild(timeGridEl); + _this.timeGrid = new TimeGrid(_this.context, timeGridEl, { + renderBgIntroHtml: _this.renderTimeGridBgIntroHtml, + renderIntroHtml: _this.renderTimeGridIntroHtml + }); + if (_this.opt('allDaySlot')) { // should we display the "all-day" area? + _this.dayGrid = new daygrid.DayGrid(// the all-day subcomponent of this view + _this.context, _this.el.querySelector('.fc-day-grid'), { + renderNumberIntroHtml: _this.renderDayGridIntroHtml, + renderBgIntroHtml: _this.renderDayGridBgIntroHtml, + renderIntroHtml: _this.renderDayGridIntroHtml, + colWeekNumbersVisible: false, + cellWeekNumbersVisible: false + }); + // have the day-grid extend it's coordinate area over the <hr> dividing the two grids + var dividerEl = _this.el.querySelector('.fc-divider'); + _this.dayGrid.bottomCoordPadding = dividerEl.getBoundingClientRect().height; + } + return _this; + } + TimeGridView.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.timeGrid.destroy(); + if (this.dayGrid) { + this.dayGrid.destroy(); + } + this.scroller.destroy(); + }; + /* Rendering + ------------------------------------------------------------------------------------------------------------------*/ + // Builds the HTML skeleton for the view. + // The day-grid and time-grid components will render inside containers defined by this HTML. + TimeGridView.prototype.renderSkeletonHtml = function () { + var theme = this.theme; + return '' + + '<table class="' + theme.getClass('tableGrid') + '">' + + (this.opt('columnHeader') ? + '<thead class="fc-head">' + + '<tr>' + + '<td class="fc-head-container ' + theme.getClass('widgetHeader') + '"> </td>' + + '</tr>' + + '</thead>' : + '') + + '<tbody class="fc-body">' + + '<tr>' + + '<td class="' + theme.getClass('widgetContent') + '">' + + (this.opt('allDaySlot') ? + '<div class="fc-day-grid"></div>' + + '<hr class="fc-divider ' + theme.getClass('widgetHeader') + '" />' : + '') + + '</td>' + + '</tr>' + + '</tbody>' + + '</table>'; + }; + /* Now Indicator + ------------------------------------------------------------------------------------------------------------------*/ + TimeGridView.prototype.getNowIndicatorUnit = function () { + return this.timeGrid.getNowIndicatorUnit(); + }; + // subclasses should implement + // renderNowIndicator(date: DateMarker) { + // } + TimeGridView.prototype.unrenderNowIndicator = function () { + this.timeGrid.unrenderNowIndicator(); + }; + /* Dimensions + ------------------------------------------------------------------------------------------------------------------*/ + TimeGridView.prototype.updateSize = function (isResize, viewHeight, isAuto) { + _super.prototype.updateSize.call(this, isResize, viewHeight, isAuto); // will call updateBaseSize. important that executes first + this.timeGrid.updateSize(isResize); + if (this.dayGrid) { + this.dayGrid.updateSize(isResize); + } + }; + // Adjusts the vertical dimensions of the view to the specified values + TimeGridView.prototype.updateBaseSize = function (isResize, viewHeight, isAuto) { + var _this = this; + var eventLimit; + var scrollerHeight; + var scrollbarWidths; + // make all axis cells line up + this.axisWidth = core.matchCellWidths(core.findElements(this.el, '.fc-axis')); + // hack to give the view some height prior to timeGrid's columns being rendered + // TODO: separate setting height from scroller VS timeGrid. + if (!this.timeGrid.colEls) { + if (!isAuto) { + scrollerHeight = this.computeScrollerHeight(viewHeight); + this.scroller.setHeight(scrollerHeight); + } + return; + } + // set of fake row elements that must compensate when scroller has scrollbars + var noScrollRowEls = core.findElements(this.el, '.fc-row').filter(function (node) { + return !_this.scroller.el.contains(node); + }); + // reset all dimensions back to the original state + this.timeGrid.bottomRuleEl.style.display = 'none'; // will be shown later if this <hr> is necessary + this.scroller.clear(); // sets height to 'auto' and clears overflow + noScrollRowEls.forEach(core.uncompensateScroll); + // limit number of events in the all-day area + if (this.dayGrid) { + this.dayGrid.removeSegPopover(); // kill the "more" popover if displayed + eventLimit = this.opt('eventLimit'); + if (eventLimit && typeof eventLimit !== 'number') { + eventLimit = TIMEGRID_ALL_DAY_EVENT_LIMIT; // make sure "auto" goes to a real number + } + if (eventLimit) { + this.dayGrid.limitRows(eventLimit); + } + } + if (!isAuto) { // should we force dimensions of the scroll container? + scrollerHeight = this.computeScrollerHeight(viewHeight); + this.scroller.setHeight(scrollerHeight); + scrollbarWidths = this.scroller.getScrollbarWidths(); + if (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars? + // make the all-day and header rows lines up + noScrollRowEls.forEach(function (rowEl) { + core.compensateScroll(rowEl, scrollbarWidths); + }); + // the scrollbar compensation might have changed text flow, which might affect height, so recalculate + // and reapply the desired height to the scroller. + scrollerHeight = this.computeScrollerHeight(viewHeight); + this.scroller.setHeight(scrollerHeight); + } + // guarantees the same scrollbar widths + this.scroller.lockOverflow(scrollbarWidths); + // if there's any space below the slats, show the horizontal rule. + // this won't cause any new overflow, because lockOverflow already called. + if (this.timeGrid.getTotalSlatHeight() < scrollerHeight) { + this.timeGrid.bottomRuleEl.style.display = ''; + } + } + }; + // given a desired total height of the view, returns what the height of the scroller should be + TimeGridView.prototype.computeScrollerHeight = function (viewHeight) { + return viewHeight - + core.subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller + }; + /* Scroll + ------------------------------------------------------------------------------------------------------------------*/ + // Computes the initial pre-configured scroll state prior to allowing the user to change it + TimeGridView.prototype.computeDateScroll = function (duration) { + var top = this.timeGrid.computeTimeTop(duration); + // zoom can give weird floating-point values. rather scroll a little bit further + top = Math.ceil(top); + if (top) { + top++; // to overcome top border that slots beyond the first have. looks better + } + return { top: top }; + }; + TimeGridView.prototype.queryDateScroll = function () { + return { top: this.scroller.getScrollTop() }; + }; + TimeGridView.prototype.applyDateScroll = function (scroll) { + if (scroll.top !== undefined) { + this.scroller.setScrollTop(scroll.top); + } + }; + // Generates an HTML attribute string for setting the width of the axis, if it is known + TimeGridView.prototype.axisStyleAttr = function () { + if (this.axisWidth != null) { + return 'style="width:' + this.axisWidth + 'px"'; + } + return ''; + }; + return TimeGridView; + }(core.View)); + TimeGridView.prototype.usesMinMaxTime = true; // indicates that minTime/maxTime affects rendering + + var SimpleTimeGrid = /** @class */ (function (_super) { + __extends(SimpleTimeGrid, _super); + function SimpleTimeGrid(context, timeGrid) { + var _this = _super.call(this, context, timeGrid.el) || this; + _this.buildDayRanges = core.memoize(buildDayRanges); + _this.slicer = new TimeGridSlicer(); + _this.timeGrid = timeGrid; + context.calendar.registerInteractiveComponent(_this, { + el: _this.timeGrid.el + }); + return _this; + } + SimpleTimeGrid.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.calendar.unregisterInteractiveComponent(this); + }; + SimpleTimeGrid.prototype.render = function (props) { + var dateProfile = props.dateProfile, dayTable = props.dayTable; + var dayRanges = this.dayRanges = this.buildDayRanges(dayTable, dateProfile, this.dateEnv); + this.timeGrid.receiveProps(__assign({}, this.slicer.sliceProps(props, dateProfile, null, this.timeGrid, dayRanges), { dateProfile: dateProfile, cells: dayTable.cells[0] })); + }; + SimpleTimeGrid.prototype.renderNowIndicator = function (date) { + this.timeGrid.renderNowIndicator(this.slicer.sliceNowDate(date, this.timeGrid, this.dayRanges), date); + }; + SimpleTimeGrid.prototype.buildPositionCaches = function () { + this.timeGrid.buildPositionCaches(); + }; + SimpleTimeGrid.prototype.queryHit = function (positionLeft, positionTop) { + var rawHit = this.timeGrid.positionToHit(positionLeft, positionTop); + if (rawHit) { + return { + component: this.timeGrid, + dateSpan: rawHit.dateSpan, + dayEl: rawHit.dayEl, + rect: { + left: rawHit.relativeRect.left, + right: rawHit.relativeRect.right, + top: rawHit.relativeRect.top, + bottom: rawHit.relativeRect.bottom + }, + layer: 0 + }; + } + }; + return SimpleTimeGrid; + }(core.DateComponent)); + function buildDayRanges(dayTable, dateProfile, dateEnv) { + var ranges = []; + for (var _i = 0, _a = dayTable.headerDates; _i < _a.length; _i++) { + var date = _a[_i]; + ranges.push({ + start: dateEnv.add(date, dateProfile.minTime), + end: dateEnv.add(date, dateProfile.maxTime) + }); + } + return ranges; + } + var TimeGridSlicer = /** @class */ (function (_super) { + __extends(TimeGridSlicer, _super); + function TimeGridSlicer() { + return _super !== null && _super.apply(this, arguments) || this; + } + TimeGridSlicer.prototype.sliceRange = function (range, dayRanges) { + var segs = []; + for (var col = 0; col < dayRanges.length; col++) { + var segRange = core.intersectRanges(range, dayRanges[col]); + if (segRange) { + segs.push({ + start: segRange.start, + end: segRange.end, + isStart: segRange.start.valueOf() === range.start.valueOf(), + isEnd: segRange.end.valueOf() === range.end.valueOf(), + col: col + }); + } + } + return segs; + }; + return TimeGridSlicer; + }(core.Slicer)); + + var TimeGridView$1 = /** @class */ (function (_super) { + __extends(TimeGridView, _super); + function TimeGridView(_context, viewSpec, dateProfileGenerator, parentEl) { + var _this = _super.call(this, _context, viewSpec, dateProfileGenerator, parentEl) || this; + _this.buildDayTable = core.memoize(buildDayTable); + if (_this.opt('columnHeader')) { + _this.header = new core.DayHeader(_this.context, _this.el.querySelector('.fc-head-container')); + } + _this.simpleTimeGrid = new SimpleTimeGrid(_this.context, _this.timeGrid); + if (_this.dayGrid) { + _this.simpleDayGrid = new daygrid.SimpleDayGrid(_this.context, _this.dayGrid); + } + return _this; + } + TimeGridView.prototype.destroy = function () { + _super.prototype.destroy.call(this); + if (this.header) { + this.header.destroy(); + } + this.simpleTimeGrid.destroy(); + if (this.simpleDayGrid) { + this.simpleDayGrid.destroy(); + } + }; + TimeGridView.prototype.render = function (props) { + _super.prototype.render.call(this, props); // for flags for updateSize + var dateProfile = this.props.dateProfile; + var dayTable = this.buildDayTable(dateProfile, this.dateProfileGenerator); + var splitProps = this.splitter.splitProps(props); + if (this.header) { + this.header.receiveProps({ + dateProfile: dateProfile, + dates: dayTable.headerDates, + datesRepDistinctDays: true, + renderIntroHtml: this.renderHeadIntroHtml + }); + } + this.simpleTimeGrid.receiveProps(__assign({}, splitProps['timed'], { dateProfile: dateProfile, + dayTable: dayTable })); + if (this.simpleDayGrid) { + this.simpleDayGrid.receiveProps(__assign({}, splitProps['allDay'], { dateProfile: dateProfile, + dayTable: dayTable, nextDayThreshold: this.nextDayThreshold, isRigid: false })); + } + }; + TimeGridView.prototype.renderNowIndicator = function (date) { + this.simpleTimeGrid.renderNowIndicator(date); + }; + return TimeGridView; + }(TimeGridView)); + function buildDayTable(dateProfile, dateProfileGenerator) { + var daySeries = new core.DaySeries(dateProfile.renderRange, dateProfileGenerator); + return new core.DayTable(daySeries, false); + } + + var main = core.createPlugin({ + defaultView: 'timeGridWeek', + views: { + timeGrid: { + class: TimeGridView$1, + allDaySlot: true, + slotDuration: '00:30:00', + slotEventOverlap: true // a bad name. confused with overlap/constraint system + }, + timeGridDay: { + type: 'timeGrid', + duration: { days: 1 } + }, + timeGridWeek: { + type: 'timeGrid', + duration: { weeks: 1 } + } + } + }); + + exports.AbstractTimeGridView = TimeGridView; + exports.TimeGrid = TimeGrid; + exports.TimeGridSlicer = TimeGridSlicer; + exports.TimeGridView = TimeGridView$1; + exports.buildDayRanges = buildDayRanges; + exports.buildDayTable = buildDayTable; + exports.default = main; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/timegrid/main.min.css b/AKPlan/static/AKPlan/fullcalendar/timegrid/main.min.css new file mode 100644 index 00000000..a1abf91f --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/timegrid/main.min.css @@ -0,0 +1 @@ +@charset "UTF-8";.fc-timeGrid-view .fc-day-grid{position:relative;z-index:2}.fc-timeGrid-view .fc-day-grid .fc-row{min-height:3em}.fc-timeGrid-view .fc-day-grid .fc-row .fc-content-skeleton{padding-bottom:1em}.fc .fc-axis{vertical-align:middle;padding:0 4px;white-space:nowrap}.fc-ltr .fc-axis{text-align:right}.fc-rtl .fc-axis{text-align:left}.fc-time-grid,.fc-time-grid-container{position:relative;z-index:1}.fc-time-grid{min-height:100%}.fc-time-grid table{border:0 hidden transparent}.fc-time-grid>.fc-bg{z-index:1}.fc-time-grid .fc-slats,.fc-time-grid>hr{position:relative;z-index:2}.fc-time-grid .fc-content-col{position:relative}.fc-time-grid .fc-content-skeleton{position:absolute;z-index:3;top:0;left:0;right:0}.fc-time-grid .fc-business-container{position:relative;z-index:1}.fc-time-grid .fc-bgevent-container{position:relative;z-index:2}.fc-time-grid .fc-highlight-container{z-index:3;position:relative}.fc-time-grid .fc-event-container{position:relative;z-index:4}.fc-time-grid .fc-now-indicator-line{z-index:5}.fc-time-grid .fc-mirror-container{position:relative;z-index:6}.fc-time-grid .fc-slats td{height:1.5em;border-bottom:0}.fc-time-grid .fc-slats .fc-minor td{border-top-style:dotted}.fc-time-grid .fc-highlight{position:absolute;left:0;right:0}.fc-ltr .fc-time-grid .fc-event-container{margin:0 2.5% 0 2px}.fc-rtl .fc-time-grid .fc-event-container{margin:0 2px 0 2.5%}.fc-time-grid .fc-bgevent,.fc-time-grid .fc-event{position:absolute;z-index:1}.fc-time-grid .fc-bgevent{left:0;right:0}.fc-time-grid-event{margin-bottom:1px}.fc-time-grid-event-inset{-webkit-box-shadow:0 0 0 1px #fff;box-shadow:0 0 0 1px #fff}.fc-time-grid-event.fc-not-start{border-top-width:0;padding-top:1px;border-top-left-radius:0;border-top-right-radius:0}.fc-time-grid-event.fc-not-end{border-bottom-width:0;padding-bottom:1px;border-bottom-left-radius:0;border-bottom-right-radius:0}.fc-time-grid-event .fc-content{overflow:hidden;max-height:100%}.fc-time-grid-event .fc-time,.fc-time-grid-event .fc-title{padding:0 1px}.fc-time-grid-event .fc-time{font-size:.85em;white-space:nowrap}.fc-time-grid-event.fc-short .fc-content{white-space:nowrap}.fc-time-grid-event.fc-short .fc-time,.fc-time-grid-event.fc-short .fc-title{display:inline-block;vertical-align:top}.fc-time-grid-event.fc-short .fc-time span{display:none}.fc-time-grid-event.fc-short .fc-time:before{content:attr(data-start)}.fc-time-grid-event.fc-short .fc-time:after{content:" - "}.fc-time-grid-event.fc-short .fc-title{font-size:.85em;padding:0}.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer{left:0;right:0;bottom:0;height:8px;overflow:hidden;line-height:8px;font-size:11px;font-family:monospace;text-align:center;cursor:s-resize}.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer:after{content:"="}.fc-time-grid-event.fc-selected .fc-resizer{border-radius:5px;border-width:1px;width:8px;height:8px;border-style:solid;border-color:inherit;background:#fff;left:50%;margin-left:-5px;bottom:-5px}.fc-time-grid .fc-now-indicator-line{border-top-width:1px;left:0;right:0}.fc-time-grid .fc-now-indicator-arrow{margin-top:-5px}.fc-ltr .fc-time-grid .fc-now-indicator-arrow{left:0;border-width:5px 0 5px 6px;border-top-color:transparent;border-bottom-color:transparent}.fc-rtl .fc-time-grid .fc-now-indicator-arrow{right:0;border-width:5px 6px 5px 0;border-top-color:transparent;border-bottom-color:transparent} \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/timegrid/main.min.js b/AKPlan/static/AKPlan/fullcalendar/timegrid/main.min.js new file mode 100644 index 00000000..13c3433e --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/timegrid/main.min.js @@ -0,0 +1,6 @@ +/*! +FullCalendar Time Grid Plugin v4.3.0 +Docs & License: https://fullcalendar.io/ +(c) 2019 Adam Shaw +*/ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@fullcalendar/core"),require("@fullcalendar/daygrid")):"function"==typeof define&&define.amd?define(["exports","@fullcalendar/core","@fullcalendar/daygrid"],t):t((e=e||self).FullCalendarTimeGrid={},e.FullCalendar,e.FullCalendarDayGrid)}(this,function(e,t,r){"use strict";var i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)};function n(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}var o=function(){return(o=Object.assign||function(e){for(var t,r=1,i=arguments.length;r<i;r++)for(var n in t=arguments[r])Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e}).apply(this,arguments)},s=function(e){function r(r){var i=e.call(this,r.context)||this;return i.timeGrid=r,i.fullTimeFormat=t.createFormatter({hour:"numeric",minute:"2-digit",separator:i.context.options.defaultRangeSeparator}),i}return n(r,e),r.prototype.attachSegs=function(e,t){for(var r=this.timeGrid.groupSegsByCol(e),i=0;i<r.length;i++)r[i]=this.sortEventSegs(r[i]);this.segsByCol=r,this.timeGrid.attachSegsByCol(r,this.timeGrid.fgContainerEls)},r.prototype.detachSegs=function(e){e.forEach(function(e){t.removeElement(e.el)}),this.segsByCol=null},r.prototype.computeSegSizes=function(e){var t=this.timeGrid,r=this.segsByCol,i=t.colCnt;if(t.computeSegVerticals(e),r)for(var n=0;n<i;n++)this.computeSegHorizontals(r[n])},r.prototype.assignSegSizes=function(e){var t=this.timeGrid,r=this.segsByCol,i=t.colCnt;if(t.assignSegVerticals(e),r)for(var n=0;n<i;n++)this.assignSegCss(r[n])},r.prototype.computeEventTimeFormat=function(){return{hour:"numeric",minute:"2-digit",meridiem:!1}},r.prototype.computeDisplayEventEnd=function(){return!0},r.prototype.renderSegHtml=function(e,r){var i,n,o,s=this.context.view,a=e.eventRange,l=a.def,d=a.ui,c=l.allDay,h=s.computeEventDraggable(l,d),u=e.isStart&&s.computeEventStartResizable(l,d),p=e.isEnd&&s.computeEventEndResizable(l,d),f=this.getSegClasses(e,h,u||p,r),g=t.cssToStr(this.getSkinCss(d));if(f.unshift("fc-time-grid-event"),t.isMultiDayRange(a.range)){if(e.isStart||e.isEnd){var m=e.start,y=e.end;i=this._getTimeText(m,y,c),n=this._getTimeText(m,y,c,this.fullTimeFormat),o=this._getTimeText(m,y,c,null,!1)}}else i=this.getTimeText(a),n=this.getTimeText(a,this.fullTimeFormat),o=this.getTimeText(a,null,!1);return'<a class="'+f.join(" ")+'"'+(l.url?' href="'+t.htmlEscape(l.url)+'"':"")+(g?' style="'+g+'"':"")+'><div class="fc-content">'+(i?'<div class="fc-time" data-start="'+t.htmlEscape(o)+'" data-full="'+t.htmlEscape(n)+'"><span>'+t.htmlEscape(i)+"</span></div>":"")+(l.title?'<div class="fc-title">'+t.htmlEscape(l.title)+"</div>":"")+"</div>"+(p?'<div class="fc-resizer fc-end-resizer"></div>':"")+"</a>"},r.prototype.computeSegHorizontals=function(e){var t,r,i;if(function(e){var t,r,i,n,o;for(t=0;t<e.length;t++)for(r=e[t],i=0;i<r.length;i++)for((n=r[i]).forwardSegs=[],o=t+1;o<e.length;o++)l(n,e[o],n.forwardSegs)}(t=function(e){var t,r,i,n=[];for(t=0;t<e.length;t++){for(r=e[t],i=0;i<n.length&&l(r,n[i]).length;i++);r.level=i,(n[i]||(n[i]=[])).push(r)}return n}(e)),r=t[0]){for(i=0;i<r.length;i++)a(r[i]);for(i=0;i<r.length;i++)this.computeSegForwardBack(r[i],0,0)}},r.prototype.computeSegForwardBack=function(e,t,r){var i,n=e.forwardSegs;if(void 0===e.forwardCoord)for(n.length?(this.sortForwardSegs(n),this.computeSegForwardBack(n[0],t+1,r),e.forwardCoord=n[0].backwardCoord):e.forwardCoord=1,e.backwardCoord=e.forwardCoord-(e.forwardCoord-r)/(t+1),i=0;i<n.length;i++)this.computeSegForwardBack(n[i],0,e.forwardCoord)},r.prototype.sortForwardSegs=function(e){var r=e.map(d),i=[{field:"forwardPressure",order:-1},{field:"backwardCoord",order:1}].concat(this.context.view.eventOrderSpecs);return r.sort(function(e,r){return t.compareByFieldSpecs(e,r,i)}),r.map(function(e){return e._seg})},r.prototype.assignSegCss=function(e){for(var r=0,i=e;r<i.length;r++){var n=i[r];t.applyStyle(n.el,this.generateSegCss(n)),n.level>0&&n.el.classList.add("fc-time-grid-event-inset"),n.eventRange.def.title&&n.bottom-n.top<30&&n.el.classList.add("fc-short")}},r.prototype.generateSegCss=function(e){var t,r,i=this.context.options.slotEventOverlap,n=e.backwardCoord,o=e.forwardCoord,s=this.timeGrid.generateSegVerticalCss(e),a=this.timeGrid.isRtl;return i&&(o=Math.min(1,n+2*(o-n))),a?(t=1-o,r=n):(t=n,r=1-o),s.zIndex=e.level+1,s.left=100*t+"%",s.right=100*r+"%",i&&e.forwardPressure&&(s[a?"marginLeft":"marginRight"]=20),s},r}(t.FgEventRenderer);function a(e){var t,r,i=e.forwardSegs,n=0;if(void 0===e.forwardPressure){for(t=0;t<i.length;t++)a(r=i[t]),n=Math.max(n,1+r.forwardPressure);e.forwardPressure=n}}function l(e,t,r){void 0===r&&(r=[]);for(var i=0;i<t.length;i++)n=e,o=t[i],n.bottom>o.top&&n.top<o.bottom&&r.push(t[i]);var n,o;return r}function d(e){var r=t.buildSegCompareObj(e);return r.forwardPressure=e.forwardPressure,r.backwardCoord=e.backwardCoord,r}var c=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return n(t,e),t.prototype.attachSegs=function(e,t){this.segsByCol=this.timeGrid.groupSegsByCol(e),this.timeGrid.attachSegsByCol(this.segsByCol,this.timeGrid.mirrorContainerEls),this.sourceSeg=t.sourceSeg},t.prototype.generateSegCss=function(t){var r=e.prototype.generateSegCss.call(this,t),i=this.sourceSeg;if(i&&i.col===t.col){var n=e.prototype.generateSegCss.call(this,i);r.left=n.left,r.right=n.right,r.marginLeft=n.marginLeft,r.marginRight=n.marginRight}return r},t}(s),h=function(e){function t(t){var r=e.call(this,t.context)||this;return r.timeGrid=t,r}return n(t,e),t.prototype.attachSegs=function(e,t){var r,i=this.timeGrid;return"bgEvent"===e?r=i.bgContainerEls:"businessHours"===e?r=i.businessContainerEls:"highlight"===e&&(r=i.highlightContainerEls),i.attachSegsByCol(i.groupSegsByCol(t),r),t.map(function(e){return e.el})},t.prototype.computeSegSizes=function(e){this.timeGrid.computeSegVerticals(e)},t.prototype.assignSegSizes=function(e){this.timeGrid.assignSegVerticals(e)},t}(t.FillRenderer),u=[{hours:1},{minutes:30},{minutes:15},{seconds:30},{seconds:15}],p=function(e){function i(r,i,n){var o=e.call(this,r,i)||this;o.isSlatSizesDirty=!1,o.isColSizesDirty=!1,o.renderSlats=t.memoizeRendering(o._renderSlats);var a=o.eventRenderer=new s(o),l=o.fillRenderer=new h(o);o.mirrorRenderer=new c(o);var d=o.renderColumns=t.memoizeRendering(o._renderColumns,o._unrenderColumns);return o.renderBusinessHours=t.memoizeRendering(l.renderSegs.bind(l,"businessHours"),l.unrender.bind(l,"businessHours"),[d]),o.renderDateSelection=t.memoizeRendering(o._renderDateSelection,o._unrenderDateSelection,[d]),o.renderFgEvents=t.memoizeRendering(a.renderSegs.bind(a),a.unrender.bind(a),[d]),o.renderBgEvents=t.memoizeRendering(l.renderSegs.bind(l,"bgEvent"),l.unrender.bind(l,"bgEvent"),[d]),o.renderEventSelection=t.memoizeRendering(a.selectByInstanceId.bind(a),a.unselectByInstanceId.bind(a),[o.renderFgEvents]),o.renderEventDrag=t.memoizeRendering(o._renderEventDrag,o._unrenderEventDrag,[d]),o.renderEventResize=t.memoizeRendering(o._renderEventResize,o._unrenderEventResize,[d]),o.processOptions(),i.innerHTML='<div class="fc-bg"></div><div class="fc-slats"></div><hr class="fc-divider '+o.theme.getClass("widgetHeader")+'" style="display:none" />',o.rootBgContainerEl=i.querySelector(".fc-bg"),o.slatContainerEl=i.querySelector(".fc-slats"),o.bottomRuleEl=i.querySelector(".fc-divider"),o.renderProps=n,o}return n(i,e),i.prototype.processOptions=function(){var e,r,i=this.opt("slotDuration"),n=this.opt("snapDuration");i=t.createDuration(i),n=n?t.createDuration(n):i,null===(e=t.wholeDivideDurations(i,n))&&(n=i,e=1),this.slotDuration=i,this.snapDuration=n,this.snapsPerSlot=e,r=this.opt("slotLabelFormat"),Array.isArray(r)&&(r=r[r.length-1]),this.labelFormat=t.createFormatter(r||{hour:"numeric",minute:"2-digit",omitZeroMinute:!0,meridiem:"short"}),r=this.opt("slotLabelInterval"),this.labelInterval=r?t.createDuration(r):this.computeLabelInterval(i)},i.prototype.computeLabelInterval=function(e){var r,i,n;for(r=u.length-1;r>=0;r--)if(i=t.createDuration(u[r]),null!==(n=t.wholeDivideDurations(i,e))&&n>1)return i;return e},i.prototype.render=function(e){var t=e.cells;this.colCnt=t.length,this.renderSlats(e.dateProfile),this.renderColumns(e.cells,e.dateProfile),this.renderBusinessHours(e.businessHourSegs),this.renderDateSelection(e.dateSelectionSegs),this.renderFgEvents(e.fgEventSegs),this.renderBgEvents(e.bgEventSegs),this.renderEventSelection(e.eventSelection),this.renderEventDrag(e.eventDrag),this.renderEventResize(e.eventResize)},i.prototype.destroy=function(){e.prototype.destroy.call(this),this.renderSlats.unrender(),this.renderColumns.unrender()},i.prototype.updateSize=function(e){var t=this.fillRenderer,r=this.eventRenderer,i=this.mirrorRenderer;(e||this.isSlatSizesDirty)&&(this.buildSlatPositions(),this.isSlatSizesDirty=!1),(e||this.isColSizesDirty)&&(this.buildColPositions(),this.isColSizesDirty=!1),t.computeSizes(e),r.computeSizes(e),i.computeSizes(e),t.assignSizes(e),r.assignSizes(e),i.assignSizes(e)},i.prototype._renderSlats=function(e){var r=this.theme;this.slatContainerEl.innerHTML='<table class="'+r.getClass("tableGrid")+'">'+this.renderSlatRowHtml(e)+"</table>",this.slatEls=t.findElements(this.slatContainerEl,"tr"),this.slatPositions=new t.PositionCache(this.el,this.slatEls,!1,!0),this.isSlatSizesDirty=!0},i.prototype.renderSlatRowHtml=function(e){for(var r,i,n,o=this.dateEnv,s=this.theme,a=this.isRtl,l="",d=t.startOfDay(e.renderRange.start),c=e.minTime,h=t.createDuration(0);t.asRoughMs(c)<t.asRoughMs(e.maxTime);)r=o.add(d,c),i=null!==t.wholeDivideDurations(h,this.labelInterval),n='<td class="fc-axis fc-time '+s.getClass("widgetContent")+'">'+(i?"<span>"+t.htmlEscape(o.format(r,this.labelFormat))+"</span>":"")+"</td>",l+='<tr data-time="'+t.formatIsoTimeString(r)+'"'+(i?"":' class="fc-minor"')+">"+(a?"":n)+'<td class="'+s.getClass("widgetContent")+'"></td>'+(a?n:"")+"</tr>",c=t.addDurations(c,this.slotDuration),h=t.addDurations(h,this.slotDuration);return l},i.prototype._renderColumns=function(e,i){var n=this.theme,o=this.dateEnv,s=this.view,a=new r.DayBgRow(this.context);this.rootBgContainerEl.innerHTML='<table class="'+n.getClass("tableGrid")+'">'+a.renderHtml({cells:e,dateProfile:i,renderIntroHtml:this.renderProps.renderBgIntroHtml})+"</table>",this.colEls=t.findElements(this.el,".fc-day, .fc-disabled-day");for(var l=0;l<this.colCnt;l++)this.publiclyTrigger("dayRender",[{date:o.toDate(e[l].date),el:this.colEls[l],view:s}]);this.isRtl&&this.colEls.reverse(),this.colPositions=new t.PositionCache(this.el,this.colEls,!0,!1),this.renderContentSkeleton(),this.isColSizesDirty=!0},i.prototype._unrenderColumns=function(){this.unrenderContentSkeleton()},i.prototype.renderContentSkeleton=function(){var e,r=[];r.push(this.renderProps.renderIntroHtml());for(var i=0;i<this.colCnt;i++)r.push('<td><div class="fc-content-col"><div class="fc-event-container fc-mirror-container"></div><div class="fc-event-container"></div><div class="fc-highlight-container"></div><div class="fc-bgevent-container"></div><div class="fc-business-container"></div></div></td>');this.isRtl&&r.reverse(),e=this.contentSkeletonEl=t.htmlToElement('<div class="fc-content-skeleton"><table><tr>'+r.join("")+"</tr></table></div>"),this.colContainerEls=t.findElements(e,".fc-content-col"),this.mirrorContainerEls=t.findElements(e,".fc-mirror-container"),this.fgContainerEls=t.findElements(e,".fc-event-container:not(.fc-mirror-container)"),this.bgContainerEls=t.findElements(e,".fc-bgevent-container"),this.highlightContainerEls=t.findElements(e,".fc-highlight-container"),this.businessContainerEls=t.findElements(e,".fc-business-container"),this.isRtl&&(this.colContainerEls.reverse(),this.mirrorContainerEls.reverse(),this.fgContainerEls.reverse(),this.bgContainerEls.reverse(),this.highlightContainerEls.reverse(),this.businessContainerEls.reverse()),this.el.appendChild(e)},i.prototype.unrenderContentSkeleton=function(){t.removeElement(this.contentSkeletonEl)},i.prototype.groupSegsByCol=function(e){var t,r=[];for(t=0;t<this.colCnt;t++)r.push([]);for(t=0;t<e.length;t++)r[e[t].col].push(e[t]);return r},i.prototype.attachSegsByCol=function(e,t){var r,i,n;for(r=0;r<this.colCnt;r++)for(i=e[r],n=0;n<i.length;n++)t[r].appendChild(i[n].el)},i.prototype.getNowIndicatorUnit=function(){return"minute"},i.prototype.renderNowIndicator=function(e,r){if(this.colContainerEls){var i,n=this.computeDateTop(r),o=[];for(i=0;i<e.length;i++){var s=t.createElement("div",{className:"fc-now-indicator fc-now-indicator-line"});s.style.top=n+"px",this.colContainerEls[e[i].col].appendChild(s),o.push(s)}if(e.length>0){var a=t.createElement("div",{className:"fc-now-indicator fc-now-indicator-arrow"});a.style.top=n+"px",this.contentSkeletonEl.appendChild(a),o.push(a)}this.nowIndicatorEls=o}},i.prototype.unrenderNowIndicator=function(){this.nowIndicatorEls&&(this.nowIndicatorEls.forEach(t.removeElement),this.nowIndicatorEls=null)},i.prototype.getTotalSlatHeight=function(){return this.slatContainerEl.getBoundingClientRect().height},i.prototype.computeDateTop=function(e,r){return r||(r=t.startOfDay(e)),this.computeTimeTop(t.createDuration(e.valueOf()-r.valueOf()))},i.prototype.computeTimeTop=function(e){var r,i,n=this.slatEls.length,o=this.props.dateProfile,s=(e.milliseconds-t.asRoughMs(o.minTime))/t.asRoughMs(this.slotDuration);return s=Math.max(0,s),s=Math.min(n,s),r=Math.floor(s),i=s-(r=Math.min(r,n-1)),this.slatPositions.tops[r]+this.slatPositions.getHeight(r)*i},i.prototype.computeSegVerticals=function(e){var t,r,i,n=this.opt("timeGridEventMinHeight");for(t=0;t<e.length;t++)r=e[t],i=this.props.cells[r.col].date,r.top=this.computeDateTop(r.start,i),r.bottom=Math.max(r.top+n,this.computeDateTop(r.end,i))},i.prototype.assignSegVerticals=function(e){var r,i;for(r=0;r<e.length;r++)i=e[r],t.applyStyle(i.el,this.generateSegVerticalCss(i))},i.prototype.generateSegVerticalCss=function(e){return{top:e.top,bottom:-e.bottom}},i.prototype.buildPositionCaches=function(){this.buildColPositions(),this.buildSlatPositions()},i.prototype.buildColPositions=function(){this.colPositions.build()},i.prototype.buildSlatPositions=function(){this.slatPositions.build()},i.prototype.positionToHit=function(e,r){var i=this.dateEnv,n=this.snapsPerSlot,o=this.slatPositions,s=this.colPositions,a=s.leftToIndex(e),l=o.topToIndex(r);if(null!=a&&null!=l){var d=o.tops[l],c=o.getHeight(l),h=(r-d)/c,u=l*n+Math.floor(h*n),p=this.props.cells[a].date,f=t.addDurations(this.props.dateProfile.minTime,t.multiplyDuration(this.snapDuration,u)),g=i.add(p,f);return{col:a,dateSpan:{range:{start:g,end:i.add(g,this.snapDuration)},allDay:!1},dayEl:this.colEls[a],relativeRect:{left:s.lefts[a],right:s.rights[a],top:d,bottom:d+c}}}},i.prototype._renderEventDrag=function(e){e&&(this.eventRenderer.hideByHash(e.affectedInstances),e.isEvent?this.mirrorRenderer.renderSegs(e.segs,{isDragging:!0,sourceSeg:e.sourceSeg}):this.fillRenderer.renderSegs("highlight",e.segs))},i.prototype._unrenderEventDrag=function(e){e&&(this.eventRenderer.showByHash(e.affectedInstances),this.mirrorRenderer.unrender(e.segs,{isDragging:!0,sourceSeg:e.sourceSeg}),this.fillRenderer.unrender("highlight"))},i.prototype._renderEventResize=function(e){e&&(this.eventRenderer.hideByHash(e.affectedInstances),this.mirrorRenderer.renderSegs(e.segs,{isResizing:!0,sourceSeg:e.sourceSeg}))},i.prototype._unrenderEventResize=function(e){e&&(this.eventRenderer.showByHash(e.affectedInstances),this.mirrorRenderer.unrender(e.segs,{isResizing:!0,sourceSeg:e.sourceSeg}))},i.prototype._renderDateSelection=function(e){e&&(this.opt("selectMirror")?this.mirrorRenderer.renderSegs(e,{isSelecting:!0}):this.fillRenderer.renderSegs("highlight",e))},i.prototype._unrenderDateSelection=function(e){this.mirrorRenderer.unrender(e,{isSelecting:!0}),this.fillRenderer.unrender("highlight")},i}(t.DateComponent),f=function(e){function r(){return null!==e&&e.apply(this,arguments)||this}return n(r,e),r.prototype.getKeyInfo=function(){return{allDay:{},timed:{}}},r.prototype.getKeysForDateSpan=function(e){return e.allDay?["allDay"]:["timed"]},r.prototype.getKeysForEventDef=function(e){return e.allDay?t.hasBgRendering(e)?["timed","allDay"]:["allDay"]:["timed"]},r}(t.Splitter),g=t.createFormatter({week:"short"}),m=function(e){function i(i,n,o,s){var a=e.call(this,i,n,o,s)||this;a.splitter=new f,a.renderHeadIntroHtml=function(){var e,r=a,i=r.theme,n=r.dateEnv,o=a.props.dateProfile.renderRange,s=t.diffDays(o.start,o.end);return a.opt("weekNumbers")?(e=n.format(o.start,g),'<th class="fc-axis fc-week-number '+i.getClass("widgetHeader")+'" '+a.axisStyleAttr()+">"+t.buildGotoAnchorHtml(a,{date:o.start,type:"week",forceOff:s>1},t.htmlEscape(e))+"</th>"):'<th class="fc-axis '+i.getClass("widgetHeader")+'" '+a.axisStyleAttr()+"></th>"},a.renderTimeGridBgIntroHtml=function(){return'<td class="fc-axis '+a.theme.getClass("widgetContent")+'" '+a.axisStyleAttr()+"></td>"},a.renderTimeGridIntroHtml=function(){return'<td class="fc-axis" '+a.axisStyleAttr()+"></td>"},a.renderDayGridBgIntroHtml=function(){return'<td class="fc-axis '+a.theme.getClass("widgetContent")+'" '+a.axisStyleAttr()+"><span>"+t.getAllDayHtml(a)+"</span></td>"},a.renderDayGridIntroHtml=function(){return'<td class="fc-axis" '+a.axisStyleAttr()+"></td>"},a.el.classList.add("fc-timeGrid-view"),a.el.innerHTML=a.renderSkeletonHtml(),a.scroller=new t.ScrollComponent("hidden","auto");var l=a.scroller.el;a.el.querySelector(".fc-body > tr > td").appendChild(l),l.classList.add("fc-time-grid-container");var d=t.createElement("div",{className:"fc-time-grid"});if(l.appendChild(d),a.timeGrid=new p(a.context,d,{renderBgIntroHtml:a.renderTimeGridBgIntroHtml,renderIntroHtml:a.renderTimeGridIntroHtml}),a.opt("allDaySlot")){a.dayGrid=new r.DayGrid(a.context,a.el.querySelector(".fc-day-grid"),{renderNumberIntroHtml:a.renderDayGridIntroHtml,renderBgIntroHtml:a.renderDayGridBgIntroHtml,renderIntroHtml:a.renderDayGridIntroHtml,colWeekNumbersVisible:!1,cellWeekNumbersVisible:!1});var c=a.el.querySelector(".fc-divider");a.dayGrid.bottomCoordPadding=c.getBoundingClientRect().height}return a}return n(i,e),i.prototype.destroy=function(){e.prototype.destroy.call(this),this.timeGrid.destroy(),this.dayGrid&&this.dayGrid.destroy(),this.scroller.destroy()},i.prototype.renderSkeletonHtml=function(){var e=this.theme;return'<table class="'+e.getClass("tableGrid")+'">'+(this.opt("columnHeader")?'<thead class="fc-head"><tr><td class="fc-head-container '+e.getClass("widgetHeader")+'"> </td></tr></thead>':"")+'<tbody class="fc-body"><tr><td class="'+e.getClass("widgetContent")+'">'+(this.opt("allDaySlot")?'<div class="fc-day-grid"></div><hr class="fc-divider '+e.getClass("widgetHeader")+'" />':"")+"</td></tr></tbody></table>"},i.prototype.getNowIndicatorUnit=function(){return this.timeGrid.getNowIndicatorUnit()},i.prototype.unrenderNowIndicator=function(){this.timeGrid.unrenderNowIndicator()},i.prototype.updateSize=function(t,r,i){e.prototype.updateSize.call(this,t,r,i),this.timeGrid.updateSize(t),this.dayGrid&&this.dayGrid.updateSize(t)},i.prototype.updateBaseSize=function(e,r,i){var n,o,s,a=this;if(this.axisWidth=t.matchCellWidths(t.findElements(this.el,".fc-axis")),this.timeGrid.colEls){var l=t.findElements(this.el,".fc-row").filter(function(e){return!a.scroller.el.contains(e)});this.timeGrid.bottomRuleEl.style.display="none",this.scroller.clear(),l.forEach(t.uncompensateScroll),this.dayGrid&&(this.dayGrid.removeSegPopover(),(n=this.opt("eventLimit"))&&"number"!=typeof n&&(n=5),n&&this.dayGrid.limitRows(n)),i||(o=this.computeScrollerHeight(r),this.scroller.setHeight(o),((s=this.scroller.getScrollbarWidths()).left||s.right)&&(l.forEach(function(e){t.compensateScroll(e,s)}),o=this.computeScrollerHeight(r),this.scroller.setHeight(o)),this.scroller.lockOverflow(s),this.timeGrid.getTotalSlatHeight()<o&&(this.timeGrid.bottomRuleEl.style.display=""))}else i||(o=this.computeScrollerHeight(r),this.scroller.setHeight(o))},i.prototype.computeScrollerHeight=function(e){return e-t.subtractInnerElHeight(this.el,this.scroller.el)},i.prototype.computeDateScroll=function(e){var t=this.timeGrid.computeTimeTop(e);return(t=Math.ceil(t))&&t++,{top:t}},i.prototype.queryDateScroll=function(){return{top:this.scroller.getScrollTop()}},i.prototype.applyDateScroll=function(e){void 0!==e.top&&this.scroller.setScrollTop(e.top)},i.prototype.axisStyleAttr=function(){return null!=this.axisWidth?'style="width:'+this.axisWidth+'px"':""},i}(t.View);m.prototype.usesMinMaxTime=!0;var y=function(e){function r(r,i){var n=e.call(this,r,i.el)||this;return n.buildDayRanges=t.memoize(v),n.slicer=new S,n.timeGrid=i,r.calendar.registerInteractiveComponent(n,{el:n.timeGrid.el}),n}return n(r,e),r.prototype.destroy=function(){e.prototype.destroy.call(this),this.calendar.unregisterInteractiveComponent(this)},r.prototype.render=function(e){var t=e.dateProfile,r=e.dayTable,i=this.dayRanges=this.buildDayRanges(r,t,this.dateEnv);this.timeGrid.receiveProps(o({},this.slicer.sliceProps(e,t,null,this.timeGrid,i),{dateProfile:t,cells:r.cells[0]}))},r.prototype.renderNowIndicator=function(e){this.timeGrid.renderNowIndicator(this.slicer.sliceNowDate(e,this.timeGrid,this.dayRanges),e)},r.prototype.buildPositionCaches=function(){this.timeGrid.buildPositionCaches()},r.prototype.queryHit=function(e,t){var r=this.timeGrid.positionToHit(e,t);if(r)return{component:this.timeGrid,dateSpan:r.dateSpan,dayEl:r.dayEl,rect:{left:r.relativeRect.left,right:r.relativeRect.right,top:r.relativeRect.top,bottom:r.relativeRect.bottom},layer:0}},r}(t.DateComponent);function v(e,t,r){for(var i=[],n=0,o=e.headerDates;n<o.length;n++){var s=o[n];i.push({start:r.add(s,t.minTime),end:r.add(s,t.maxTime)})}return i}var S=function(e){function r(){return null!==e&&e.apply(this,arguments)||this}return n(r,e),r.prototype.sliceRange=function(e,r){for(var i=[],n=0;n<r.length;n++){var o=t.intersectRanges(e,r[n]);o&&i.push({start:o.start,end:o.end,isStart:o.start.valueOf()===e.start.valueOf(),isEnd:o.end.valueOf()===e.end.valueOf(),col:n})}return i},r}(t.Slicer),C=function(e){function i(i,n,o,s){var a=e.call(this,i,n,o,s)||this;return a.buildDayTable=t.memoize(E),a.opt("columnHeader")&&(a.header=new t.DayHeader(a.context,a.el.querySelector(".fc-head-container"))),a.simpleTimeGrid=new y(a.context,a.timeGrid),a.dayGrid&&(a.simpleDayGrid=new r.SimpleDayGrid(a.context,a.dayGrid)),a}return n(i,e),i.prototype.destroy=function(){e.prototype.destroy.call(this),this.header&&this.header.destroy(),this.simpleTimeGrid.destroy(),this.simpleDayGrid&&this.simpleDayGrid.destroy()},i.prototype.render=function(t){e.prototype.render.call(this,t);var r=this.props.dateProfile,i=this.buildDayTable(r,this.dateProfileGenerator),n=this.splitter.splitProps(t);this.header&&this.header.receiveProps({dateProfile:r,dates:i.headerDates,datesRepDistinctDays:!0,renderIntroHtml:this.renderHeadIntroHtml}),this.simpleTimeGrid.receiveProps(o({},n.timed,{dateProfile:r,dayTable:i})),this.simpleDayGrid&&this.simpleDayGrid.receiveProps(o({},n.allDay,{dateProfile:r,dayTable:i,nextDayThreshold:this.nextDayThreshold,isRigid:!1}))},i.prototype.renderNowIndicator=function(e){this.simpleTimeGrid.renderNowIndicator(e)},i}(m);function E(e,r){var i=new t.DaySeries(e.renderRange,r);return new t.DayTable(i,!1)}var b=t.createPlugin({defaultView:"timeGridWeek",views:{timeGrid:{class:C,allDaySlot:!0,slotDuration:"00:30:00",slotEventOverlap:!0},timeGridDay:{type:"timeGrid",duration:{days:1}},timeGridWeek:{type:"timeGrid",duration:{weeks:1}}}});e.AbstractTimeGridView=m,e.TimeGrid=p,e.TimeGridSlicer=S,e.TimeGridView=C,e.buildDayRanges=v,e.buildDayTable=E,e.default=b,Object.defineProperty(e,"__esModule",{value:!0})}); \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/timegrid/package.json b/AKPlan/static/AKPlan/fullcalendar/timegrid/package.json new file mode 100644 index 00000000..9226f350 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/timegrid/package.json @@ -0,0 +1,36 @@ +{ + "name": "@fullcalendar/timegrid", + "version": "4.3.0", + "title": "FullCalendar Time Grid Plugin", + "description": "Display your events on a grid of time slots", + "keywords": [ + "calendar", + "event", + "full-sized" + ], + "homepage": "https://fullcalendar.io/", + "docs": "https://fullcalendar.io/docs/timegrid-view", + "bugs": "https://fullcalendar.io/reporting-bugs", + "repository": { + "type": "git", + "url": "https://github.com/fullcalendar/fullcalendar.git", + "homepage": "https://github.com/fullcalendar/fullcalendar" + }, + "license": "MIT", + "author": { + "name": "Adam Shaw", + "email": "arshaw@arshaw.com", + "url": "http://arshaw.com/" + }, + "copyright": "2019 Adam Shaw", + "dependencies": { + "@fullcalendar/daygrid": "~4.3.0" + }, + "peerDependencies": { + "@fullcalendar/core": "~4.3.0" + }, + "main": "main.js", + "module": "main.esm.js", + "unpkg": "main.min.js", + "types": "main.d.ts" +} diff --git a/AKPlan/static/AKPlan/fullcalendar/timeline/LICENSE.md b/AKPlan/static/AKPlan/fullcalendar/timeline/LICENSE.md new file mode 100644 index 00000000..52296639 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/timeline/LICENSE.md @@ -0,0 +1,18 @@ + +For complete licensing information, visit: +http://fullcalendar.io/scheduler/license + +FullCalendar Scheduler is tri-licensed, meaning you must choose +one of three licenses to use. Here is a summary of those licenses: + +- Commercial License + (a paid license, meant for commercial use) + http://fullcalendar.io/scheduler/license-details + +- Creative Commons Non-Commercial No-Derivatives + (meant for trial and non-commercial use) + https://creativecommons.org/licenses/by-nc-nd/4.0/ + +- GPLv3 License + (meant for open-source projects) + http://www.gnu.org/licenses/gpl-3.0.en.html diff --git a/AKPlan/static/AKPlan/fullcalendar/timeline/README.md b/AKPlan/static/AKPlan/fullcalendar/timeline/README.md new file mode 100644 index 00000000..ade1cab5 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/timeline/README.md @@ -0,0 +1,8 @@ + +# FullCalendar Timeline Plugin + +Display events on a horizontal time axis (without resources) + +[View the docs »](https://fullcalendar.io/docs/timeline-view-no-resources) + +This package was created from the [FullCalendar monorepo »](https://github.com/fullcalendar/fullcalendar-scheduler) diff --git a/AKPlan/static/AKPlan/fullcalendar/timeline/main.css b/AKPlan/static/AKPlan/fullcalendar/timeline/main.css new file mode 100644 index 00000000..69f5999c --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/timeline/main.css @@ -0,0 +1,351 @@ +/* Scroller +--------------------------------------------------------------------------------------------------*/ +.fc-scroller-clip { + overflow: hidden; + /* for clipping scrollbars */ + position: relative; + /* so things like scrollfollowers can attach to this */ +} + +/* supresses rendering of native scrollbars */ +/* on .fc-scroller */ +.fc-no-scrollbars { + background: rgba(255, 255, 255, 0); + /* hack for dynamic DOM nodes (in Chrome OSX at least) */ +} + +.fc-no-scrollbars::-webkit-scrollbar { + width: 0; + height: 0; +} + +.fc-scroller-canvas { + position: relative; + /* origin for bg */ + box-sizing: border-box; + /* so that padding (for gutter) will be part of height */ + min-height: 100%; +} + +.fc-scroller-canvas > .fc-bg { + z-index: 1; + /* make default? */ +} + +.fc-scroller-canvas > .fc-content { + z-index: 2; + /* make default? */ + position: relative; + /* origin for inner content */ + border-style: solid; + border-width: 0; +} + +.fc-scroller-canvas.fc-gutter-left > .fc-content { + border-left-width: 1px; + margin-left: -1px; +} + +.fc-scroller-canvas.fc-gutter-right > .fc-content { + border-right-width: 1px; + margin-right: -1px; +} + +.fc-scroller-canvas.fc-gutter-top > .fc-content { + border-top-width: 1px; + margin-top: -1px; +} + +/* content is responsible for bottom border */ +/* View Structure +--------------------------------------------------------------------------------------------------*/ +.fc-rtl .fc-timeline { + direction: rtl; +} + +.fc-scrolled .fc-head .fc-scroller { + z-index: 2; + /* so drop shadow will go above body panes */ +} + +.fc-timeline.fc-scrolled .fc-head .fc-scroller { + box-shadow: 0 3px 4px rgba(0, 0, 0, 0.075); +} + +.fc-timeline .fc-body .fc-scroller { + z-index: 1; +} + +/* +on most tables that expand to the edges, kill the outer border, +because the container elements take care of it. +example tables: +.fc-scroller-canvas .fc-content table +.fc-scroller-canvas .fc-bg .fc-slats table +*/ +.fc-timeline .fc-scroller-canvas > div > table, +.fc-timeline .fc-scroller-canvas > div > div > table { + border-style: hidden; +} + +/* +for resource rows (in both the spreadsheet and timeline areas), +undo previous rule in order to always show last border. +*/ +.fc-timeline .fc-scroller-canvas > .fc-content > .fc-rows > table { + border-bottom-style: none; +} + +/* Table Cell Common +--------------------------------------------------------------------------------------------------*/ +.fc-timeline th, +.fc-timeline td { + white-space: nowrap; +} + +.fc-timeline .fc-cell-content { + overflow: hidden; +} + +.fc-timeline .fc-cell-text { + display: inline-block; + padding-left: 4px; + padding-right: 4px; +} + +/* +Cells at the start of a week +TODO: figure out better styling + +.fc-ltr .fc-timeline .fc-em-cell div { + border-left: 3px solid #eee; + height: 100%; +} +.fc-rtl .fc-timeline .fc-em-cell { + border-right-width: 3px; +} +*/ +/* head */ +.fc-timeline th { + vertical-align: middle; +} + +.fc-timeline .fc-head .fc-cell-content { + padding-top: 3px; + padding-bottom: 3px; +} + +.fc-timeline .fc-head .fc-time-area .fc-cell-content { + overflow: visible; +} + +/* Time Area +--------------------------------------------------------------------------------------------------*/ +.fc-time-area col { + min-width: 2.2em; + /* detected by JS */ +} + +/* head */ +.fc-ltr .fc-time-area .fc-chrono th { + text-align: left; +} + +.fc-rtl .fc-time-area .fc-chrono th { + text-align: right; +} + +/* body slats (vertical lines) */ +.fc-time-area .fc-slats { + /* fc-bg is responsible for a lot of this now! */ + position: absolute; + z-index: 1; + top: 0; + left: 0; + right: 0; + bottom: 0; +} + +.fc-time-area .fc-slats table { + height: 100%; +} + +.fc-time-area .fc-slats .fc-minor { + border-style: dotted; +} + +.fc-time-area .fc-slats td { + border-width: 0 1px; + /* need to do this. sometimes -1 margin wouldn't hide the dotted */ +} + +.fc-ltr .fc-time-area .fc-slats td { + border-right-width: 0; +} + +.fc-rtl .fc-time-area .fc-slats td { + border-left-width: 0; +} + +/* body content containers + can be within rows or directly within the pane's content +*/ +.fc-time-area .fc-bgevent-container, +.fc-time-area .fc-highlight-container { + position: absolute; + z-index: 2; + /* only for directly within pane. not for row. overridden later */ + top: 0; + bottom: 0; + width: 0; +} + +.fc-ltr .fc-time-area .fc-mirror-container, +.fc-ltr .fc-time-area .fc-bgevent-container, +.fc-ltr .fc-time-area .fc-highlight-container { + left: 0; +} + +.fc-rtl .fc-time-area .fc-mirror-container, +.fc-rtl .fc-time-area .fc-bgevent-container, +.fc-rtl .fc-time-area .fc-highlight-container { + right: 0; +} + +.fc-time-area .fc-bgevent, +.fc-time-area .fc-highlight { + position: absolute; + top: 0; + bottom: 0; +} + +/* Now Indicator +--------------------------------------------------------------------------------------------------*/ +.fc-timeline .fc-now-indicator { + /* both the arrow and the line */ + z-index: 3; + /* one above scroller's fc-content */ + top: 0; +} + +.fc-time-area .fc-now-indicator-arrow { + margin: 0 -6px; + /* 5, then one more to counteract scroller's negative margins */ + /* triangle pointing down... */ + border-width: 6px 5px 0 5px; + border-left-color: transparent; + border-right-color: transparent; +} + +.fc-time-area .fc-now-indicator-line { + margin: 0 -1px; + /* counteract scroller's negative margins */ + bottom: 0; + border-left-width: 1px; +} + +/* Event Container +--------------------------------------------------------------------------------------------------*/ +.fc-time-area .fc-event-container { + position: relative; + z-index: 2; + /* above bgevent and highlight */ + width: 0; + /* for event positioning. will end up on correct side based on dir */ +} + +.fc-time-area .fc-mirror-container { + /* also an fc-event-container */ + position: absolute; + z-index: 3; + top: 0; +} + +.fc-time-area .fc-event-container { + padding-bottom: 8px; + top: -1px; +} + +.fc-time-area tr:first-child .fc-event-container { + top: 0; +} + +.fc-no-overlap .fc-time-area .fc-event-container { + padding-bottom: 0; + top: 0; +} + +/* Time Grid Events +--------------------------------------------------------------------------------------------------*/ +.fc-timeline-event { + position: absolute; + display: flex; + border-radius: 0; + padding: 2px 1px; + margin-bottom: 1px; +} + +.fc-no-overlap .fc-timeline-event { + padding-top: 5px; + padding-bottom: 5px; + margin-bottom: 0; +} + +.fc-ltr .fc-timeline-event { + flex-direction: row; + margin-right: 1px; +} + +.fc-rtl .fc-timeline-event { + margin-left: 1px; +} + +.fc-timeline-event .fc-time-wrap { + flex-shrink: 0; + min-width: 0; +} + +.fc-timeline-event .fc-title-wrap { + flex-grow: 1; + min-width: 0; +} + +.fc-timeline-event .fc-time, +.fc-timeline-event .fc-title { + display: inline-block; + vertical-align: top; + max-width: 100%; + padding: 0 2px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + white-space: nowrap; + overflow: hidden; +} + +.fc-timeline-event .fc-time { + font-weight: bold; +} + +.fc-timeline-event.fc-not-start:before, +.fc-timeline-event.fc-not-end:after { + content: ""; + align-self: center; + width: 0; + height: 0; + margin: 0 1px; + border: 5px solid #000; + border-top-color: transparent; + border-bottom-color: transparent; + opacity: 0.5; +} + +.fc-ltr .fc-timeline-event.fc-not-start:before, +.fc-rtl .fc-timeline-event.fc-not-end:after { + border-left: 0; +} + +.fc-ltr .fc-timeline-event.fc-not-end:after, +.fc-rtl .fc-timeline-event.fc-not-start:before { + border-right: 0; +} diff --git a/AKPlan/static/AKPlan/fullcalendar/timeline/main.d.ts b/AKPlan/static/AKPlan/fullcalendar/timeline/main.d.ts new file mode 100644 index 00000000..dd4e64ef --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/timeline/main.d.ts @@ -0,0 +1,353 @@ +// Generated by dts-bundle v0.7.3-fork.1 +// Dependencies for this module: +// ../../../../../@fullcalendar/core + +declare module '@fullcalendar/timeline' { + import TimelineView from '@fullcalendar/timeline/TimelineView'; + export { TimelineView }; + export { default as TimelineLane } from '@fullcalendar/timeline/TimelineLane'; + export { default as ScrollJoiner } from '@fullcalendar/timeline/util/ScrollJoiner'; + export { default as StickyScroller } from '@fullcalendar/timeline/util/StickyScroller'; + export { default as TimeAxis } from '@fullcalendar/timeline/TimeAxis'; + export { default as HeaderBodyLayout } from '@fullcalendar/timeline/HeaderBodyLayout'; + const _default: import("@fullcalendar/core").PluginDef; + export default _default; +} + +declare module '@fullcalendar/timeline/TimelineView' { + import { Hit, View, ViewProps, ComponentContext, ViewSpec, DateProfileGenerator, DateProfile, Duration } from '@fullcalendar/core'; + import TimeAxis from '@fullcalendar/timeline/TimeAxis'; + import TimelineLane from '@fullcalendar/timeline/TimelineLane'; + export { TimelineView as default, TimelineView }; + class TimelineView extends View { + timeAxis: TimeAxis; + lane: TimelineLane; + constructor(context: ComponentContext, viewSpec: ViewSpec, dateProfileGenerator: DateProfileGenerator, parentEl: HTMLElement); + destroy(): void; + renderSkeletonHtml(): string; + render(props: ViewProps): void; + updateSize(isResize: any, totalHeight: any, isAuto: any): void; + getNowIndicatorUnit(dateProfile: DateProfile): string; + renderNowIndicator(date: any): void; + unrenderNowIndicator(): void; + computeDateScroll(duration: Duration): { + left: number; + }; + applyScroll(scroll: any, isResize: any): void; + applyDateScroll(scroll: any): void; + queryScroll(): { + top: number; + left: number; + }; + buildPositionCaches(): void; + queryHit(positionLeft: number, positionTop: number, elWidth: number, elHeight: number): Hit; + } +} + +declare module '@fullcalendar/timeline/TimelineLane' { + import { Duration, EventStore, EventUiHash, DateMarker, DateSpan, EventInteractionState, EventSegUiInteractionState, DateComponent, ComponentContext, Seg, DateProfile } from '@fullcalendar/core'; + import TimeAxis from '@fullcalendar/timeline/TimeAxis'; + export interface TimelineLaneSeg extends Seg { + start: DateMarker; + end: DateMarker; + } + export interface TimelineLaneProps { + dateProfile: DateProfile; + nextDayThreshold: Duration; + businessHours: EventStore | null; + eventStore: EventStore | null; + eventUiBases: EventUiHash; + dateSelection: DateSpan | null; + eventSelection: string; + eventDrag: EventInteractionState | null; + eventResize: EventInteractionState | null; + } + export { TimelineLane as default, TimelineLane }; + class TimelineLane extends DateComponent<TimelineLaneProps> { + timeAxis: TimeAxis; + constructor(context: ComponentContext, fgContainerEl: HTMLElement, bgContainerEl: HTMLElement, timeAxis: TimeAxis); + render(props: TimelineLaneProps): void; + destroy(): void; + _renderEventDrag(state: EventSegUiInteractionState): void; + _unrenderEventDrag(state: EventSegUiInteractionState): void; + _renderEventResize(state: EventSegUiInteractionState): void; + _unrenderEventResize(state: EventSegUiInteractionState): void; + updateSize(isResize: boolean): void; + } +} + +declare module '@fullcalendar/timeline/util/ScrollJoiner' { + import ClippedScroller from '@fullcalendar/timeline/util/ClippedScroller'; + export { ScrollJoiner as default, ScrollJoiner }; + class ScrollJoiner { + axis: any; + scrollers: ClippedScroller[]; + masterScroller: ClippedScroller; + constructor(axis: any, scrollers: ClippedScroller[]); + initScroller(scroller: ClippedScroller): void; + assignMasterScroller(scroller: any): void; + unassignMasterScroller(): void; + update(): void; + } +} + +declare module '@fullcalendar/timeline/util/StickyScroller' { + import { Rect, Point } from '@fullcalendar/core'; + import EnhancedScroller from '@fullcalendar/timeline/util/EnhancedScroller'; + interface ElementGeom { + parentBound: Rect; + naturalBound: Rect | null; + elWidth: number; + elHeight: number; + computedTextAlign: string; + intendedTextAlign: string; + } + export { StickyScroller as default, StickyScroller }; + class StickyScroller { + scroller: EnhancedScroller; + usingRelative: boolean | null; + constructor(scroller: EnhancedScroller, isRtl: boolean, isVertical: boolean); + destroy(): void; + updateSize: () => void; + queryElGeoms(els: HTMLElement[]): ElementGeom[]; + computeElDestinations(elGeoms: ElementGeom[], viewportWidth: number): Point[]; + } + export {}; +} + +declare module '@fullcalendar/timeline/TimeAxis' { + import { DateProfile, DateMarker, Component, ComponentContext, Duration } from '@fullcalendar/core'; + import HeaderBodyLayout from '@fullcalendar/timeline/HeaderBodyLayout'; + import TimelineHeader from '@fullcalendar/timeline/TimelineHeader'; + import TimelineSlats from '@fullcalendar/timeline/TimelineSlats'; + import { TimelineDateProfile } from '@fullcalendar/timeline/timeline-date-profile'; + import TimelineNowIndicator from '@fullcalendar/timeline/TimelineNowIndicator'; + import StickyScroller from '@fullcalendar/timeline/util/StickyScroller'; + export interface TimeAxisProps { + dateProfile: DateProfile; + } + export { TimeAxis as default, TimeAxis }; + class TimeAxis extends Component<TimeAxisProps> { + layout: HeaderBodyLayout; + header: TimelineHeader; + slats: TimelineSlats; + nowIndicator: TimelineNowIndicator; + headStickyScroller: StickyScroller; + bodyStickyScroller: StickyScroller; + tDateProfile: TimelineDateProfile; + constructor(context: ComponentContext, headerContainerEl: any, bodyContainerEl: any); + destroy(): void; + render(props: TimeAxisProps): void; + getNowIndicatorUnit(dateProfile: DateProfile): string; + renderNowIndicator(date: any): void; + unrenderNowIndicator(): void; + updateSize(isResize: any, totalHeight: any, isAuto: any): void; + updateStickyScrollers(): void; + computeSlotWidth(): any; + computeDefaultSlotWidth(tDateProfile: any): number; + applySlotWidth(slotWidth: number | string): void; + computeDateSnapCoverage(date: DateMarker): number; + dateToCoord(date: any): any; + rangeToCoords(range: any): { + right: any; + left: any; + }; + computeDateScroll(duration: Duration): { + left: number; + }; + queryDateScroll(): { + left: number; + }; + applyDateScroll(scroll: any): void; + } +} + +declare module '@fullcalendar/timeline/HeaderBodyLayout' { + import ClippedScroller from '@fullcalendar/timeline/util/ClippedScroller'; + import ScrollJoiner from '@fullcalendar/timeline/util/ScrollJoiner'; + export { HeaderBodyLayout as default, HeaderBodyLayout }; + class HeaderBodyLayout { + headerScroller: ClippedScroller; + bodyScroller: ClippedScroller; + scrollJoiner: ScrollJoiner; + constructor(headerContainerEl: any, bodyContainerEl: any, verticalScroll: any); + destroy(): void; + setHeight(totalHeight: any, isAuto: any): void; + queryHeadHeight(): number; + } +} + +declare module '@fullcalendar/timeline/util/ClippedScroller' { + import { ScrollbarWidths } from '@fullcalendar/core'; + import EnhancedScroller from '@fullcalendar/timeline/util/EnhancedScroller'; + export { ClippedScroller as default, ClippedScroller }; + class ClippedScroller { + el: HTMLElement; + enhancedScroll: EnhancedScroller; + isHScrollbarsClipped: boolean; + isVScrollbarsClipped: boolean; + constructor(overflowX: string, overflowY: string, parentEl: HTMLElement); + destroy(): void; + updateSize(): void; + setHeight(height: number | string): void; + getScrollbarWidths(): ScrollbarWidths; + } +} + +declare module '@fullcalendar/timeline/util/EnhancedScroller' { + import { ScrollComponent, EmitterInterface } from '@fullcalendar/core'; + import ScrollerCanvas from '@fullcalendar/timeline/util/ScrollerCanvas'; + export { EnhancedScroller as default, EnhancedScroller }; + class EnhancedScroller extends ScrollComponent { + on: EmitterInterface['on']; + one: EmitterInterface['one']; + off: EmitterInterface['off']; + trigger: EmitterInterface['trigger']; + triggerWith: EmitterInterface['triggerWith']; + hasHandlers: EmitterInterface['hasHandlers']; + canvas: ScrollerCanvas; + isScrolling: boolean; + isTouching: boolean; + isMoving: boolean; + isTouchScrollEnabled: boolean; + preventTouchScrollHandler: any; + requestMovingEnd: any; + constructor(overflowX: string, overflowY: string); + destroy(): void; + disableTouchScroll(): void; + enableTouchScroll(): void; + bindPreventTouchScroll(): void; + unbindPreventTouchScroll(): void; + bindHandlers(): void; + unbindHandlers(): void; + reportScroll: () => void; + reportScrollStart: () => void; + reportMovingEnd(): void; + reportScrollEnd(): void; + reportTouchStart: () => void; + reportTouchEnd: () => void; + getScrollLeft(): number; + setScrollLeft(val: any): void; + getScrollFromLeft(): number; + } +} + +declare module '@fullcalendar/timeline/TimelineHeader' { + import { Component, ComponentContext, DateProfile } from '@fullcalendar/core'; + import { TimelineDateProfile } from '@fullcalendar/timeline/timeline-date-profile'; + export interface TimelineHeaderProps { + dateProfile: DateProfile; + tDateProfile: TimelineDateProfile; + } + export { TimelineHeader as default, TimelineHeader }; + class TimelineHeader extends Component<TimelineHeaderProps> { + tableEl: HTMLElement; + slatColEls: HTMLElement[]; + innerEls: HTMLElement[]; + constructor(context: ComponentContext, parentEl: HTMLElement); + destroy(): void; + render(props: TimelineHeaderProps): void; + renderDates(tDateProfile: TimelineDateProfile): void; + } +} + +declare module '@fullcalendar/timeline/TimelineSlats' { + import { PositionCache, Component, ComponentContext, DateProfile } from '@fullcalendar/core'; + import { TimelineDateProfile } from '@fullcalendar/timeline/timeline-date-profile'; + export interface TimelineSlatsProps { + dateProfile: DateProfile; + tDateProfile: TimelineDateProfile; + } + export { TimelineSlats as default, TimelineSlats }; + class TimelineSlats extends Component<TimelineSlatsProps> { + el: HTMLElement; + slatColEls: HTMLElement[]; + slatEls: HTMLElement[]; + outerCoordCache: PositionCache; + innerCoordCache: PositionCache; + constructor(context: ComponentContext, parentEl: HTMLElement); + destroy(): void; + render(props: TimelineSlatsProps): void; + renderDates(tDateProfile: TimelineDateProfile): void; + slatCellHtml(date: any, isEm: any, tDateProfile: TimelineDateProfile): string; + updateSize(): void; + positionToHit(leftPosition: any): { + dateSpan: { + range: { + start: Date; + end: Date; + }; + allDay: boolean; + }; + dayEl: HTMLElement; + left: any; + right: any; + }; + } +} + +declare module '@fullcalendar/timeline/timeline-date-profile' { + import { Duration, View, DateProfile, DateMarker, DateEnv, DateRange } from '@fullcalendar/core'; + export interface TimelineDateProfile { + labelInterval: Duration; + slotDuration: Duration; + headerFormats: any; + isTimeScale: boolean; + largeUnit: string; + emphasizeWeeks: boolean; + snapDuration: Duration; + snapsPerSlot: number; + normalizedRange: DateRange; + timeWindowMs: number; + slotDates: DateMarker[]; + isWeekStarts: boolean[]; + snapDiffToIndex: number[]; + snapIndexToDiff: number[]; + snapCnt: number; + slotCnt: number; + cellRows: TimelineHeaderCell[][]; + } + export interface TimelineHeaderCell { + text: string; + spanHtml: string; + date: DateMarker; + colspan: number; + isWeekStart: boolean; + } + export function buildTimelineDateProfile(dateProfile: DateProfile, view: View): TimelineDateProfile; + export function normalizeDate(date: DateMarker, tDateProfile: TimelineDateProfile, dateEnv: DateEnv): DateMarker; + export function normalizeRange(range: DateRange, tDateProfile: TimelineDateProfile, dateEnv: DateEnv): DateRange; + export function isValidDate(date: DateMarker, tDateProfile: TimelineDateProfile, dateProfile: DateProfile, view: View): boolean; +} + +declare module '@fullcalendar/timeline/TimelineNowIndicator' { + export { TimelineNowIndicator as default, TimelineNowIndicator }; + class TimelineNowIndicator { + headParent: HTMLElement; + bodyParent: HTMLElement; + arrowEl: HTMLElement; + lineEl: HTMLElement; + constructor(headParent: HTMLElement, bodyParent: HTMLElement); + render(coord: number, isRtl: boolean): void; + unrender(): void; + } +} + +declare module '@fullcalendar/timeline/util/ScrollerCanvas' { + export { ScrollerCanvas as default, ScrollerCanvas }; + class ScrollerCanvas { + el: HTMLElement; + contentEl: HTMLElement; + bgEl: HTMLElement; + gutters: any; + width: any; + minWidth: any; + constructor(); + setGutters(gutters: any): void; + setWidth(width: any): void; + setMinWidth(minWidth: any): void; + clearWidth(): void; + updateSize(): void; + } +} + diff --git a/AKPlan/static/AKPlan/fullcalendar/timeline/main.esm.js b/AKPlan/static/AKPlan/fullcalendar/timeline/main.esm.js new file mode 100644 index 00000000..2cbb80b8 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/timeline/main.esm.js @@ -0,0 +1,1983 @@ +/*! +FullCalendar Timeline Plugin v4.3.0 +Docs & License: https://fullcalendar.io/scheduler +(c) 2019 Adam Shaw +*/ + +import { htmlToElement, forceClassName, applyStyle, debounce, preventDefault, ScrollComponent, EmitterMixin, removeElement, createElement, computeEdges, asRoughMs, isSingleDay, getDayClasses, findElements, Component, PositionCache, findChildren, isInt, multiplyDuration, config, createFormatter, greatestDurationDenominator, createDuration, wholeDivideDurations, addDays, startOfDay, computeVisibleDayRange, asRoughMinutes, padStart, asRoughSeconds, diffWholeDays, buildGotoAnchorHtml, htmlEscape, translateRect, rangeContainsMarker, cssToStr, computeHeightAndMargins, applyStyleProp, FgEventRenderer, FillRenderer, memoizeRendering, DateComponent, intersectRanges, addMs, Slicer, View, createPlugin } from '@fullcalendar/core'; + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} + +var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; + +/* +A rectangular area of content that lives within a Scroller. +Can have "gutters", areas of dead spacing around the perimeter. +Also very useful for forcing a width, which a Scroller cannot do alone. +Has a content area that lives above a background area. +*/ +var ScrollerCanvas = /** @class */ (function () { + function ScrollerCanvas() { + this.gutters = {}; + this.el = htmlToElement("<div class=\"fc-scroller-canvas\"> <div class=\"fc-content\"></div> <div class=\"fc-bg\"></div> </div>"); + this.contentEl = this.el.querySelector('.fc-content'); + this.bgEl = this.el.querySelector('.fc-bg'); + } + /* + If falsy, resets all the gutters to 0 + */ + ScrollerCanvas.prototype.setGutters = function (gutters) { + if (!gutters) { + this.gutters = {}; + } + else { + __assign(this.gutters, gutters); + } + this.updateSize(); + }; + ScrollerCanvas.prototype.setWidth = function (width) { + this.width = width; + this.updateSize(); + }; + ScrollerCanvas.prototype.setMinWidth = function (minWidth) { + this.minWidth = minWidth; + this.updateSize(); + }; + ScrollerCanvas.prototype.clearWidth = function () { + this.width = null; + this.minWidth = null; + this.updateSize(); + }; + ScrollerCanvas.prototype.updateSize = function () { + var _a = this, gutters = _a.gutters, el = _a.el; + // is border-box (width includes padding) + forceClassName(el, 'fc-gutter-left', gutters.left); + forceClassName(el, 'fc-gutter-right', gutters.right); + forceClassName(el, 'fc-gutter-top', gutters.top); + forceClassName(el, 'fc-gutter-bottom', gutters.bottom); + applyStyle(el, { + paddingLeft: gutters.left || '', + paddingRight: gutters.right || '', + paddingTop: gutters.top || '', + paddingBottom: gutters.bottom || '', + width: (this.width != null) ? + this.width + (gutters.left || 0) + (gutters.right || 0) : + '', + minWidth: (this.minWidth != null) ? + this.minWidth + (gutters.left || 0) + (gutters.right || 0) : + '' + }); + applyStyle(this.bgEl, { + left: gutters.left || '', + right: gutters.right || '', + top: gutters.top || '', + bottom: gutters.bottom || '' + }); + }; + return ScrollerCanvas; +}()); + +var EnhancedScroller = /** @class */ (function (_super) { + __extends(EnhancedScroller, _super); + function EnhancedScroller(overflowX, overflowY) { + var _this = _super.call(this, overflowX, overflowY) || this; + // Scroll Events + // ---------------------------------------------------------------------------------------------- + _this.reportScroll = function () { + if (!_this.isScrolling) { + _this.reportScrollStart(); + } + _this.trigger('scroll'); + _this.isMoving = true; + _this.requestMovingEnd(); + }; + _this.reportScrollStart = function () { + if (!_this.isScrolling) { + _this.isScrolling = true; + _this.trigger('scrollStart', _this.isTouching); // created in constructor + } + }; + // Touch Events + // ---------------------------------------------------------------------------------------------- + // will fire *before* the scroll event is fired + _this.reportTouchStart = function () { + _this.isTouching = true; + }; + _this.reportTouchEnd = function () { + if (_this.isTouching) { + _this.isTouching = false; + // if touch scrolling was re-enabled during a recent touch scroll + // then unbind the handlers that are preventing it from happening. + if (_this.isTouchScrollEnabled) { + _this.unbindPreventTouchScroll(); // won't do anything if not bound + } + // if the user ended their touch, and the scroll area wasn't moving, + // we consider this to be the end of the scroll. + if (!_this.isMoving) { + _this.reportScrollEnd(); // won't fire if already ended + } + } + }; + _this.isScrolling = false; + _this.isTouching = false; + _this.isMoving = false; + _this.isTouchScrollEnabled = true; + _this.requestMovingEnd = debounce(_this.reportMovingEnd, 500); + _this.canvas = new ScrollerCanvas(); + _this.el.appendChild(_this.canvas.el); + _this.applyOverflow(); + _this.bindHandlers(); + return _this; + } + EnhancedScroller.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.unbindHandlers(); + }; + // Touch scroll prevention + // ---------------------------------------------------------------------------------------------- + EnhancedScroller.prototype.disableTouchScroll = function () { + this.isTouchScrollEnabled = false; + this.bindPreventTouchScroll(); // will be unbound in enableTouchScroll or reportTouchEnd + }; + EnhancedScroller.prototype.enableTouchScroll = function () { + this.isTouchScrollEnabled = true; + // only immediately unbind if a touch event is NOT in progress. + // otherwise, it will be handled by reportTouchEnd. + if (!this.isTouching) { + this.unbindPreventTouchScroll(); + } + }; + EnhancedScroller.prototype.bindPreventTouchScroll = function () { + if (!this.preventTouchScrollHandler) { + this.el.addEventListener('touchmove', (this.preventTouchScrollHandler = preventDefault)); + } + }; + EnhancedScroller.prototype.unbindPreventTouchScroll = function () { + if (this.preventTouchScrollHandler) { + this.el.removeEventListener('touchmove', this.preventTouchScrollHandler); + this.preventTouchScrollHandler = null; + } + }; + // Handlers + // ---------------------------------------------------------------------------------------------- + EnhancedScroller.prototype.bindHandlers = function () { + this.el.addEventListener('scroll', this.reportScroll); + this.el.addEventListener('touchstart', this.reportTouchStart, { passive: true }); + this.el.addEventListener('touchend', this.reportTouchEnd); + }; + EnhancedScroller.prototype.unbindHandlers = function () { + this.el.removeEventListener('scroll', this.reportScroll); + this.el.removeEventListener('touchstart', this.reportTouchStart, { passive: true }); + this.el.removeEventListener('touchend', this.reportTouchEnd); + }; + EnhancedScroller.prototype.reportMovingEnd = function () { + this.isMoving = false; + // only end the scroll if not currently touching. + // if touching, the scrolling will end later, on touchend. + if (!this.isTouching) { + this.reportScrollEnd(); + } + }; + EnhancedScroller.prototype.reportScrollEnd = function () { + if (this.isScrolling) { + this.trigger('scrollEnd'); + this.isScrolling = false; + } + }; + // Horizontal Scroll Normalization + // ---------------------------------------------------------------------------------------------- + // http://stackoverflow.com/questions/24276619/better-way-to-get-the-viewport-of-a-scrollable-div-in-rtl-mode/24394376#24394376 + // TODO: move all this to util functions + /* + If RTL, and scrolled to the left, returns NEGATIVE value (like Firefox) + */ + EnhancedScroller.prototype.getScrollLeft = function () { + var el = this.el; + var direction = window.getComputedStyle(el).direction; + var val = el.scrollLeft; + if (direction === 'rtl') { + switch (getRtlScrollSystem()) { + case 'positive': + val = (val + el.clientWidth) - el.scrollWidth; + break; + case 'reverse': + val = -val; + break; + } + } + return val; + }; + /* + Accepts a NEGATIVE value for when scrolled in RTL + */ + EnhancedScroller.prototype.setScrollLeft = function (val) { + var el = this.el; + var direction = window.getComputedStyle(el).direction; + if (direction === 'rtl') { + switch (getRtlScrollSystem()) { + case 'positive': + val = (val - el.clientWidth) + el.scrollWidth; + break; + case 'reverse': + val = -val; + break; + } + } + el.scrollLeft = val; + }; + /* + Always returns the number of pixels scrolled from the leftmost position (even if RTL). + Always positive. + */ + EnhancedScroller.prototype.getScrollFromLeft = function () { + var el = this.el; + var direction = window.getComputedStyle(el).direction; + var val = el.scrollLeft; + if (direction === 'rtl') { + switch (getRtlScrollSystem()) { + case 'negative': + val = (val - el.clientWidth) + el.scrollWidth; + break; + case 'reverse': + val = (-val - el.clientWidth) + el.scrollWidth; + break; + } + } + return val; + }; + return EnhancedScroller; +}(ScrollComponent)); +EmitterMixin.mixInto(EnhancedScroller); +// Horizontal Scroll System Detection +// ---------------------------------------------------------------------------------------------- +var _rtlScrollSystem; +function getRtlScrollSystem() { + return _rtlScrollSystem || (_rtlScrollSystem = detectRtlScrollSystem()); +} +function detectRtlScrollSystem() { + var el = htmlToElement("<div style=\" position: absolute; top: -1000px; width: 1px; height: 1px; overflow: scroll; direction: rtl; font-size: 100px; \">A</div>"); + document.body.appendChild(el); + var system; + if (el.scrollLeft > 0) { + system = 'positive'; + } + else { + el.scrollLeft = 1; + if (el.scrollLeft > 0) { + system = 'reverse'; + } + else { + system = 'negative'; + } + } + removeElement(el); + return system; +} + +/* +A Scroller, but with a wrapping div that allows "clipping" away of native scrollbars, +giving the appearance that there are no scrollbars. +*/ +var ClippedScroller = /** @class */ (function () { + /* + Received overflows can be set to 'clipped', meaning scrollbars shouldn't be visible + to the user, but the area should still scroll. + */ + function ClippedScroller(overflowX, overflowY, parentEl) { + this.isHScrollbarsClipped = false; + this.isVScrollbarsClipped = false; + if (overflowX === 'clipped-scroll') { + overflowX = 'scroll'; + this.isHScrollbarsClipped = true; + } + if (overflowY === 'clipped-scroll') { + overflowY = 'scroll'; + this.isVScrollbarsClipped = true; + } + this.enhancedScroll = new EnhancedScroller(overflowX, overflowY); + parentEl.appendChild(this.el = createElement('div', { + className: 'fc-scroller-clip' + })); + this.el.appendChild(this.enhancedScroll.el); + } + ClippedScroller.prototype.destroy = function () { + removeElement(this.el); + }; + ClippedScroller.prototype.updateSize = function () { + var enhancedScroll = this.enhancedScroll; + var scrollEl = enhancedScroll.el; + var edges = computeEdges(scrollEl); + var cssProps = { marginLeft: 0, marginRight: 0, marginTop: 0, marginBottom: 0 }; + // give the inner scrolling div negative margins so that its scrollbars + // are nudged outside of the bounding box of the wrapper, which is overflow:hidden + if (this.isVScrollbarsClipped) { + cssProps.marginLeft = -edges.scrollbarLeft; + cssProps.marginRight = -edges.scrollbarRight; + } + if (this.isHScrollbarsClipped) { + cssProps.marginBottom = -edges.scrollbarBottom; + } + applyStyle(scrollEl, cssProps); + // if we are attempting to hide the scrollbars offscreen, OSX/iOS will still + // display the floating scrollbars. attach a className to force-hide them. + if ((this.isHScrollbarsClipped || (enhancedScroll.overflowX === 'hidden')) && // should never show? + (this.isVScrollbarsClipped || (enhancedScroll.overflowY === 'hidden')) && // should never show? + !( // doesn't have any scrollbar mass + edges.scrollbarLeft || + edges.scrollbarRight || + edges.scrollbarBottom)) { + scrollEl.classList.add('fc-no-scrollbars'); + } + else { + scrollEl.classList.remove('fc-no-scrollbars'); + } + }; + ClippedScroller.prototype.setHeight = function (height) { + this.enhancedScroll.setHeight(height); + }; + /* + Accounts for 'clipped' scrollbars + */ + ClippedScroller.prototype.getScrollbarWidths = function () { + var widths = this.enhancedScroll.getScrollbarWidths(); + if (this.isVScrollbarsClipped) { + widths.left = 0; + widths.right = 0; + } + if (this.isHScrollbarsClipped) { + widths.bottom = 0; + } + return widths; + }; + return ClippedScroller; +}()); + +var ScrollJoiner = /** @class */ (function () { + function ScrollJoiner(axis, scrollers) { + this.axis = axis; + this.scrollers = scrollers; + for (var _i = 0, _a = this.scrollers; _i < _a.length; _i++) { + var scroller = _a[_i]; + this.initScroller(scroller); + } + } + ScrollJoiner.prototype.initScroller = function (scroller) { + var _this = this; + var enhancedScroll = scroller.enhancedScroll; + // when the user scrolls via mousewheel, we know for sure the target + // scroller should be the master. capture the various x-browser events that fire. + var onScroll = function () { + _this.assignMasterScroller(scroller); + }; + 'wheel mousewheel DomMouseScroll MozMousePixelScroll'.split(' ').forEach(function (evName) { + enhancedScroll.el.addEventListener(evName, onScroll); + }); + enhancedScroll + .on('scrollStart', function () { + if (!_this.masterScroller) { + _this.assignMasterScroller(scroller); + } + }) + .on('scroll', function () { + if (scroller === _this.masterScroller) { + for (var _i = 0, _a = _this.scrollers; _i < _a.length; _i++) { + var otherScroller = _a[_i]; + if (otherScroller !== scroller) { + switch (_this.axis) { + case 'horizontal': + otherScroller.enhancedScroll.el.scrollLeft = enhancedScroll.el.scrollLeft; + break; + case 'vertical': + otherScroller.enhancedScroll.setScrollTop(enhancedScroll.getScrollTop()); + break; + } + } + } + } + }) + .on('scrollEnd', function () { + if (scroller === _this.masterScroller) { + _this.unassignMasterScroller(); + } + }); + }; + ScrollJoiner.prototype.assignMasterScroller = function (scroller) { + this.unassignMasterScroller(); + this.masterScroller = scroller; + for (var _i = 0, _a = this.scrollers; _i < _a.length; _i++) { + var otherScroller = _a[_i]; + if (otherScroller !== scroller) { + otherScroller.enhancedScroll.disableTouchScroll(); + } + } + }; + ScrollJoiner.prototype.unassignMasterScroller = function () { + if (this.masterScroller) { + for (var _i = 0, _a = this.scrollers; _i < _a.length; _i++) { + var otherScroller = _a[_i]; + otherScroller.enhancedScroll.enableTouchScroll(); + } + this.masterScroller = null; + } + }; + ScrollJoiner.prototype.update = function () { + var allWidths = this.scrollers.map(function (scroller) { return scroller.getScrollbarWidths(); }); + var maxLeft = 0; + var maxRight = 0; + var maxTop = 0; + var maxBottom = 0; + var widths; + var i; + for (var _i = 0, allWidths_1 = allWidths; _i < allWidths_1.length; _i++) { + widths = allWidths_1[_i]; + maxLeft = Math.max(maxLeft, widths.left); + maxRight = Math.max(maxRight, widths.right); + maxTop = Math.max(maxTop, widths.top); + maxBottom = Math.max(maxBottom, widths.bottom); + } + for (i = 0; i < this.scrollers.length; i++) { + var scroller = this.scrollers[i]; + widths = allWidths[i]; + scroller.enhancedScroll.canvas.setGutters(this.axis === 'horizontal' ? + { + left: maxLeft - widths.left, + right: maxRight - widths.right + } : + { + top: maxTop - widths.top, + bottom: maxBottom - widths.bottom + }); + } + }; + return ScrollJoiner; +}()); + +var HeaderBodyLayout = /** @class */ (function () { + /* + verticalScroll = 'auto' | 'clipped-scroll' + */ + function HeaderBodyLayout(headerContainerEl, bodyContainerEl, verticalScroll) { + this.headerScroller = new ClippedScroller('clipped-scroll', 'hidden', headerContainerEl); + this.bodyScroller = new ClippedScroller('auto', verticalScroll, bodyContainerEl); + this.scrollJoiner = new ScrollJoiner('horizontal', [ + this.headerScroller, + this.bodyScroller + ]); + } + HeaderBodyLayout.prototype.destroy = function () { + this.headerScroller.destroy(); + this.bodyScroller.destroy(); + }; + HeaderBodyLayout.prototype.setHeight = function (totalHeight, isAuto) { + var bodyHeight; + if (isAuto) { + bodyHeight = 'auto'; + } + else { + bodyHeight = totalHeight - this.queryHeadHeight(); + } + this.bodyScroller.setHeight(bodyHeight); + this.headerScroller.updateSize(); // adjusts gutters and classNames + this.bodyScroller.updateSize(); // adjusts gutters and classNames + this.scrollJoiner.update(); + }; + HeaderBodyLayout.prototype.queryHeadHeight = function () { + return this.headerScroller.enhancedScroll.canvas.contentEl.getBoundingClientRect().height; + }; + return HeaderBodyLayout; +}()); + +var TimelineHeader = /** @class */ (function (_super) { + __extends(TimelineHeader, _super); + function TimelineHeader(context, parentEl) { + var _this = _super.call(this, context) || this; + parentEl.appendChild(_this.tableEl = createElement('table', { + className: _this.theme.getClass('tableGrid') + })); + return _this; + } + TimelineHeader.prototype.destroy = function () { + removeElement(this.tableEl); + _super.prototype.destroy.call(this); + }; + TimelineHeader.prototype.render = function (props) { + this.renderDates(props.tDateProfile); + }; + TimelineHeader.prototype.renderDates = function (tDateProfile) { + var _a = this, dateEnv = _a.dateEnv, theme = _a.theme; + var cellRows = tDateProfile.cellRows; + var lastRow = cellRows[cellRows.length - 1]; + var isChrono = asRoughMs(tDateProfile.labelInterval) > asRoughMs(tDateProfile.slotDuration); + var oneDay = isSingleDay(tDateProfile.slotDuration); + var html = '<colgroup>'; + // needs to be a col for each body slat. header cells will have colspans + for (var i = tDateProfile.slotCnt - 1; i >= 0; i--) { + html += '<col/>'; + } + html += '</colgroup>'; + html += '<tbody>'; + for (var _i = 0, cellRows_1 = cellRows; _i < cellRows_1.length; _i++) { + var rowCells = cellRows_1[_i]; + var isLast = rowCells === lastRow; + html += '<tr' + (isChrono && isLast ? ' class="fc-chrono"' : '') + '>'; + for (var _b = 0, rowCells_1 = rowCells; _b < rowCells_1.length; _b++) { + var cell = rowCells_1[_b]; + var headerCellClassNames = [theme.getClass('widgetHeader')]; + if (cell.isWeekStart) { + headerCellClassNames.push('fc-em-cell'); + } + if (oneDay) { + headerCellClassNames = headerCellClassNames.concat(getDayClasses(cell.date, this.props.dateProfile, this.context, true) // adds "today" class and other day-based classes + ); + } + html += + '<th class="' + headerCellClassNames.join(' ') + '"' + + ' data-date="' + dateEnv.formatIso(cell.date, { omitTime: !tDateProfile.isTimeScale, omitTimeZoneOffset: true }) + '"' + + (cell.colspan > 1 ? ' colspan="' + cell.colspan + '"' : '') + + '>' + + '<div class="fc-cell-content">' + + cell.spanHtml + + '</div>' + + '</th>'; + } + html += '</tr>'; + } + html += '</tbody>'; + this.tableEl.innerHTML = html; // TODO: does this work cross-browser? + this.slatColEls = findElements(this.tableEl, 'col'); + this.innerEls = findElements(this.tableEl.querySelector('tr:last-child'), // compound selector won't work because of query-root problem + 'th .fc-cell-text'); + findElements(this.tableEl.querySelectorAll('tr:not(:last-child)'), // compound selector won't work because of query-root problem + 'th .fc-cell-text').forEach(function (innerEl) { + innerEl.classList.add('fc-sticky'); + }); + }; + return TimelineHeader; +}(Component)); + +var TimelineSlats = /** @class */ (function (_super) { + __extends(TimelineSlats, _super); + function TimelineSlats(context, parentEl) { + var _this = _super.call(this, context) || this; + parentEl.appendChild(_this.el = createElement('div', { className: 'fc-slats' })); + return _this; + } + TimelineSlats.prototype.destroy = function () { + removeElement(this.el); + _super.prototype.destroy.call(this); + }; + TimelineSlats.prototype.render = function (props) { + this.renderDates(props.tDateProfile); + }; + TimelineSlats.prototype.renderDates = function (tDateProfile) { + var _a = this, theme = _a.theme, view = _a.view, dateEnv = _a.dateEnv; + var slotDates = tDateProfile.slotDates, isWeekStarts = tDateProfile.isWeekStarts; + var html = '<table class="' + theme.getClass('tableGrid') + '">' + + '<colgroup>'; + for (var i = 0; i < slotDates.length; i++) { + html += '<col/>'; + } + html += '</colgroup>'; + html += '<tbody><tr>'; + for (var i = 0; i < slotDates.length; i++) { + html += this.slatCellHtml(slotDates[i], isWeekStarts[i], tDateProfile); + } + html += '</tr></tbody></table>'; + this.el.innerHTML = html; + this.slatColEls = findElements(this.el, 'col'); + this.slatEls = findElements(this.el, 'td'); + for (var i = 0; i < slotDates.length; i++) { + view.publiclyTrigger('dayRender', [ + { + date: dateEnv.toDate(slotDates[i]), + el: this.slatEls[i], + view: view + } + ]); + } + this.outerCoordCache = new PositionCache(this.el, this.slatEls, true, // isHorizontal + false // isVertical + ); + // for the inner divs within the slats + // used for event rendering and scrollTime, to disregard slat border + this.innerCoordCache = new PositionCache(this.el, findChildren(this.slatEls, 'div'), true, // isHorizontal + false // isVertical + ); + }; + TimelineSlats.prototype.slatCellHtml = function (date, isEm, tDateProfile) { + var _a = this, theme = _a.theme, dateEnv = _a.dateEnv; + var classes; + if (tDateProfile.isTimeScale) { + classes = []; + classes.push(isInt(dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.labelInterval)) ? + 'fc-major' : + 'fc-minor'); + } + else { + classes = getDayClasses(date, this.props.dateProfile, this.context); + classes.push('fc-day'); + } + classes.unshift(theme.getClass('widgetContent')); + if (isEm) { + classes.push('fc-em-cell'); + } + return '<td class="' + classes.join(' ') + '"' + + ' data-date="' + dateEnv.formatIso(date, { omitTime: !tDateProfile.isTimeScale, omitTimeZoneOffset: true }) + '"' + + '><div></div></td>'; + }; + TimelineSlats.prototype.updateSize = function () { + this.outerCoordCache.build(); + this.innerCoordCache.build(); + }; + TimelineSlats.prototype.positionToHit = function (leftPosition) { + var outerCoordCache = this.outerCoordCache; + var tDateProfile = this.props.tDateProfile; + var slatIndex = outerCoordCache.leftToIndex(leftPosition); + if (slatIndex != null) { + // somewhat similar to what TimeGrid does. consolidate? + var slatWidth = outerCoordCache.getWidth(slatIndex); + var partial = this.isRtl ? + (outerCoordCache.rights[slatIndex] - leftPosition) / slatWidth : + (leftPosition - outerCoordCache.lefts[slatIndex]) / slatWidth; + var localSnapIndex = Math.floor(partial * tDateProfile.snapsPerSlot); + var start = this.dateEnv.add(tDateProfile.slotDates[slatIndex], multiplyDuration(tDateProfile.snapDuration, localSnapIndex)); + var end = this.dateEnv.add(start, tDateProfile.snapDuration); + return { + dateSpan: { + range: { start: start, end: end }, + allDay: !this.props.tDateProfile.isTimeScale + }, + dayEl: this.slatColEls[slatIndex], + left: outerCoordCache.lefts[slatIndex], + right: outerCoordCache.rights[slatIndex] + }; + } + return null; + }; + return TimelineSlats; +}(Component)); + +var MIN_AUTO_LABELS = 18; // more than `12` months but less that `24` hours +var MAX_AUTO_SLOTS_PER_LABEL = 6; // allows 6 10-min slots in an hour +var MAX_AUTO_CELLS = 200; // allows 4-days to have a :30 slot duration +config.MAX_TIMELINE_SLOTS = 1000; +// potential nice values for slot-duration and interval-duration +var STOCK_SUB_DURATIONS = [ + { years: 1 }, + { months: 1 }, + { days: 1 }, + { hours: 1 }, + { minutes: 30 }, + { minutes: 15 }, + { minutes: 10 }, + { minutes: 5 }, + { minutes: 1 }, + { seconds: 30 }, + { seconds: 15 }, + { seconds: 10 }, + { seconds: 5 }, + { seconds: 1 }, + { milliseconds: 500 }, + { milliseconds: 100 }, + { milliseconds: 10 }, + { milliseconds: 1 } +]; +function buildTimelineDateProfile(dateProfile, view) { + var dateEnv = view.dateEnv; + var tDateProfile = { + labelInterval: queryDurationOption(view, 'slotLabelInterval'), + slotDuration: queryDurationOption(view, 'slotDuration') + }; + validateLabelAndSlot(tDateProfile, dateProfile, dateEnv); // validate after computed grid duration + ensureLabelInterval(tDateProfile, dateProfile, dateEnv); + ensureSlotDuration(tDateProfile, dateProfile, dateEnv); + var input = view.opt('slotLabelFormat'); + var rawFormats = Array.isArray(input) ? + input + : (input != null) ? + [input] + : + computeHeaderFormats(tDateProfile, dateProfile, dateEnv, view); + tDateProfile.headerFormats = rawFormats.map(function (rawFormat) { + return createFormatter(rawFormat); + }); + tDateProfile.isTimeScale = Boolean(tDateProfile.slotDuration.milliseconds); + var largeUnit = null; + if (!tDateProfile.isTimeScale) { + var slotUnit = greatestDurationDenominator(tDateProfile.slotDuration).unit; + if (/year|month|week/.test(slotUnit)) { + largeUnit = slotUnit; + } + } + tDateProfile.largeUnit = largeUnit; + tDateProfile.emphasizeWeeks = + isSingleDay(tDateProfile.slotDuration) && + currentRangeAs('weeks', dateProfile, dateEnv) >= 2 && + !view.opt('businessHours'); + /* + console.log('label interval =', timelineView.labelInterval.humanize()) + console.log('slot duration =', timelineView.slotDuration.humanize()) + console.log('header formats =', timelineView.headerFormats) + console.log('isTimeScale', timelineView.isTimeScale) + console.log('largeUnit', timelineView.largeUnit) + */ + var rawSnapDuration = view.opt('snapDuration'); + var snapDuration; + var snapsPerSlot; + if (rawSnapDuration) { + snapDuration = createDuration(rawSnapDuration); + snapsPerSlot = wholeDivideDurations(tDateProfile.slotDuration, snapDuration); + // ^ TODO: warning if not whole? + } + if (snapsPerSlot == null) { + snapDuration = tDateProfile.slotDuration; + snapsPerSlot = 1; + } + tDateProfile.snapDuration = snapDuration; + tDateProfile.snapsPerSlot = snapsPerSlot; + // more... + var timeWindowMs = asRoughMs(dateProfile.maxTime) - asRoughMs(dateProfile.minTime); + // TODO: why not use normalizeRange!? + var normalizedStart = normalizeDate(dateProfile.renderRange.start, tDateProfile, dateEnv); + var normalizedEnd = normalizeDate(dateProfile.renderRange.end, tDateProfile, dateEnv); + // apply minTime/maxTime + // TODO: View should be responsible. + if (tDateProfile.isTimeScale) { + normalizedStart = dateEnv.add(normalizedStart, dateProfile.minTime); + normalizedEnd = dateEnv.add(addDays(normalizedEnd, -1), dateProfile.maxTime); + } + tDateProfile.timeWindowMs = timeWindowMs; + tDateProfile.normalizedRange = { start: normalizedStart, end: normalizedEnd }; + var slotDates = []; + var date = normalizedStart; + while (date < normalizedEnd) { + if (isValidDate(date, tDateProfile, dateProfile, view)) { + slotDates.push(date); + } + date = dateEnv.add(date, tDateProfile.slotDuration); + } + tDateProfile.slotDates = slotDates; + // more... + var snapIndex = -1; + var snapDiff = 0; // index of the diff :( + var snapDiffToIndex = []; + var snapIndexToDiff = []; + date = normalizedStart; + while (date < normalizedEnd) { + if (isValidDate(date, tDateProfile, dateProfile, view)) { + snapIndex++; + snapDiffToIndex.push(snapIndex); + snapIndexToDiff.push(snapDiff); + } + else { + snapDiffToIndex.push(snapIndex + 0.5); + } + date = dateEnv.add(date, tDateProfile.snapDuration); + snapDiff++; + } + tDateProfile.snapDiffToIndex = snapDiffToIndex; + tDateProfile.snapIndexToDiff = snapIndexToDiff; + tDateProfile.snapCnt = snapIndex + 1; // is always one behind + tDateProfile.slotCnt = tDateProfile.snapCnt / tDateProfile.snapsPerSlot; + // more... + tDateProfile.isWeekStarts = buildIsWeekStarts(tDateProfile, dateEnv); + tDateProfile.cellRows = buildCellRows(tDateProfile, dateEnv, view); + return tDateProfile; +} +/* +snaps to appropriate unit +*/ +function normalizeDate(date, tDateProfile, dateEnv) { + var normalDate = date; + if (!tDateProfile.isTimeScale) { + normalDate = startOfDay(normalDate); + if (tDateProfile.largeUnit) { + normalDate = dateEnv.startOf(normalDate, tDateProfile.largeUnit); + } + } + return normalDate; +} +/* +snaps to appropriate unit +*/ +function normalizeRange(range, tDateProfile, dateEnv) { + if (!tDateProfile.isTimeScale) { + range = computeVisibleDayRange(range); + if (tDateProfile.largeUnit) { + var dayRange = range; // preserve original result + range = { + start: dateEnv.startOf(range.start, tDateProfile.largeUnit), + end: dateEnv.startOf(range.end, tDateProfile.largeUnit) + }; + // if date is partially through the interval, or is in the same interval as the start, + // make the exclusive end be the *next* interval + if (range.end.valueOf() !== dayRange.end.valueOf() || range.end <= range.start) { + range = { + start: range.start, + end: dateEnv.add(range.end, tDateProfile.slotDuration) + }; + } + } + } + return range; +} +function isValidDate(date, tDateProfile, dateProfile, view) { + if (view.dateProfileGenerator.isHiddenDay(date)) { + return false; + } + else if (tDateProfile.isTimeScale) { + // determine if the time is within minTime/maxTime, which may have wacky values + var day = startOfDay(date); + var timeMs = date.valueOf() - day.valueOf(); + var ms = timeMs - asRoughMs(dateProfile.minTime); // milliseconds since minTime + ms = ((ms % 86400000) + 86400000) % 86400000; // make negative values wrap to 24hr clock + return ms < tDateProfile.timeWindowMs; // before the maxTime? + } + else { + return true; + } +} +function queryDurationOption(view, name) { + var input = view.opt(name); + if (input != null) { + return createDuration(input); + } +} +function validateLabelAndSlot(tDateProfile, dateProfile, dateEnv) { + var currentRange = dateProfile.currentRange; + // make sure labelInterval doesn't exceed the max number of cells + if (tDateProfile.labelInterval) { + var labelCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, tDateProfile.labelInterval); + if (labelCnt > config.MAX_TIMELINE_SLOTS) { + console.warn('slotLabelInterval results in too many cells'); + tDateProfile.labelInterval = null; + } + } + // make sure slotDuration doesn't exceed the maximum number of cells + if (tDateProfile.slotDuration) { + var slotCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, tDateProfile.slotDuration); + if (slotCnt > config.MAX_TIMELINE_SLOTS) { + console.warn('slotDuration results in too many cells'); + tDateProfile.slotDuration = null; + } + } + // make sure labelInterval is a multiple of slotDuration + if (tDateProfile.labelInterval && tDateProfile.slotDuration) { + var slotsPerLabel = wholeDivideDurations(tDateProfile.labelInterval, tDateProfile.slotDuration); + if (slotsPerLabel === null || slotsPerLabel < 1) { + console.warn('slotLabelInterval must be a multiple of slotDuration'); + tDateProfile.slotDuration = null; + } + } +} +function ensureLabelInterval(tDateProfile, dateProfile, dateEnv) { + var currentRange = dateProfile.currentRange; + var labelInterval = tDateProfile.labelInterval; + if (!labelInterval) { + // compute based off the slot duration + // find the largest label interval with an acceptable slots-per-label + var input = void 0; + if (tDateProfile.slotDuration) { + for (var _i = 0, STOCK_SUB_DURATIONS_1 = STOCK_SUB_DURATIONS; _i < STOCK_SUB_DURATIONS_1.length; _i++) { + input = STOCK_SUB_DURATIONS_1[_i]; + var tryLabelInterval = createDuration(input); + var slotsPerLabel = wholeDivideDurations(tryLabelInterval, tDateProfile.slotDuration); + if (slotsPerLabel !== null && slotsPerLabel <= MAX_AUTO_SLOTS_PER_LABEL) { + labelInterval = tryLabelInterval; + break; + } + } + // use the slot duration as a last resort + if (!labelInterval) { + labelInterval = tDateProfile.slotDuration; + } + // compute based off the view's duration + // find the largest label interval that yields the minimum number of labels + } + else { + for (var _a = 0, STOCK_SUB_DURATIONS_2 = STOCK_SUB_DURATIONS; _a < STOCK_SUB_DURATIONS_2.length; _a++) { + input = STOCK_SUB_DURATIONS_2[_a]; + labelInterval = createDuration(input); + var labelCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, labelInterval); + if (labelCnt >= MIN_AUTO_LABELS) { + break; + } + } + } + tDateProfile.labelInterval = labelInterval; + } + return labelInterval; +} +function ensureSlotDuration(tDateProfile, dateProfile, dateEnv) { + var currentRange = dateProfile.currentRange; + var slotDuration = tDateProfile.slotDuration; + if (!slotDuration) { + var labelInterval = ensureLabelInterval(tDateProfile, dateProfile, dateEnv); // will compute if necessary + // compute based off the label interval + // find the largest slot duration that is different from labelInterval, but still acceptable + for (var _i = 0, STOCK_SUB_DURATIONS_3 = STOCK_SUB_DURATIONS; _i < STOCK_SUB_DURATIONS_3.length; _i++) { + var input = STOCK_SUB_DURATIONS_3[_i]; + var trySlotDuration = createDuration(input); + var slotsPerLabel = wholeDivideDurations(labelInterval, trySlotDuration); + if (slotsPerLabel !== null && slotsPerLabel > 1 && slotsPerLabel <= MAX_AUTO_SLOTS_PER_LABEL) { + slotDuration = trySlotDuration; + break; + } + } + // only allow the value if it won't exceed the view's # of slots limit + if (slotDuration) { + var slotCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, slotDuration); + if (slotCnt > MAX_AUTO_CELLS) { + slotDuration = null; + } + } + // use the label interval as a last resort + if (!slotDuration) { + slotDuration = labelInterval; + } + tDateProfile.slotDuration = slotDuration; + } + return slotDuration; +} +function computeHeaderFormats(tDateProfile, dateProfile, dateEnv, view) { + var format1; + var format2; + var labelInterval = tDateProfile.labelInterval; + var unit = greatestDurationDenominator(labelInterval).unit; + var weekNumbersVisible = view.opt('weekNumbers'); + var format0 = (format1 = (format2 = null)); + // NOTE: weekNumber computation function wont work + if ((unit === 'week') && !weekNumbersVisible) { + unit = 'day'; + } + switch (unit) { + case 'year': + format0 = { year: 'numeric' }; // '2015' + break; + case 'month': + if (currentRangeAs('years', dateProfile, dateEnv) > 1) { + format0 = { year: 'numeric' }; // '2015' + } + format1 = { month: 'short' }; // 'Jan' + break; + case 'week': + if (currentRangeAs('years', dateProfile, dateEnv) > 1) { + format0 = { year: 'numeric' }; // '2015' + } + format1 = { week: 'narrow' }; // 'Wk4' + break; + case 'day': + if (currentRangeAs('years', dateProfile, dateEnv) > 1) { + format0 = { year: 'numeric', month: 'long' }; // 'January 2014' + } + else if (currentRangeAs('months', dateProfile, dateEnv) > 1) { + format0 = { month: 'long' }; // 'January' + } + if (weekNumbersVisible) { + format1 = { week: 'short' }; // 'Wk 4' + } + format2 = { weekday: 'narrow', day: 'numeric' }; // 'Su 9' + break; + case 'hour': + if (weekNumbersVisible) { + format0 = { week: 'short' }; // 'Wk 4' + } + if (currentRangeAs('days', dateProfile, dateEnv) > 1) { + format1 = { weekday: 'short', day: 'numeric', month: 'numeric', omitCommas: true }; // Sat 4/7 + } + format2 = { + hour: 'numeric', + minute: '2-digit', + omitZeroMinute: true, + meridiem: 'short' + }; + break; + case 'minute': + // sufficiently large number of different minute cells? + if ((asRoughMinutes(labelInterval) / 60) >= MAX_AUTO_SLOTS_PER_LABEL) { + format0 = { + hour: 'numeric', + meridiem: 'short' + }; + format1 = function (params) { + return ':' + padStart(params.date.minute, 2); // ':30' + }; + } + else { + format0 = { + hour: 'numeric', + minute: 'numeric', + meridiem: 'short' + }; + } + break; + case 'second': + // sufficiently large number of different second cells? + if ((asRoughSeconds(labelInterval) / 60) >= MAX_AUTO_SLOTS_PER_LABEL) { + format0 = { hour: 'numeric', minute: '2-digit', meridiem: 'lowercase' }; // '8:30 PM' + format1 = function (params) { + return ':' + padStart(params.date.second, 2); // ':30' + }; + } + else { + format0 = { hour: 'numeric', minute: '2-digit', second: '2-digit', meridiem: 'lowercase' }; // '8:30:45 PM' + } + break; + case 'millisecond': + format0 = { hour: 'numeric', minute: '2-digit', second: '2-digit', meridiem: 'lowercase' }; // '8:30:45 PM' + format1 = function (params) { + return '.' + padStart(params.millisecond, 3); + }; + break; + } + return [].concat(format0 || [], format1 || [], format2 || []); +} +// Compute the number of the give units in the "current" range. +// Won't go more precise than days. +// Will return `0` if there's not a clean whole interval. +function currentRangeAs(unit, dateProfile, dateEnv) { + var range = dateProfile.currentRange; + var res = null; + if (unit === 'years') { + res = dateEnv.diffWholeYears(range.start, range.end); + } + else if (unit === 'months') { + res = dateEnv.diffWholeMonths(range.start, range.end); + } + else if (unit === 'weeks') { + res = dateEnv.diffWholeMonths(range.start, range.end); + } + else if (unit === 'days') { + res = diffWholeDays(range.start, range.end); + } + return res || 0; +} +function buildIsWeekStarts(tDateProfile, dateEnv) { + var slotDates = tDateProfile.slotDates, emphasizeWeeks = tDateProfile.emphasizeWeeks; + var prevWeekNumber = null; + var isWeekStarts = []; + for (var _i = 0, slotDates_1 = slotDates; _i < slotDates_1.length; _i++) { + var slotDate = slotDates_1[_i]; + var weekNumber = dateEnv.computeWeekNumber(slotDate); + var isWeekStart = emphasizeWeeks && (prevWeekNumber !== null) && (prevWeekNumber !== weekNumber); + prevWeekNumber = weekNumber; + isWeekStarts.push(isWeekStart); + } + return isWeekStarts; +} +function buildCellRows(tDateProfile, dateEnv, view) { + var slotDates = tDateProfile.slotDates; + var formats = tDateProfile.headerFormats; + var cellRows = formats.map(function (format) { return []; }); // indexed by row,col + // specifically for navclicks + var rowUnits = formats.map(function (format) { + return format.getLargestUnit ? format.getLargestUnit() : null; + }); + // builds cellRows and slotCells + for (var i = 0; i < slotDates.length; i++) { + var date = slotDates[i]; + var isWeekStart = tDateProfile.isWeekStarts[i]; + for (var row = 0; row < formats.length; row++) { + var format = formats[row]; + var rowCells = cellRows[row]; + var leadingCell = rowCells[rowCells.length - 1]; + var isSuperRow = (formats.length > 1) && (row < (formats.length - 1)); // more than one row and not the last + var newCell = null; + if (isSuperRow) { + var text = dateEnv.format(date, format); + if (!leadingCell || (leadingCell.text !== text)) { + newCell = buildCellObject(date, text, rowUnits[row], view); + } + else { + leadingCell.colspan += 1; + } + } + else { + if (!leadingCell || + isInt(dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.labelInterval))) { + var text = dateEnv.format(date, format); + newCell = buildCellObject(date, text, rowUnits[row], view); + } + else { + leadingCell.colspan += 1; + } + } + if (newCell) { + newCell.weekStart = isWeekStart; + rowCells.push(newCell); + } + } + } + return cellRows; +} +function buildCellObject(date, text, rowUnit, view) { + var spanHtml = buildGotoAnchorHtml(view, { + date: date, + type: rowUnit, + forceOff: !rowUnit + }, { + 'class': 'fc-cell-text' + }, htmlEscape(text)); + return { text: text, spanHtml: spanHtml, date: date, colspan: 1, isWeekStart: false }; +} + +var TimelineNowIndicator = /** @class */ (function () { + function TimelineNowIndicator(headParent, bodyParent) { + this.headParent = headParent; + this.bodyParent = bodyParent; + } + TimelineNowIndicator.prototype.render = function (coord, isRtl) { + var styleProps = isRtl ? { right: -coord } : { left: coord }; + this.headParent.appendChild(this.arrowEl = createElement('div', { + className: 'fc-now-indicator fc-now-indicator-arrow', + style: styleProps + })); + this.bodyParent.appendChild(this.lineEl = createElement('div', { + className: 'fc-now-indicator fc-now-indicator-line', + style: styleProps + })); + }; + TimelineNowIndicator.prototype.unrender = function () { + if (this.arrowEl) { + removeElement(this.arrowEl); + } + if (this.lineEl) { + removeElement(this.lineEl); + } + }; + return TimelineNowIndicator; +}()); + +var STICKY_PROP_VAL = computeStickyPropVal(); // if null, means not supported at all +var IS_MS_EDGE = /Edge/.test(navigator.userAgent); +var IS_SAFARI = STICKY_PROP_VAL === '-webkit-sticky'; // good b/c doesn't confuse chrome +var STICKY_CLASSNAME = 'fc-sticky'; +/* +useful beyond the native position:sticky for these reasons: +- support in IE11 +- nice centering support +*/ +var StickyScroller = /** @class */ (function () { + function StickyScroller(scroller, isRtl, isVertical) { + var _this = this; + this.usingRelative = null; + /* + known bug: called twice on init. problem when mixing with ScrollJoiner + */ + this.updateSize = function () { + var els = Array.prototype.slice.call(_this.scroller.canvas.el.querySelectorAll('.' + STICKY_CLASSNAME)); + var elGeoms = _this.queryElGeoms(els); + var viewportWidth = _this.scroller.el.clientWidth; + if (_this.usingRelative) { + var elDestinations = _this.computeElDestinations(elGeoms, viewportWidth); // read before prepPositioning + assignRelativePositions(els, elGeoms, elDestinations); + } + else { + assignStickyPositions(els, elGeoms, viewportWidth); + } + }; + this.scroller = scroller; + this.usingRelative = + !STICKY_PROP_VAL || // IE11 + (IS_MS_EDGE && isRtl) || // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/18883305/ + ((IS_MS_EDGE || IS_SAFARI) && isVertical); // because doesn't work with rowspan in tables, our only vertial use + if (this.usingRelative) { + scroller.on('scrollEnd', this.updateSize); + } + } + StickyScroller.prototype.destroy = function () { + this.scroller.off('scrollEnd', this.updateSize); + }; + StickyScroller.prototype.queryElGeoms = function (els) { + var canvasOrigin = this.scroller.canvas.el.getBoundingClientRect(); + var elGeoms = []; + for (var _i = 0, els_1 = els; _i < els_1.length; _i++) { + var el = els_1[_i]; + var parentBound = translateRect(el.parentNode.getBoundingClientRect(), -canvasOrigin.left, -canvasOrigin.top); + var elRect = el.getBoundingClientRect(); + var computedStyles = window.getComputedStyle(el); + var computedTextAlign = window.getComputedStyle(el.parentNode).textAlign; // ask the parent + var intendedTextAlign = computedTextAlign; + var naturalBound = null; + if (computedStyles.position !== 'sticky') { + naturalBound = translateRect(elRect, -canvasOrigin.left - (parseFloat(computedStyles.left) || 0), // could be 'auto' + -canvasOrigin.top - (parseFloat(computedStyles.top) || 0)); + } + if (el.hasAttribute('data-sticky-center')) { + intendedTextAlign = 'center'; + } + elGeoms.push({ + parentBound: parentBound, + naturalBound: naturalBound, + elWidth: elRect.width, + elHeight: elRect.height, + computedTextAlign: computedTextAlign, + intendedTextAlign: intendedTextAlign + }); + } + return elGeoms; + }; + StickyScroller.prototype.computeElDestinations = function (elGeoms, viewportWidth) { + var viewportLeft = this.scroller.getScrollFromLeft(); + var viewportTop = this.scroller.getScrollTop(); + var viewportRight = viewportLeft + viewportWidth; + return elGeoms.map(function (elGeom) { + var elWidth = elGeom.elWidth, elHeight = elGeom.elHeight, parentBound = elGeom.parentBound, naturalBound = elGeom.naturalBound; + var destLeft; // relative to canvas topleft + var destTop; // " + switch (elGeom.intendedTextAlign) { + case 'left': + destLeft = viewportLeft; + break; + case 'right': + destLeft = viewportRight - elWidth; + break; + case 'center': + destLeft = (viewportLeft + viewportRight) / 2 - elWidth / 2; + break; + } + destLeft = Math.min(destLeft, parentBound.right - elWidth); + destLeft = Math.max(destLeft, parentBound.left); + destTop = viewportTop; + destTop = Math.min(destTop, parentBound.bottom - elHeight); + destTop = Math.max(destTop, naturalBound.top); // better to use natural top for upper bound + return { left: destLeft, top: destTop }; + }); + }; + return StickyScroller; +}()); +function assignRelativePositions(els, elGeoms, elDestinations) { + els.forEach(function (el, i) { + var naturalBound = elGeoms[i].naturalBound; + applyStyle(el, { + position: 'relative', + left: elDestinations[i].left - naturalBound.left, + top: elDestinations[i].top - naturalBound.top + }); + }); +} +function assignStickyPositions(els, elGeoms, viewportWidth) { + els.forEach(function (el, i) { + var stickyLeft = 0; + if (elGeoms[i].intendedTextAlign === 'center') { + stickyLeft = (viewportWidth - elGeoms[i].elWidth) / 2; + // needs to be forced to left? + if (elGeoms[i].computedTextAlign === 'center') { + el.setAttribute('data-sticky-center', '') // remember for next queryElGeoms + ; + el.parentNode.style.textAlign = 'left'; + } + } + applyStyle(el, { + position: STICKY_PROP_VAL, + left: stickyLeft, + right: 0, + top: 0 + }); + }); +} +function computeStickyPropVal() { + var el = htmlToElement('<div style="position:-webkit-sticky;position:sticky"></div>'); + var val = el.style.position; + if (val.indexOf('sticky') !== -1) { + return val; + } + else { + return null; + } +} + +var TimeAxis = /** @class */ (function (_super) { + __extends(TimeAxis, _super); + function TimeAxis(context, headerContainerEl, bodyContainerEl) { + var _this = _super.call(this, context) || this; + var layout = _this.layout = new HeaderBodyLayout(headerContainerEl, bodyContainerEl, 'auto'); + var headerEnhancedScroller = layout.headerScroller.enhancedScroll; + var bodyEnhancedScroller = layout.bodyScroller.enhancedScroll; + // needs to go after layout, which has ScrollJoiner + _this.headStickyScroller = new StickyScroller(headerEnhancedScroller, _this.isRtl, false); // isVertical=false + _this.bodyStickyScroller = new StickyScroller(bodyEnhancedScroller, _this.isRtl, false); // isVertical=false + _this.header = new TimelineHeader(context, headerEnhancedScroller.canvas.contentEl); + _this.slats = new TimelineSlats(context, bodyEnhancedScroller.canvas.bgEl); + _this.nowIndicator = new TimelineNowIndicator(headerEnhancedScroller.canvas.el, bodyEnhancedScroller.canvas.el); + return _this; + } + TimeAxis.prototype.destroy = function () { + this.layout.destroy(); + this.header.destroy(); + this.slats.destroy(); + this.nowIndicator.unrender(); + this.headStickyScroller.destroy(); + this.bodyStickyScroller.destroy(); + _super.prototype.destroy.call(this); + }; + TimeAxis.prototype.render = function (props) { + var tDateProfile = this.tDateProfile = + buildTimelineDateProfile(props.dateProfile, this.view); // TODO: cache + this.header.receiveProps({ + dateProfile: props.dateProfile, + tDateProfile: tDateProfile + }); + this.slats.receiveProps({ + dateProfile: props.dateProfile, + tDateProfile: tDateProfile + }); + }; + // Now Indicator + // ------------------------------------------------------------------------------------------ + TimeAxis.prototype.getNowIndicatorUnit = function (dateProfile) { + // yuck + var tDateProfile = this.tDateProfile = + buildTimelineDateProfile(dateProfile, this.view); // TODO: cache + if (tDateProfile.isTimeScale) { + return greatestDurationDenominator(tDateProfile.slotDuration).unit; + } + }; + // will only execute if isTimeScale + TimeAxis.prototype.renderNowIndicator = function (date) { + if (rangeContainsMarker(this.tDateProfile.normalizedRange, date)) { + this.nowIndicator.render(this.dateToCoord(date), this.isRtl); + } + }; + // will only execute if isTimeScale + TimeAxis.prototype.unrenderNowIndicator = function () { + this.nowIndicator.unrender(); + }; + // Sizing + // ------------------------------------------------------------------------------------------ + TimeAxis.prototype.updateSize = function (isResize, totalHeight, isAuto) { + this.applySlotWidth(this.computeSlotWidth()); + // adjusts gutters. do after slot widths set + this.layout.setHeight(totalHeight, isAuto); + // pretty much just queries coords. do last + this.slats.updateSize(); + }; + TimeAxis.prototype.updateStickyScrollers = function () { + this.headStickyScroller.updateSize(); + this.bodyStickyScroller.updateSize(); + }; + TimeAxis.prototype.computeSlotWidth = function () { + var slotWidth = this.opt('slotWidth') || ''; + if (slotWidth === '') { + slotWidth = this.computeDefaultSlotWidth(this.tDateProfile); + } + return slotWidth; + }; + TimeAxis.prototype.computeDefaultSlotWidth = function (tDateProfile) { + var maxInnerWidth = 0; // TODO: harness core's `matchCellWidths` for this + this.header.innerEls.forEach(function (innerEl, i) { + maxInnerWidth = Math.max(maxInnerWidth, innerEl.getBoundingClientRect().width); + }); + var headingCellWidth = Math.ceil(maxInnerWidth) + 1; // assume no padding, and one pixel border + // in TimelineView.defaults we ensured that labelInterval is an interval of slotDuration + // TODO: rename labelDuration? + var slotsPerLabel = wholeDivideDurations(tDateProfile.labelInterval, tDateProfile.slotDuration); + var slotWidth = Math.ceil(headingCellWidth / slotsPerLabel); + var minWidth = window.getComputedStyle(this.header.slatColEls[0]).minWidth; + if (minWidth) { + minWidth = parseInt(minWidth, 10); + if (minWidth) { + slotWidth = Math.max(slotWidth, minWidth); + } + } + return slotWidth; + }; + TimeAxis.prototype.applySlotWidth = function (slotWidth) { + var _a = this, layout = _a.layout, tDateProfile = _a.tDateProfile; + var containerWidth = ''; + var containerMinWidth = ''; + var nonLastSlotWidth = ''; + if (slotWidth !== '') { + slotWidth = Math.round(slotWidth); + containerWidth = slotWidth * tDateProfile.slotDates.length; + containerMinWidth = ''; + nonLastSlotWidth = slotWidth; + var availableWidth = layout.bodyScroller.enhancedScroll.getClientWidth(); + if (availableWidth > containerWidth) { + containerMinWidth = availableWidth; + containerWidth = ''; + nonLastSlotWidth = Math.floor(availableWidth / tDateProfile.slotDates.length); + } + } + layout.headerScroller.enhancedScroll.canvas.setWidth(containerWidth); + layout.headerScroller.enhancedScroll.canvas.setMinWidth(containerMinWidth); + layout.bodyScroller.enhancedScroll.canvas.setWidth(containerWidth); + layout.bodyScroller.enhancedScroll.canvas.setMinWidth(containerMinWidth); + if (nonLastSlotWidth !== '') { + this.header.slatColEls.slice(0, -1).concat(this.slats.slatColEls.slice(0, -1)).forEach(function (el) { + el.style.width = nonLastSlotWidth + 'px'; + }); + } + }; + // returned value is between 0 and the number of snaps + TimeAxis.prototype.computeDateSnapCoverage = function (date) { + var _a = this, dateEnv = _a.dateEnv, tDateProfile = _a.tDateProfile; + var snapDiff = dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.snapDuration); + if (snapDiff < 0) { + return 0; + } + else if (snapDiff >= tDateProfile.snapDiffToIndex.length) { + return tDateProfile.snapCnt; + } + else { + var snapDiffInt = Math.floor(snapDiff); + var snapCoverage = tDateProfile.snapDiffToIndex[snapDiffInt]; + if (isInt(snapCoverage)) { // not an in-between value + snapCoverage += snapDiff - snapDiffInt; // add the remainder + } + else { + // a fractional value, meaning the date is not visible + // always round up in this case. works for start AND end dates in a range. + snapCoverage = Math.ceil(snapCoverage); + } + return snapCoverage; + } + }; + // for LTR, results range from 0 to width of area + // for RTL, results range from negative width of area to 0 + TimeAxis.prototype.dateToCoord = function (date) { + var tDateProfile = this.tDateProfile; + var snapCoverage = this.computeDateSnapCoverage(date); + var slotCoverage = snapCoverage / tDateProfile.snapsPerSlot; + var slotIndex = Math.floor(slotCoverage); + slotIndex = Math.min(slotIndex, tDateProfile.slotCnt - 1); + var partial = slotCoverage - slotIndex; + var _a = this.slats, innerCoordCache = _a.innerCoordCache, outerCoordCache = _a.outerCoordCache; + if (this.isRtl) { + return (outerCoordCache.rights[slotIndex] - + (innerCoordCache.getWidth(slotIndex) * partial)) - outerCoordCache.originClientRect.width; + } + else { + return (outerCoordCache.lefts[slotIndex] + + (innerCoordCache.getWidth(slotIndex) * partial)); + } + }; + TimeAxis.prototype.rangeToCoords = function (range) { + if (this.isRtl) { + return { right: this.dateToCoord(range.start), left: this.dateToCoord(range.end) }; + } + else { + return { left: this.dateToCoord(range.start), right: this.dateToCoord(range.end) }; + } + }; + // Scrolling + // ------------------------------------------------------------------------------------------ + TimeAxis.prototype.computeDateScroll = function (duration) { + var dateEnv = this.dateEnv; + var dateProfile = this.props.dateProfile; + var left = 0; + if (dateProfile) { + left = this.dateToCoord(dateEnv.add(startOfDay(dateProfile.activeRange.start), // startOfDay needed? + duration)); + // hack to overcome the left borders of non-first slat + if (!this.isRtl && left) { + left += 1; + } + } + return { left: left }; + }; + TimeAxis.prototype.queryDateScroll = function () { + var enhancedScroll = this.layout.bodyScroller.enhancedScroll; + return { + left: enhancedScroll.getScrollLeft() + }; + }; + TimeAxis.prototype.applyDateScroll = function (scroll) { + // TODO: lame we have to update both. use the scrolljoiner instead maybe + this.layout.bodyScroller.enhancedScroll.setScrollLeft(scroll.left || 0); + this.layout.headerScroller.enhancedScroll.setScrollLeft(scroll.left || 0); + }; + return TimeAxis; +}(Component)); + +var TimelineLaneEventRenderer = /** @class */ (function (_super) { + __extends(TimelineLaneEventRenderer, _super); + function TimelineLaneEventRenderer(context, masterContainerEl, timeAxis) { + var _this = _super.call(this, context) || this; + _this.masterContainerEl = masterContainerEl; + _this.timeAxis = timeAxis; + return _this; + } + TimelineLaneEventRenderer.prototype.renderSegHtml = function (seg, mirrorInfo) { + var view = this.context.view; + var eventRange = seg.eventRange; + var eventDef = eventRange.def; + var eventUi = eventRange.ui; + var isDraggable = view.computeEventDraggable(eventDef, eventUi); + var isResizableFromStart = seg.isStart && view.computeEventStartResizable(eventDef, eventUi); + var isResizableFromEnd = seg.isEnd && view.computeEventEndResizable(eventDef, eventUi); + var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd, mirrorInfo); + classes.unshift('fc-timeline-event', 'fc-h-event'); + var timeText = this.getTimeText(eventRange); + return '<a class="' + classes.join(' ') + '" style="' + cssToStr(this.getSkinCss(eventUi)) + '"' + + (eventDef.url ? + ' href="' + htmlEscape(eventDef.url) + '"' : + '') + + '>' + + (timeText ? + '<span class="fc-time-wrap">' + + '<span class="fc-time">' + + htmlEscape(timeText) + + '</span>' + + '</span>' + : + '') + + '<span class="fc-title-wrap">' + + '<span class="fc-title fc-sticky">' + + (eventDef.title ? htmlEscape(eventDef.title) : ' ') + + '</span>' + + '</span>' + + (isResizableFromStart ? + '<div class="fc-resizer fc-start-resizer"></div>' : + '') + + (isResizableFromEnd ? + '<div class="fc-resizer fc-end-resizer"></div>' : + '') + + '</a>'; + }; + TimelineLaneEventRenderer.prototype.computeDisplayEventTime = function () { + return !this.timeAxis.tDateProfile.isTimeScale; // because times should be obvious via axis + }; + TimelineLaneEventRenderer.prototype.computeDisplayEventEnd = function () { + return false; + }; + // Computes a default event time formatting string if `timeFormat` is not explicitly defined + TimelineLaneEventRenderer.prototype.computeEventTimeFormat = function () { + return { + hour: 'numeric', + minute: '2-digit', + omitZeroMinute: true, + meridiem: 'narrow' + }; + }; + TimelineLaneEventRenderer.prototype.attachSegs = function (segs, mirrorInfo) { + if (!this.el && this.masterContainerEl) { + this.el = createElement('div', { className: 'fc-event-container' }); + if (mirrorInfo) { + this.el.classList.add('fc-mirror-container'); + } + this.masterContainerEl.appendChild(this.el); + } + if (this.el) { + for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { + var seg = segs_1[_i]; + this.el.appendChild(seg.el); + } + } + }; + TimelineLaneEventRenderer.prototype.detachSegs = function (segs) { + for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { + var seg = segs_2[_i]; + removeElement(seg.el); + } + }; + // computes AND assigns (assigns the left/right at least). bad + TimelineLaneEventRenderer.prototype.computeSegSizes = function (segs) { + var timeAxis = this.timeAxis; + for (var _i = 0, segs_3 = segs; _i < segs_3.length; _i++) { + var seg = segs_3[_i]; + var coords = timeAxis.rangeToCoords(seg); // works because Seg has start/end + applyStyle(seg.el, { + left: (seg.left = coords.left), + right: -(seg.right = coords.right) + }); + } + }; + TimelineLaneEventRenderer.prototype.assignSegSizes = function (segs) { + if (!this.el) { + return; + } + // compute seg verticals + for (var _i = 0, segs_4 = segs; _i < segs_4.length; _i++) { + var seg = segs_4[_i]; + seg.height = computeHeightAndMargins(seg.el); + } + this.buildSegLevels(segs); // populates above/below props for computeOffsetForSegs + var totalHeight = computeOffsetForSegs(segs); // also assigns seg.top + applyStyleProp(this.el, 'height', totalHeight); + // assign seg verticals + for (var _a = 0, segs_5 = segs; _a < segs_5.length; _a++) { + var seg = segs_5[_a]; + applyStyleProp(seg.el, 'top', seg.top); + } + }; + TimelineLaneEventRenderer.prototype.buildSegLevels = function (segs) { + var segLevels = []; + segs = this.sortEventSegs(segs); + for (var _i = 0, segs_6 = segs; _i < segs_6.length; _i++) { + var unplacedSeg = segs_6[_i]; + unplacedSeg.above = []; + // determine the first level with no collisions + var level = 0; // level index + while (level < segLevels.length) { + var isLevelCollision = false; + // determine collisions + for (var _a = 0, _b = segLevels[level]; _a < _b.length; _a++) { + var placedSeg = _b[_a]; + if (timeRowSegsCollide(unplacedSeg, placedSeg)) { + unplacedSeg.above.push(placedSeg); + isLevelCollision = true; + } + } + if (isLevelCollision) { + level += 1; + } + else { + break; + } + } + // insert into the first non-colliding level. create if necessary + (segLevels[level] || (segLevels[level] = [])) + .push(unplacedSeg); + // record possible colliding segments below (TODO: automated test for this) + level += 1; + while (level < segLevels.length) { + for (var _c = 0, _d = segLevels[level]; _c < _d.length; _c++) { + var belowSeg = _d[_c]; + if (timeRowSegsCollide(unplacedSeg, belowSeg)) { + belowSeg.above.push(unplacedSeg); + } + } + level += 1; + } + } + return segLevels; + }; + return TimelineLaneEventRenderer; +}(FgEventRenderer)); +function computeOffsetForSegs(segs) { + var max = 0; + for (var _i = 0, segs_7 = segs; _i < segs_7.length; _i++) { + var seg = segs_7[_i]; + max = Math.max(max, computeOffsetForSeg(seg)); + } + return max; +} +function computeOffsetForSeg(seg) { + if ((seg.top == null)) { + seg.top = computeOffsetForSegs(seg.above); + } + return seg.top + seg.height; +} +function timeRowSegsCollide(seg0, seg1) { + return (seg0.left < seg1.right) && (seg0.right > seg1.left); +} + +var TimelineLaneFillRenderer = /** @class */ (function (_super) { + __extends(TimelineLaneFillRenderer, _super); + function TimelineLaneFillRenderer(context, masterContainerEl, timeAxis) { + var _this = _super.call(this, context) || this; + _this.masterContainerEl = masterContainerEl; + _this.timeAxis = timeAxis; + return _this; + } + TimelineLaneFillRenderer.prototype.attachSegs = function (type, segs) { + if (segs.length) { + var className = void 0; + if (type === 'businessHours') { + className = 'bgevent'; + } + else { + className = type.toLowerCase(); + } + // making a new container each time is OKAY + // all types of segs (background or business hours or whatever) are rendered in one pass + var containerEl = createElement('div', { className: 'fc-' + className + '-container' }); + this.masterContainerEl.appendChild(containerEl); + for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { + var seg = segs_1[_i]; + containerEl.appendChild(seg.el); + } + return [containerEl]; // return value + } + }; + TimelineLaneFillRenderer.prototype.computeSegSizes = function (segs) { + var timeAxis = this.timeAxis; + for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { + var seg = segs_2[_i]; + var coords = timeAxis.rangeToCoords(seg); + seg.left = coords.left; + seg.right = coords.right; + } + }; + TimelineLaneFillRenderer.prototype.assignSegSizes = function (segs) { + for (var _i = 0, segs_3 = segs; _i < segs_3.length; _i++) { + var seg = segs_3[_i]; + applyStyle(seg.el, { + left: seg.left, + right: -seg.right + }); + } + }; + return TimelineLaneFillRenderer; +}(FillRenderer)); + +var TimelineLane = /** @class */ (function (_super) { + __extends(TimelineLane, _super); + function TimelineLane(context, fgContainerEl, bgContainerEl, timeAxis) { + var _this = _super.call(this, context, bgContainerEl) // should el be bgContainerEl??? + || this; + _this.slicer = new TimelineLaneSlicer(); + _this.renderEventDrag = memoizeRendering(_this._renderEventDrag, _this._unrenderEventDrag); + _this.renderEventResize = memoizeRendering(_this._renderEventResize, _this._unrenderEventResize); + var fillRenderer = _this.fillRenderer = new TimelineLaneFillRenderer(context, bgContainerEl, timeAxis); + var eventRenderer = _this.eventRenderer = new TimelineLaneEventRenderer(context, fgContainerEl, timeAxis); + _this.mirrorRenderer = new TimelineLaneEventRenderer(context, fgContainerEl, timeAxis); + _this.renderBusinessHours = memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'businessHours'), fillRenderer.unrender.bind(fillRenderer, 'businessHours')); + _this.renderDateSelection = memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'highlight'), fillRenderer.unrender.bind(fillRenderer, 'highlight')); + _this.renderBgEvents = memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'bgEvent'), fillRenderer.unrender.bind(fillRenderer, 'bgEvent')); + _this.renderFgEvents = memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer)); + _this.renderEventSelection = memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]); + _this.timeAxis = timeAxis; + return _this; + } + TimelineLane.prototype.render = function (props) { + var slicedProps = this.slicer.sliceProps(props, props.dateProfile, this.timeAxis.tDateProfile.isTimeScale ? null : props.nextDayThreshold, this, this.timeAxis); + this.renderBusinessHours(slicedProps.businessHourSegs); + this.renderDateSelection(slicedProps.dateSelectionSegs); + this.renderBgEvents(slicedProps.bgEventSegs); + this.renderFgEvents(slicedProps.fgEventSegs); + this.renderEventSelection(slicedProps.eventSelection); + this.renderEventDrag(slicedProps.eventDrag); + this.renderEventResize(slicedProps.eventResize); + }; + TimelineLane.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.renderBusinessHours.unrender(); + this.renderDateSelection.unrender(); + this.renderBgEvents.unrender(); + this.renderFgEvents.unrender(); + this.renderEventSelection.unrender(); + this.renderEventDrag.unrender(); + this.renderEventResize.unrender(); + }; + TimelineLane.prototype._renderEventDrag = function (state) { + if (state) { + this.eventRenderer.hideByHash(state.affectedInstances); + this.mirrorRenderer.renderSegs(state.segs, { isDragging: true, sourceSeg: state.sourceSeg }); + } + }; + TimelineLane.prototype._unrenderEventDrag = function (state) { + if (state) { + this.eventRenderer.showByHash(state.affectedInstances); + this.mirrorRenderer.unrender(state.segs, { isDragging: true, sourceSeg: state.sourceSeg }); + } + }; + TimelineLane.prototype._renderEventResize = function (state) { + if (state) { + // HACK. eventRenderer and fillRenderer both use these segs. would compete over seg.el + var segsForHighlight = state.segs.map(function (seg) { + return __assign({}, seg); + }); + this.eventRenderer.hideByHash(state.affectedInstances); + this.fillRenderer.renderSegs('highlight', segsForHighlight); + this.mirrorRenderer.renderSegs(state.segs, { isDragging: true, sourceSeg: state.sourceSeg }); + } + }; + TimelineLane.prototype._unrenderEventResize = function (state) { + if (state) { + this.eventRenderer.showByHash(state.affectedInstances); + this.fillRenderer.unrender('highlight'); + this.mirrorRenderer.unrender(state.segs, { isDragging: true, sourceSeg: state.sourceSeg }); + } + }; + TimelineLane.prototype.updateSize = function (isResize) { + var _a = this, fillRenderer = _a.fillRenderer, eventRenderer = _a.eventRenderer, mirrorRenderer = _a.mirrorRenderer; + fillRenderer.computeSizes(isResize); + eventRenderer.computeSizes(isResize); + mirrorRenderer.computeSizes(isResize); + fillRenderer.assignSizes(isResize); + eventRenderer.assignSizes(isResize); + mirrorRenderer.assignSizes(isResize); + }; + return TimelineLane; +}(DateComponent)); +var TimelineLaneSlicer = /** @class */ (function (_super) { + __extends(TimelineLaneSlicer, _super); + function TimelineLaneSlicer() { + return _super !== null && _super.apply(this, arguments) || this; + } + TimelineLaneSlicer.prototype.sliceRange = function (origRange, timeAxis) { + var tDateProfile = timeAxis.tDateProfile; + var dateProfile = timeAxis.props.dateProfile; + var normalRange = normalizeRange(origRange, tDateProfile, timeAxis.dateEnv); + var segs = []; + // protect against when the span is entirely in an invalid date region + if (timeAxis.computeDateSnapCoverage(normalRange.start) < timeAxis.computeDateSnapCoverage(normalRange.end)) { + // intersect the footprint's range with the grid's range + var slicedRange = intersectRanges(normalRange, tDateProfile.normalizedRange); + if (slicedRange) { + segs.push({ + start: slicedRange.start, + end: slicedRange.end, + isStart: slicedRange.start.valueOf() === normalRange.start.valueOf() && isValidDate(slicedRange.start, tDateProfile, dateProfile, timeAxis.view), + isEnd: slicedRange.end.valueOf() === normalRange.end.valueOf() && isValidDate(addMs(slicedRange.end, -1), tDateProfile, dateProfile, timeAxis.view) + }); + } + } + return segs; + }; + return TimelineLaneSlicer; +}(Slicer)); + +var TimelineView = /** @class */ (function (_super) { + __extends(TimelineView, _super); + function TimelineView(context, viewSpec, dateProfileGenerator, parentEl) { + var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this; + _this.el.classList.add('fc-timeline'); + if (_this.opt('eventOverlap') === false) { + _this.el.classList.add('fc-no-overlap'); + } + _this.el.innerHTML = _this.renderSkeletonHtml(); + _this.timeAxis = new TimeAxis(_this.context, _this.el.querySelector('thead .fc-time-area'), _this.el.querySelector('tbody .fc-time-area')); + _this.lane = new TimelineLane(_this.context, _this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.contentEl, _this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.bgEl, _this.timeAxis); + context.calendar.registerInteractiveComponent(_this, { + el: _this.timeAxis.slats.el + }); + return _this; + } + TimelineView.prototype.destroy = function () { + this.timeAxis.destroy(); + this.lane.destroy(); + _super.prototype.destroy.call(this); + this.calendar.unregisterInteractiveComponent(this); + }; + TimelineView.prototype.renderSkeletonHtml = function () { + var theme = this.theme; + return "<table class=\"" + theme.getClass('tableGrid') + "\"> <thead class=\"fc-head\"> <tr> <td class=\"fc-time-area " + theme.getClass('widgetHeader') + "\"></td> </tr> </thead> <tbody class=\"fc-body\"> <tr> <td class=\"fc-time-area " + theme.getClass('widgetContent') + "\"></td> </tr> </tbody> </table>"; + }; + TimelineView.prototype.render = function (props) { + _super.prototype.render.call(this, props); // flags for updateSize, addScroll + this.timeAxis.receiveProps({ + dateProfile: props.dateProfile + }); + this.lane.receiveProps(__assign({}, props, { nextDayThreshold: this.nextDayThreshold })); + }; + TimelineView.prototype.updateSize = function (isResize, totalHeight, isAuto) { + this.timeAxis.updateSize(isResize, totalHeight, isAuto); + this.lane.updateSize(isResize); + }; + // Now Indicator + // ------------------------------------------------------------------------------------------ + TimelineView.prototype.getNowIndicatorUnit = function (dateProfile) { + return this.timeAxis.getNowIndicatorUnit(dateProfile); + }; + TimelineView.prototype.renderNowIndicator = function (date) { + this.timeAxis.renderNowIndicator(date); + }; + TimelineView.prototype.unrenderNowIndicator = function () { + this.timeAxis.unrenderNowIndicator(); + }; + // Scroll System + // ------------------------------------------------------------------------------------------ + TimelineView.prototype.computeDateScroll = function (duration) { + return this.timeAxis.computeDateScroll(duration); + }; + TimelineView.prototype.applyScroll = function (scroll, isResize) { + _super.prototype.applyScroll.call(this, scroll, isResize); // will call applyDateScroll + // avoid updating stickyscroll too often + // TODO: repeat code as ResourceTimelineView::updateSize + var calendar = this.calendar; + if (isResize || calendar.isViewUpdated || calendar.isDatesUpdated || calendar.isEventsUpdated) { + this.timeAxis.updateStickyScrollers(); + } + }; + TimelineView.prototype.applyDateScroll = function (scroll) { + this.timeAxis.applyDateScroll(scroll); + }; + TimelineView.prototype.queryScroll = function () { + var enhancedScroll = this.timeAxis.layout.bodyScroller.enhancedScroll; + return { + top: enhancedScroll.getScrollTop(), + left: enhancedScroll.getScrollLeft() + }; + }; + // Hit System + // ------------------------------------------------------------------------------------------ + TimelineView.prototype.buildPositionCaches = function () { + this.timeAxis.slats.updateSize(); + }; + TimelineView.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) { + var slatHit = this.timeAxis.slats.positionToHit(positionLeft); + if (slatHit) { + return { + component: this, + dateSpan: slatHit.dateSpan, + rect: { + left: slatHit.left, + right: slatHit.right, + top: 0, + bottom: elHeight + }, + dayEl: slatHit.dayEl, + layer: 0 + }; + } + }; + return TimelineView; +}(View)); + +var main = createPlugin({ + defaultView: 'timelineDay', + views: { + timeline: { + class: TimelineView, + eventResizableFromStart: true // how is this consumed for TimelineView tho? + }, + timelineDay: { + type: 'timeline', + duration: { days: 1 } + }, + timelineWeek: { + type: 'timeline', + duration: { weeks: 1 } + }, + timelineMonth: { + type: 'timeline', + duration: { months: 1 } + }, + timelineYear: { + type: 'timeline', + duration: { years: 1 } + } + } +}); + +export default main; +export { HeaderBodyLayout, ScrollJoiner, StickyScroller, TimeAxis, TimelineLane, TimelineView }; diff --git a/AKPlan/static/AKPlan/fullcalendar/timeline/main.js b/AKPlan/static/AKPlan/fullcalendar/timeline/main.js new file mode 100644 index 00000000..f349419b --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/timeline/main.js @@ -0,0 +1,1996 @@ +/*! +FullCalendar Timeline Plugin v4.3.0 +Docs & License: https://fullcalendar.io/scheduler +(c) 2019 Adam Shaw +*/ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) : + typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) : + (global = global || self, factory(global.FullCalendarTimeline = {}, global.FullCalendar)); +}(this, function (exports, core) { 'use strict'; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + /* + A rectangular area of content that lives within a Scroller. + Can have "gutters", areas of dead spacing around the perimeter. + Also very useful for forcing a width, which a Scroller cannot do alone. + Has a content area that lives above a background area. + */ + var ScrollerCanvas = /** @class */ (function () { + function ScrollerCanvas() { + this.gutters = {}; + this.el = core.htmlToElement("<div class=\"fc-scroller-canvas\"> <div class=\"fc-content\"></div> <div class=\"fc-bg\"></div> </div>"); + this.contentEl = this.el.querySelector('.fc-content'); + this.bgEl = this.el.querySelector('.fc-bg'); + } + /* + If falsy, resets all the gutters to 0 + */ + ScrollerCanvas.prototype.setGutters = function (gutters) { + if (!gutters) { + this.gutters = {}; + } + else { + __assign(this.gutters, gutters); + } + this.updateSize(); + }; + ScrollerCanvas.prototype.setWidth = function (width) { + this.width = width; + this.updateSize(); + }; + ScrollerCanvas.prototype.setMinWidth = function (minWidth) { + this.minWidth = minWidth; + this.updateSize(); + }; + ScrollerCanvas.prototype.clearWidth = function () { + this.width = null; + this.minWidth = null; + this.updateSize(); + }; + ScrollerCanvas.prototype.updateSize = function () { + var _a = this, gutters = _a.gutters, el = _a.el; + // is border-box (width includes padding) + core.forceClassName(el, 'fc-gutter-left', gutters.left); + core.forceClassName(el, 'fc-gutter-right', gutters.right); + core.forceClassName(el, 'fc-gutter-top', gutters.top); + core.forceClassName(el, 'fc-gutter-bottom', gutters.bottom); + core.applyStyle(el, { + paddingLeft: gutters.left || '', + paddingRight: gutters.right || '', + paddingTop: gutters.top || '', + paddingBottom: gutters.bottom || '', + width: (this.width != null) ? + this.width + (gutters.left || 0) + (gutters.right || 0) : + '', + minWidth: (this.minWidth != null) ? + this.minWidth + (gutters.left || 0) + (gutters.right || 0) : + '' + }); + core.applyStyle(this.bgEl, { + left: gutters.left || '', + right: gutters.right || '', + top: gutters.top || '', + bottom: gutters.bottom || '' + }); + }; + return ScrollerCanvas; + }()); + + var EnhancedScroller = /** @class */ (function (_super) { + __extends(EnhancedScroller, _super); + function EnhancedScroller(overflowX, overflowY) { + var _this = _super.call(this, overflowX, overflowY) || this; + // Scroll Events + // ---------------------------------------------------------------------------------------------- + _this.reportScroll = function () { + if (!_this.isScrolling) { + _this.reportScrollStart(); + } + _this.trigger('scroll'); + _this.isMoving = true; + _this.requestMovingEnd(); + }; + _this.reportScrollStart = function () { + if (!_this.isScrolling) { + _this.isScrolling = true; + _this.trigger('scrollStart', _this.isTouching); // created in constructor + } + }; + // Touch Events + // ---------------------------------------------------------------------------------------------- + // will fire *before* the scroll event is fired + _this.reportTouchStart = function () { + _this.isTouching = true; + }; + _this.reportTouchEnd = function () { + if (_this.isTouching) { + _this.isTouching = false; + // if touch scrolling was re-enabled during a recent touch scroll + // then unbind the handlers that are preventing it from happening. + if (_this.isTouchScrollEnabled) { + _this.unbindPreventTouchScroll(); // won't do anything if not bound + } + // if the user ended their touch, and the scroll area wasn't moving, + // we consider this to be the end of the scroll. + if (!_this.isMoving) { + _this.reportScrollEnd(); // won't fire if already ended + } + } + }; + _this.isScrolling = false; + _this.isTouching = false; + _this.isMoving = false; + _this.isTouchScrollEnabled = true; + _this.requestMovingEnd = core.debounce(_this.reportMovingEnd, 500); + _this.canvas = new ScrollerCanvas(); + _this.el.appendChild(_this.canvas.el); + _this.applyOverflow(); + _this.bindHandlers(); + return _this; + } + EnhancedScroller.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.unbindHandlers(); + }; + // Touch scroll prevention + // ---------------------------------------------------------------------------------------------- + EnhancedScroller.prototype.disableTouchScroll = function () { + this.isTouchScrollEnabled = false; + this.bindPreventTouchScroll(); // will be unbound in enableTouchScroll or reportTouchEnd + }; + EnhancedScroller.prototype.enableTouchScroll = function () { + this.isTouchScrollEnabled = true; + // only immediately unbind if a touch event is NOT in progress. + // otherwise, it will be handled by reportTouchEnd. + if (!this.isTouching) { + this.unbindPreventTouchScroll(); + } + }; + EnhancedScroller.prototype.bindPreventTouchScroll = function () { + if (!this.preventTouchScrollHandler) { + this.el.addEventListener('touchmove', (this.preventTouchScrollHandler = core.preventDefault)); + } + }; + EnhancedScroller.prototype.unbindPreventTouchScroll = function () { + if (this.preventTouchScrollHandler) { + this.el.removeEventListener('touchmove', this.preventTouchScrollHandler); + this.preventTouchScrollHandler = null; + } + }; + // Handlers + // ---------------------------------------------------------------------------------------------- + EnhancedScroller.prototype.bindHandlers = function () { + this.el.addEventListener('scroll', this.reportScroll); + this.el.addEventListener('touchstart', this.reportTouchStart, { passive: true }); + this.el.addEventListener('touchend', this.reportTouchEnd); + }; + EnhancedScroller.prototype.unbindHandlers = function () { + this.el.removeEventListener('scroll', this.reportScroll); + this.el.removeEventListener('touchstart', this.reportTouchStart, { passive: true }); + this.el.removeEventListener('touchend', this.reportTouchEnd); + }; + EnhancedScroller.prototype.reportMovingEnd = function () { + this.isMoving = false; + // only end the scroll if not currently touching. + // if touching, the scrolling will end later, on touchend. + if (!this.isTouching) { + this.reportScrollEnd(); + } + }; + EnhancedScroller.prototype.reportScrollEnd = function () { + if (this.isScrolling) { + this.trigger('scrollEnd'); + this.isScrolling = false; + } + }; + // Horizontal Scroll Normalization + // ---------------------------------------------------------------------------------------------- + // http://stackoverflow.com/questions/24276619/better-way-to-get-the-viewport-of-a-scrollable-div-in-rtl-mode/24394376#24394376 + // TODO: move all this to util functions + /* + If RTL, and scrolled to the left, returns NEGATIVE value (like Firefox) + */ + EnhancedScroller.prototype.getScrollLeft = function () { + var el = this.el; + var direction = window.getComputedStyle(el).direction; + var val = el.scrollLeft; + if (direction === 'rtl') { + switch (getRtlScrollSystem()) { + case 'positive': + val = (val + el.clientWidth) - el.scrollWidth; + break; + case 'reverse': + val = -val; + break; + } + } + return val; + }; + /* + Accepts a NEGATIVE value for when scrolled in RTL + */ + EnhancedScroller.prototype.setScrollLeft = function (val) { + var el = this.el; + var direction = window.getComputedStyle(el).direction; + if (direction === 'rtl') { + switch (getRtlScrollSystem()) { + case 'positive': + val = (val - el.clientWidth) + el.scrollWidth; + break; + case 'reverse': + val = -val; + break; + } + } + el.scrollLeft = val; + }; + /* + Always returns the number of pixels scrolled from the leftmost position (even if RTL). + Always positive. + */ + EnhancedScroller.prototype.getScrollFromLeft = function () { + var el = this.el; + var direction = window.getComputedStyle(el).direction; + var val = el.scrollLeft; + if (direction === 'rtl') { + switch (getRtlScrollSystem()) { + case 'negative': + val = (val - el.clientWidth) + el.scrollWidth; + break; + case 'reverse': + val = (-val - el.clientWidth) + el.scrollWidth; + break; + } + } + return val; + }; + return EnhancedScroller; + }(core.ScrollComponent)); + core.EmitterMixin.mixInto(EnhancedScroller); + // Horizontal Scroll System Detection + // ---------------------------------------------------------------------------------------------- + var _rtlScrollSystem; + function getRtlScrollSystem() { + return _rtlScrollSystem || (_rtlScrollSystem = detectRtlScrollSystem()); + } + function detectRtlScrollSystem() { + var el = core.htmlToElement("<div style=\" position: absolute; top: -1000px; width: 1px; height: 1px; overflow: scroll; direction: rtl; font-size: 100px; \">A</div>"); + document.body.appendChild(el); + var system; + if (el.scrollLeft > 0) { + system = 'positive'; + } + else { + el.scrollLeft = 1; + if (el.scrollLeft > 0) { + system = 'reverse'; + } + else { + system = 'negative'; + } + } + core.removeElement(el); + return system; + } + + /* + A Scroller, but with a wrapping div that allows "clipping" away of native scrollbars, + giving the appearance that there are no scrollbars. + */ + var ClippedScroller = /** @class */ (function () { + /* + Received overflows can be set to 'clipped', meaning scrollbars shouldn't be visible + to the user, but the area should still scroll. + */ + function ClippedScroller(overflowX, overflowY, parentEl) { + this.isHScrollbarsClipped = false; + this.isVScrollbarsClipped = false; + if (overflowX === 'clipped-scroll') { + overflowX = 'scroll'; + this.isHScrollbarsClipped = true; + } + if (overflowY === 'clipped-scroll') { + overflowY = 'scroll'; + this.isVScrollbarsClipped = true; + } + this.enhancedScroll = new EnhancedScroller(overflowX, overflowY); + parentEl.appendChild(this.el = core.createElement('div', { + className: 'fc-scroller-clip' + })); + this.el.appendChild(this.enhancedScroll.el); + } + ClippedScroller.prototype.destroy = function () { + core.removeElement(this.el); + }; + ClippedScroller.prototype.updateSize = function () { + var enhancedScroll = this.enhancedScroll; + var scrollEl = enhancedScroll.el; + var edges = core.computeEdges(scrollEl); + var cssProps = { marginLeft: 0, marginRight: 0, marginTop: 0, marginBottom: 0 }; + // give the inner scrolling div negative margins so that its scrollbars + // are nudged outside of the bounding box of the wrapper, which is overflow:hidden + if (this.isVScrollbarsClipped) { + cssProps.marginLeft = -edges.scrollbarLeft; + cssProps.marginRight = -edges.scrollbarRight; + } + if (this.isHScrollbarsClipped) { + cssProps.marginBottom = -edges.scrollbarBottom; + } + core.applyStyle(scrollEl, cssProps); + // if we are attempting to hide the scrollbars offscreen, OSX/iOS will still + // display the floating scrollbars. attach a className to force-hide them. + if ((this.isHScrollbarsClipped || (enhancedScroll.overflowX === 'hidden')) && // should never show? + (this.isVScrollbarsClipped || (enhancedScroll.overflowY === 'hidden')) && // should never show? + !( // doesn't have any scrollbar mass + edges.scrollbarLeft || + edges.scrollbarRight || + edges.scrollbarBottom)) { + scrollEl.classList.add('fc-no-scrollbars'); + } + else { + scrollEl.classList.remove('fc-no-scrollbars'); + } + }; + ClippedScroller.prototype.setHeight = function (height) { + this.enhancedScroll.setHeight(height); + }; + /* + Accounts for 'clipped' scrollbars + */ + ClippedScroller.prototype.getScrollbarWidths = function () { + var widths = this.enhancedScroll.getScrollbarWidths(); + if (this.isVScrollbarsClipped) { + widths.left = 0; + widths.right = 0; + } + if (this.isHScrollbarsClipped) { + widths.bottom = 0; + } + return widths; + }; + return ClippedScroller; + }()); + + var ScrollJoiner = /** @class */ (function () { + function ScrollJoiner(axis, scrollers) { + this.axis = axis; + this.scrollers = scrollers; + for (var _i = 0, _a = this.scrollers; _i < _a.length; _i++) { + var scroller = _a[_i]; + this.initScroller(scroller); + } + } + ScrollJoiner.prototype.initScroller = function (scroller) { + var _this = this; + var enhancedScroll = scroller.enhancedScroll; + // when the user scrolls via mousewheel, we know for sure the target + // scroller should be the master. capture the various x-browser events that fire. + var onScroll = function () { + _this.assignMasterScroller(scroller); + }; + 'wheel mousewheel DomMouseScroll MozMousePixelScroll'.split(' ').forEach(function (evName) { + enhancedScroll.el.addEventListener(evName, onScroll); + }); + enhancedScroll + .on('scrollStart', function () { + if (!_this.masterScroller) { + _this.assignMasterScroller(scroller); + } + }) + .on('scroll', function () { + if (scroller === _this.masterScroller) { + for (var _i = 0, _a = _this.scrollers; _i < _a.length; _i++) { + var otherScroller = _a[_i]; + if (otherScroller !== scroller) { + switch (_this.axis) { + case 'horizontal': + otherScroller.enhancedScroll.el.scrollLeft = enhancedScroll.el.scrollLeft; + break; + case 'vertical': + otherScroller.enhancedScroll.setScrollTop(enhancedScroll.getScrollTop()); + break; + } + } + } + } + }) + .on('scrollEnd', function () { + if (scroller === _this.masterScroller) { + _this.unassignMasterScroller(); + } + }); + }; + ScrollJoiner.prototype.assignMasterScroller = function (scroller) { + this.unassignMasterScroller(); + this.masterScroller = scroller; + for (var _i = 0, _a = this.scrollers; _i < _a.length; _i++) { + var otherScroller = _a[_i]; + if (otherScroller !== scroller) { + otherScroller.enhancedScroll.disableTouchScroll(); + } + } + }; + ScrollJoiner.prototype.unassignMasterScroller = function () { + if (this.masterScroller) { + for (var _i = 0, _a = this.scrollers; _i < _a.length; _i++) { + var otherScroller = _a[_i]; + otherScroller.enhancedScroll.enableTouchScroll(); + } + this.masterScroller = null; + } + }; + ScrollJoiner.prototype.update = function () { + var allWidths = this.scrollers.map(function (scroller) { return scroller.getScrollbarWidths(); }); + var maxLeft = 0; + var maxRight = 0; + var maxTop = 0; + var maxBottom = 0; + var widths; + var i; + for (var _i = 0, allWidths_1 = allWidths; _i < allWidths_1.length; _i++) { + widths = allWidths_1[_i]; + maxLeft = Math.max(maxLeft, widths.left); + maxRight = Math.max(maxRight, widths.right); + maxTop = Math.max(maxTop, widths.top); + maxBottom = Math.max(maxBottom, widths.bottom); + } + for (i = 0; i < this.scrollers.length; i++) { + var scroller = this.scrollers[i]; + widths = allWidths[i]; + scroller.enhancedScroll.canvas.setGutters(this.axis === 'horizontal' ? + { + left: maxLeft - widths.left, + right: maxRight - widths.right + } : + { + top: maxTop - widths.top, + bottom: maxBottom - widths.bottom + }); + } + }; + return ScrollJoiner; + }()); + + var HeaderBodyLayout = /** @class */ (function () { + /* + verticalScroll = 'auto' | 'clipped-scroll' + */ + function HeaderBodyLayout(headerContainerEl, bodyContainerEl, verticalScroll) { + this.headerScroller = new ClippedScroller('clipped-scroll', 'hidden', headerContainerEl); + this.bodyScroller = new ClippedScroller('auto', verticalScroll, bodyContainerEl); + this.scrollJoiner = new ScrollJoiner('horizontal', [ + this.headerScroller, + this.bodyScroller + ]); + } + HeaderBodyLayout.prototype.destroy = function () { + this.headerScroller.destroy(); + this.bodyScroller.destroy(); + }; + HeaderBodyLayout.prototype.setHeight = function (totalHeight, isAuto) { + var bodyHeight; + if (isAuto) { + bodyHeight = 'auto'; + } + else { + bodyHeight = totalHeight - this.queryHeadHeight(); + } + this.bodyScroller.setHeight(bodyHeight); + this.headerScroller.updateSize(); // adjusts gutters and classNames + this.bodyScroller.updateSize(); // adjusts gutters and classNames + this.scrollJoiner.update(); + }; + HeaderBodyLayout.prototype.queryHeadHeight = function () { + return this.headerScroller.enhancedScroll.canvas.contentEl.getBoundingClientRect().height; + }; + return HeaderBodyLayout; + }()); + + var TimelineHeader = /** @class */ (function (_super) { + __extends(TimelineHeader, _super); + function TimelineHeader(context, parentEl) { + var _this = _super.call(this, context) || this; + parentEl.appendChild(_this.tableEl = core.createElement('table', { + className: _this.theme.getClass('tableGrid') + })); + return _this; + } + TimelineHeader.prototype.destroy = function () { + core.removeElement(this.tableEl); + _super.prototype.destroy.call(this); + }; + TimelineHeader.prototype.render = function (props) { + this.renderDates(props.tDateProfile); + }; + TimelineHeader.prototype.renderDates = function (tDateProfile) { + var _a = this, dateEnv = _a.dateEnv, theme = _a.theme; + var cellRows = tDateProfile.cellRows; + var lastRow = cellRows[cellRows.length - 1]; + var isChrono = core.asRoughMs(tDateProfile.labelInterval) > core.asRoughMs(tDateProfile.slotDuration); + var oneDay = core.isSingleDay(tDateProfile.slotDuration); + var html = '<colgroup>'; + // needs to be a col for each body slat. header cells will have colspans + for (var i = tDateProfile.slotCnt - 1; i >= 0; i--) { + html += '<col/>'; + } + html += '</colgroup>'; + html += '<tbody>'; + for (var _i = 0, cellRows_1 = cellRows; _i < cellRows_1.length; _i++) { + var rowCells = cellRows_1[_i]; + var isLast = rowCells === lastRow; + html += '<tr' + (isChrono && isLast ? ' class="fc-chrono"' : '') + '>'; + for (var _b = 0, rowCells_1 = rowCells; _b < rowCells_1.length; _b++) { + var cell = rowCells_1[_b]; + var headerCellClassNames = [theme.getClass('widgetHeader')]; + if (cell.isWeekStart) { + headerCellClassNames.push('fc-em-cell'); + } + if (oneDay) { + headerCellClassNames = headerCellClassNames.concat(core.getDayClasses(cell.date, this.props.dateProfile, this.context, true) // adds "today" class and other day-based classes + ); + } + html += + '<th class="' + headerCellClassNames.join(' ') + '"' + + ' data-date="' + dateEnv.formatIso(cell.date, { omitTime: !tDateProfile.isTimeScale, omitTimeZoneOffset: true }) + '"' + + (cell.colspan > 1 ? ' colspan="' + cell.colspan + '"' : '') + + '>' + + '<div class="fc-cell-content">' + + cell.spanHtml + + '</div>' + + '</th>'; + } + html += '</tr>'; + } + html += '</tbody>'; + this.tableEl.innerHTML = html; // TODO: does this work cross-browser? + this.slatColEls = core.findElements(this.tableEl, 'col'); + this.innerEls = core.findElements(this.tableEl.querySelector('tr:last-child'), // compound selector won't work because of query-root problem + 'th .fc-cell-text'); + core.findElements(this.tableEl.querySelectorAll('tr:not(:last-child)'), // compound selector won't work because of query-root problem + 'th .fc-cell-text').forEach(function (innerEl) { + innerEl.classList.add('fc-sticky'); + }); + }; + return TimelineHeader; + }(core.Component)); + + var TimelineSlats = /** @class */ (function (_super) { + __extends(TimelineSlats, _super); + function TimelineSlats(context, parentEl) { + var _this = _super.call(this, context) || this; + parentEl.appendChild(_this.el = core.createElement('div', { className: 'fc-slats' })); + return _this; + } + TimelineSlats.prototype.destroy = function () { + core.removeElement(this.el); + _super.prototype.destroy.call(this); + }; + TimelineSlats.prototype.render = function (props) { + this.renderDates(props.tDateProfile); + }; + TimelineSlats.prototype.renderDates = function (tDateProfile) { + var _a = this, theme = _a.theme, view = _a.view, dateEnv = _a.dateEnv; + var slotDates = tDateProfile.slotDates, isWeekStarts = tDateProfile.isWeekStarts; + var html = '<table class="' + theme.getClass('tableGrid') + '">' + + '<colgroup>'; + for (var i = 0; i < slotDates.length; i++) { + html += '<col/>'; + } + html += '</colgroup>'; + html += '<tbody><tr>'; + for (var i = 0; i < slotDates.length; i++) { + html += this.slatCellHtml(slotDates[i], isWeekStarts[i], tDateProfile); + } + html += '</tr></tbody></table>'; + this.el.innerHTML = html; + this.slatColEls = core.findElements(this.el, 'col'); + this.slatEls = core.findElements(this.el, 'td'); + for (var i = 0; i < slotDates.length; i++) { + view.publiclyTrigger('dayRender', [ + { + date: dateEnv.toDate(slotDates[i]), + el: this.slatEls[i], + view: view + } + ]); + } + this.outerCoordCache = new core.PositionCache(this.el, this.slatEls, true, // isHorizontal + false // isVertical + ); + // for the inner divs within the slats + // used for event rendering and scrollTime, to disregard slat border + this.innerCoordCache = new core.PositionCache(this.el, core.findChildren(this.slatEls, 'div'), true, // isHorizontal + false // isVertical + ); + }; + TimelineSlats.prototype.slatCellHtml = function (date, isEm, tDateProfile) { + var _a = this, theme = _a.theme, dateEnv = _a.dateEnv; + var classes; + if (tDateProfile.isTimeScale) { + classes = []; + classes.push(core.isInt(dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.labelInterval)) ? + 'fc-major' : + 'fc-minor'); + } + else { + classes = core.getDayClasses(date, this.props.dateProfile, this.context); + classes.push('fc-day'); + } + classes.unshift(theme.getClass('widgetContent')); + if (isEm) { + classes.push('fc-em-cell'); + } + return '<td class="' + classes.join(' ') + '"' + + ' data-date="' + dateEnv.formatIso(date, { omitTime: !tDateProfile.isTimeScale, omitTimeZoneOffset: true }) + '"' + + '><div></div></td>'; + }; + TimelineSlats.prototype.updateSize = function () { + this.outerCoordCache.build(); + this.innerCoordCache.build(); + }; + TimelineSlats.prototype.positionToHit = function (leftPosition) { + var outerCoordCache = this.outerCoordCache; + var tDateProfile = this.props.tDateProfile; + var slatIndex = outerCoordCache.leftToIndex(leftPosition); + if (slatIndex != null) { + // somewhat similar to what TimeGrid does. consolidate? + var slatWidth = outerCoordCache.getWidth(slatIndex); + var partial = this.isRtl ? + (outerCoordCache.rights[slatIndex] - leftPosition) / slatWidth : + (leftPosition - outerCoordCache.lefts[slatIndex]) / slatWidth; + var localSnapIndex = Math.floor(partial * tDateProfile.snapsPerSlot); + var start = this.dateEnv.add(tDateProfile.slotDates[slatIndex], core.multiplyDuration(tDateProfile.snapDuration, localSnapIndex)); + var end = this.dateEnv.add(start, tDateProfile.snapDuration); + return { + dateSpan: { + range: { start: start, end: end }, + allDay: !this.props.tDateProfile.isTimeScale + }, + dayEl: this.slatColEls[slatIndex], + left: outerCoordCache.lefts[slatIndex], + right: outerCoordCache.rights[slatIndex] + }; + } + return null; + }; + return TimelineSlats; + }(core.Component)); + + var MIN_AUTO_LABELS = 18; // more than `12` months but less that `24` hours + var MAX_AUTO_SLOTS_PER_LABEL = 6; // allows 6 10-min slots in an hour + var MAX_AUTO_CELLS = 200; // allows 4-days to have a :30 slot duration + core.config.MAX_TIMELINE_SLOTS = 1000; + // potential nice values for slot-duration and interval-duration + var STOCK_SUB_DURATIONS = [ + { years: 1 }, + { months: 1 }, + { days: 1 }, + { hours: 1 }, + { minutes: 30 }, + { minutes: 15 }, + { minutes: 10 }, + { minutes: 5 }, + { minutes: 1 }, + { seconds: 30 }, + { seconds: 15 }, + { seconds: 10 }, + { seconds: 5 }, + { seconds: 1 }, + { milliseconds: 500 }, + { milliseconds: 100 }, + { milliseconds: 10 }, + { milliseconds: 1 } + ]; + function buildTimelineDateProfile(dateProfile, view) { + var dateEnv = view.dateEnv; + var tDateProfile = { + labelInterval: queryDurationOption(view, 'slotLabelInterval'), + slotDuration: queryDurationOption(view, 'slotDuration') + }; + validateLabelAndSlot(tDateProfile, dateProfile, dateEnv); // validate after computed grid duration + ensureLabelInterval(tDateProfile, dateProfile, dateEnv); + ensureSlotDuration(tDateProfile, dateProfile, dateEnv); + var input = view.opt('slotLabelFormat'); + var rawFormats = Array.isArray(input) ? + input + : (input != null) ? + [input] + : + computeHeaderFormats(tDateProfile, dateProfile, dateEnv, view); + tDateProfile.headerFormats = rawFormats.map(function (rawFormat) { + return core.createFormatter(rawFormat); + }); + tDateProfile.isTimeScale = Boolean(tDateProfile.slotDuration.milliseconds); + var largeUnit = null; + if (!tDateProfile.isTimeScale) { + var slotUnit = core.greatestDurationDenominator(tDateProfile.slotDuration).unit; + if (/year|month|week/.test(slotUnit)) { + largeUnit = slotUnit; + } + } + tDateProfile.largeUnit = largeUnit; + tDateProfile.emphasizeWeeks = + core.isSingleDay(tDateProfile.slotDuration) && + currentRangeAs('weeks', dateProfile, dateEnv) >= 2 && + !view.opt('businessHours'); + /* + console.log('label interval =', timelineView.labelInterval.humanize()) + console.log('slot duration =', timelineView.slotDuration.humanize()) + console.log('header formats =', timelineView.headerFormats) + console.log('isTimeScale', timelineView.isTimeScale) + console.log('largeUnit', timelineView.largeUnit) + */ + var rawSnapDuration = view.opt('snapDuration'); + var snapDuration; + var snapsPerSlot; + if (rawSnapDuration) { + snapDuration = core.createDuration(rawSnapDuration); + snapsPerSlot = core.wholeDivideDurations(tDateProfile.slotDuration, snapDuration); + // ^ TODO: warning if not whole? + } + if (snapsPerSlot == null) { + snapDuration = tDateProfile.slotDuration; + snapsPerSlot = 1; + } + tDateProfile.snapDuration = snapDuration; + tDateProfile.snapsPerSlot = snapsPerSlot; + // more... + var timeWindowMs = core.asRoughMs(dateProfile.maxTime) - core.asRoughMs(dateProfile.minTime); + // TODO: why not use normalizeRange!? + var normalizedStart = normalizeDate(dateProfile.renderRange.start, tDateProfile, dateEnv); + var normalizedEnd = normalizeDate(dateProfile.renderRange.end, tDateProfile, dateEnv); + // apply minTime/maxTime + // TODO: View should be responsible. + if (tDateProfile.isTimeScale) { + normalizedStart = dateEnv.add(normalizedStart, dateProfile.minTime); + normalizedEnd = dateEnv.add(core.addDays(normalizedEnd, -1), dateProfile.maxTime); + } + tDateProfile.timeWindowMs = timeWindowMs; + tDateProfile.normalizedRange = { start: normalizedStart, end: normalizedEnd }; + var slotDates = []; + var date = normalizedStart; + while (date < normalizedEnd) { + if (isValidDate(date, tDateProfile, dateProfile, view)) { + slotDates.push(date); + } + date = dateEnv.add(date, tDateProfile.slotDuration); + } + tDateProfile.slotDates = slotDates; + // more... + var snapIndex = -1; + var snapDiff = 0; // index of the diff :( + var snapDiffToIndex = []; + var snapIndexToDiff = []; + date = normalizedStart; + while (date < normalizedEnd) { + if (isValidDate(date, tDateProfile, dateProfile, view)) { + snapIndex++; + snapDiffToIndex.push(snapIndex); + snapIndexToDiff.push(snapDiff); + } + else { + snapDiffToIndex.push(snapIndex + 0.5); + } + date = dateEnv.add(date, tDateProfile.snapDuration); + snapDiff++; + } + tDateProfile.snapDiffToIndex = snapDiffToIndex; + tDateProfile.snapIndexToDiff = snapIndexToDiff; + tDateProfile.snapCnt = snapIndex + 1; // is always one behind + tDateProfile.slotCnt = tDateProfile.snapCnt / tDateProfile.snapsPerSlot; + // more... + tDateProfile.isWeekStarts = buildIsWeekStarts(tDateProfile, dateEnv); + tDateProfile.cellRows = buildCellRows(tDateProfile, dateEnv, view); + return tDateProfile; + } + /* + snaps to appropriate unit + */ + function normalizeDate(date, tDateProfile, dateEnv) { + var normalDate = date; + if (!tDateProfile.isTimeScale) { + normalDate = core.startOfDay(normalDate); + if (tDateProfile.largeUnit) { + normalDate = dateEnv.startOf(normalDate, tDateProfile.largeUnit); + } + } + return normalDate; + } + /* + snaps to appropriate unit + */ + function normalizeRange(range, tDateProfile, dateEnv) { + if (!tDateProfile.isTimeScale) { + range = core.computeVisibleDayRange(range); + if (tDateProfile.largeUnit) { + var dayRange = range; // preserve original result + range = { + start: dateEnv.startOf(range.start, tDateProfile.largeUnit), + end: dateEnv.startOf(range.end, tDateProfile.largeUnit) + }; + // if date is partially through the interval, or is in the same interval as the start, + // make the exclusive end be the *next* interval + if (range.end.valueOf() !== dayRange.end.valueOf() || range.end <= range.start) { + range = { + start: range.start, + end: dateEnv.add(range.end, tDateProfile.slotDuration) + }; + } + } + } + return range; + } + function isValidDate(date, tDateProfile, dateProfile, view) { + if (view.dateProfileGenerator.isHiddenDay(date)) { + return false; + } + else if (tDateProfile.isTimeScale) { + // determine if the time is within minTime/maxTime, which may have wacky values + var day = core.startOfDay(date); + var timeMs = date.valueOf() - day.valueOf(); + var ms = timeMs - core.asRoughMs(dateProfile.minTime); // milliseconds since minTime + ms = ((ms % 86400000) + 86400000) % 86400000; // make negative values wrap to 24hr clock + return ms < tDateProfile.timeWindowMs; // before the maxTime? + } + else { + return true; + } + } + function queryDurationOption(view, name) { + var input = view.opt(name); + if (input != null) { + return core.createDuration(input); + } + } + function validateLabelAndSlot(tDateProfile, dateProfile, dateEnv) { + var currentRange = dateProfile.currentRange; + // make sure labelInterval doesn't exceed the max number of cells + if (tDateProfile.labelInterval) { + var labelCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, tDateProfile.labelInterval); + if (labelCnt > core.config.MAX_TIMELINE_SLOTS) { + console.warn('slotLabelInterval results in too many cells'); + tDateProfile.labelInterval = null; + } + } + // make sure slotDuration doesn't exceed the maximum number of cells + if (tDateProfile.slotDuration) { + var slotCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, tDateProfile.slotDuration); + if (slotCnt > core.config.MAX_TIMELINE_SLOTS) { + console.warn('slotDuration results in too many cells'); + tDateProfile.slotDuration = null; + } + } + // make sure labelInterval is a multiple of slotDuration + if (tDateProfile.labelInterval && tDateProfile.slotDuration) { + var slotsPerLabel = core.wholeDivideDurations(tDateProfile.labelInterval, tDateProfile.slotDuration); + if (slotsPerLabel === null || slotsPerLabel < 1) { + console.warn('slotLabelInterval must be a multiple of slotDuration'); + tDateProfile.slotDuration = null; + } + } + } + function ensureLabelInterval(tDateProfile, dateProfile, dateEnv) { + var currentRange = dateProfile.currentRange; + var labelInterval = tDateProfile.labelInterval; + if (!labelInterval) { + // compute based off the slot duration + // find the largest label interval with an acceptable slots-per-label + var input = void 0; + if (tDateProfile.slotDuration) { + for (var _i = 0, STOCK_SUB_DURATIONS_1 = STOCK_SUB_DURATIONS; _i < STOCK_SUB_DURATIONS_1.length; _i++) { + input = STOCK_SUB_DURATIONS_1[_i]; + var tryLabelInterval = core.createDuration(input); + var slotsPerLabel = core.wholeDivideDurations(tryLabelInterval, tDateProfile.slotDuration); + if (slotsPerLabel !== null && slotsPerLabel <= MAX_AUTO_SLOTS_PER_LABEL) { + labelInterval = tryLabelInterval; + break; + } + } + // use the slot duration as a last resort + if (!labelInterval) { + labelInterval = tDateProfile.slotDuration; + } + // compute based off the view's duration + // find the largest label interval that yields the minimum number of labels + } + else { + for (var _a = 0, STOCK_SUB_DURATIONS_2 = STOCK_SUB_DURATIONS; _a < STOCK_SUB_DURATIONS_2.length; _a++) { + input = STOCK_SUB_DURATIONS_2[_a]; + labelInterval = core.createDuration(input); + var labelCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, labelInterval); + if (labelCnt >= MIN_AUTO_LABELS) { + break; + } + } + } + tDateProfile.labelInterval = labelInterval; + } + return labelInterval; + } + function ensureSlotDuration(tDateProfile, dateProfile, dateEnv) { + var currentRange = dateProfile.currentRange; + var slotDuration = tDateProfile.slotDuration; + if (!slotDuration) { + var labelInterval = ensureLabelInterval(tDateProfile, dateProfile, dateEnv); // will compute if necessary + // compute based off the label interval + // find the largest slot duration that is different from labelInterval, but still acceptable + for (var _i = 0, STOCK_SUB_DURATIONS_3 = STOCK_SUB_DURATIONS; _i < STOCK_SUB_DURATIONS_3.length; _i++) { + var input = STOCK_SUB_DURATIONS_3[_i]; + var trySlotDuration = core.createDuration(input); + var slotsPerLabel = core.wholeDivideDurations(labelInterval, trySlotDuration); + if (slotsPerLabel !== null && slotsPerLabel > 1 && slotsPerLabel <= MAX_AUTO_SLOTS_PER_LABEL) { + slotDuration = trySlotDuration; + break; + } + } + // only allow the value if it won't exceed the view's # of slots limit + if (slotDuration) { + var slotCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, slotDuration); + if (slotCnt > MAX_AUTO_CELLS) { + slotDuration = null; + } + } + // use the label interval as a last resort + if (!slotDuration) { + slotDuration = labelInterval; + } + tDateProfile.slotDuration = slotDuration; + } + return slotDuration; + } + function computeHeaderFormats(tDateProfile, dateProfile, dateEnv, view) { + var format1; + var format2; + var labelInterval = tDateProfile.labelInterval; + var unit = core.greatestDurationDenominator(labelInterval).unit; + var weekNumbersVisible = view.opt('weekNumbers'); + var format0 = (format1 = (format2 = null)); + // NOTE: weekNumber computation function wont work + if ((unit === 'week') && !weekNumbersVisible) { + unit = 'day'; + } + switch (unit) { + case 'year': + format0 = { year: 'numeric' }; // '2015' + break; + case 'month': + if (currentRangeAs('years', dateProfile, dateEnv) > 1) { + format0 = { year: 'numeric' }; // '2015' + } + format1 = { month: 'short' }; // 'Jan' + break; + case 'week': + if (currentRangeAs('years', dateProfile, dateEnv) > 1) { + format0 = { year: 'numeric' }; // '2015' + } + format1 = { week: 'narrow' }; // 'Wk4' + break; + case 'day': + if (currentRangeAs('years', dateProfile, dateEnv) > 1) { + format0 = { year: 'numeric', month: 'long' }; // 'January 2014' + } + else if (currentRangeAs('months', dateProfile, dateEnv) > 1) { + format0 = { month: 'long' }; // 'January' + } + if (weekNumbersVisible) { + format1 = { week: 'short' }; // 'Wk 4' + } + format2 = { weekday: 'narrow', day: 'numeric' }; // 'Su 9' + break; + case 'hour': + if (weekNumbersVisible) { + format0 = { week: 'short' }; // 'Wk 4' + } + if (currentRangeAs('days', dateProfile, dateEnv) > 1) { + format1 = { weekday: 'short', day: 'numeric', month: 'numeric', omitCommas: true }; // Sat 4/7 + } + format2 = { + hour: 'numeric', + minute: '2-digit', + omitZeroMinute: true, + meridiem: 'short' + }; + break; + case 'minute': + // sufficiently large number of different minute cells? + if ((core.asRoughMinutes(labelInterval) / 60) >= MAX_AUTO_SLOTS_PER_LABEL) { + format0 = { + hour: 'numeric', + meridiem: 'short' + }; + format1 = function (params) { + return ':' + core.padStart(params.date.minute, 2); // ':30' + }; + } + else { + format0 = { + hour: 'numeric', + minute: 'numeric', + meridiem: 'short' + }; + } + break; + case 'second': + // sufficiently large number of different second cells? + if ((core.asRoughSeconds(labelInterval) / 60) >= MAX_AUTO_SLOTS_PER_LABEL) { + format0 = { hour: 'numeric', minute: '2-digit', meridiem: 'lowercase' }; // '8:30 PM' + format1 = function (params) { + return ':' + core.padStart(params.date.second, 2); // ':30' + }; + } + else { + format0 = { hour: 'numeric', minute: '2-digit', second: '2-digit', meridiem: 'lowercase' }; // '8:30:45 PM' + } + break; + case 'millisecond': + format0 = { hour: 'numeric', minute: '2-digit', second: '2-digit', meridiem: 'lowercase' }; // '8:30:45 PM' + format1 = function (params) { + return '.' + core.padStart(params.millisecond, 3); + }; + break; + } + return [].concat(format0 || [], format1 || [], format2 || []); + } + // Compute the number of the give units in the "current" range. + // Won't go more precise than days. + // Will return `0` if there's not a clean whole interval. + function currentRangeAs(unit, dateProfile, dateEnv) { + var range = dateProfile.currentRange; + var res = null; + if (unit === 'years') { + res = dateEnv.diffWholeYears(range.start, range.end); + } + else if (unit === 'months') { + res = dateEnv.diffWholeMonths(range.start, range.end); + } + else if (unit === 'weeks') { + res = dateEnv.diffWholeMonths(range.start, range.end); + } + else if (unit === 'days') { + res = core.diffWholeDays(range.start, range.end); + } + return res || 0; + } + function buildIsWeekStarts(tDateProfile, dateEnv) { + var slotDates = tDateProfile.slotDates, emphasizeWeeks = tDateProfile.emphasizeWeeks; + var prevWeekNumber = null; + var isWeekStarts = []; + for (var _i = 0, slotDates_1 = slotDates; _i < slotDates_1.length; _i++) { + var slotDate = slotDates_1[_i]; + var weekNumber = dateEnv.computeWeekNumber(slotDate); + var isWeekStart = emphasizeWeeks && (prevWeekNumber !== null) && (prevWeekNumber !== weekNumber); + prevWeekNumber = weekNumber; + isWeekStarts.push(isWeekStart); + } + return isWeekStarts; + } + function buildCellRows(tDateProfile, dateEnv, view) { + var slotDates = tDateProfile.slotDates; + var formats = tDateProfile.headerFormats; + var cellRows = formats.map(function (format) { return []; }); // indexed by row,col + // specifically for navclicks + var rowUnits = formats.map(function (format) { + return format.getLargestUnit ? format.getLargestUnit() : null; + }); + // builds cellRows and slotCells + for (var i = 0; i < slotDates.length; i++) { + var date = slotDates[i]; + var isWeekStart = tDateProfile.isWeekStarts[i]; + for (var row = 0; row < formats.length; row++) { + var format = formats[row]; + var rowCells = cellRows[row]; + var leadingCell = rowCells[rowCells.length - 1]; + var isSuperRow = (formats.length > 1) && (row < (formats.length - 1)); // more than one row and not the last + var newCell = null; + if (isSuperRow) { + var text = dateEnv.format(date, format); + if (!leadingCell || (leadingCell.text !== text)) { + newCell = buildCellObject(date, text, rowUnits[row], view); + } + else { + leadingCell.colspan += 1; + } + } + else { + if (!leadingCell || + core.isInt(dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.labelInterval))) { + var text = dateEnv.format(date, format); + newCell = buildCellObject(date, text, rowUnits[row], view); + } + else { + leadingCell.colspan += 1; + } + } + if (newCell) { + newCell.weekStart = isWeekStart; + rowCells.push(newCell); + } + } + } + return cellRows; + } + function buildCellObject(date, text, rowUnit, view) { + var spanHtml = core.buildGotoAnchorHtml(view, { + date: date, + type: rowUnit, + forceOff: !rowUnit + }, { + 'class': 'fc-cell-text' + }, core.htmlEscape(text)); + return { text: text, spanHtml: spanHtml, date: date, colspan: 1, isWeekStart: false }; + } + + var TimelineNowIndicator = /** @class */ (function () { + function TimelineNowIndicator(headParent, bodyParent) { + this.headParent = headParent; + this.bodyParent = bodyParent; + } + TimelineNowIndicator.prototype.render = function (coord, isRtl) { + var styleProps = isRtl ? { right: -coord } : { left: coord }; + this.headParent.appendChild(this.arrowEl = core.createElement('div', { + className: 'fc-now-indicator fc-now-indicator-arrow', + style: styleProps + })); + this.bodyParent.appendChild(this.lineEl = core.createElement('div', { + className: 'fc-now-indicator fc-now-indicator-line', + style: styleProps + })); + }; + TimelineNowIndicator.prototype.unrender = function () { + if (this.arrowEl) { + core.removeElement(this.arrowEl); + } + if (this.lineEl) { + core.removeElement(this.lineEl); + } + }; + return TimelineNowIndicator; + }()); + + var STICKY_PROP_VAL = computeStickyPropVal(); // if null, means not supported at all + var IS_MS_EDGE = /Edge/.test(navigator.userAgent); + var IS_SAFARI = STICKY_PROP_VAL === '-webkit-sticky'; // good b/c doesn't confuse chrome + var STICKY_CLASSNAME = 'fc-sticky'; + /* + useful beyond the native position:sticky for these reasons: + - support in IE11 + - nice centering support + */ + var StickyScroller = /** @class */ (function () { + function StickyScroller(scroller, isRtl, isVertical) { + var _this = this; + this.usingRelative = null; + /* + known bug: called twice on init. problem when mixing with ScrollJoiner + */ + this.updateSize = function () { + var els = Array.prototype.slice.call(_this.scroller.canvas.el.querySelectorAll('.' + STICKY_CLASSNAME)); + var elGeoms = _this.queryElGeoms(els); + var viewportWidth = _this.scroller.el.clientWidth; + if (_this.usingRelative) { + var elDestinations = _this.computeElDestinations(elGeoms, viewportWidth); // read before prepPositioning + assignRelativePositions(els, elGeoms, elDestinations); + } + else { + assignStickyPositions(els, elGeoms, viewportWidth); + } + }; + this.scroller = scroller; + this.usingRelative = + !STICKY_PROP_VAL || // IE11 + (IS_MS_EDGE && isRtl) || // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/18883305/ + ((IS_MS_EDGE || IS_SAFARI) && isVertical); // because doesn't work with rowspan in tables, our only vertial use + if (this.usingRelative) { + scroller.on('scrollEnd', this.updateSize); + } + } + StickyScroller.prototype.destroy = function () { + this.scroller.off('scrollEnd', this.updateSize); + }; + StickyScroller.prototype.queryElGeoms = function (els) { + var canvasOrigin = this.scroller.canvas.el.getBoundingClientRect(); + var elGeoms = []; + for (var _i = 0, els_1 = els; _i < els_1.length; _i++) { + var el = els_1[_i]; + var parentBound = core.translateRect(el.parentNode.getBoundingClientRect(), -canvasOrigin.left, -canvasOrigin.top); + var elRect = el.getBoundingClientRect(); + var computedStyles = window.getComputedStyle(el); + var computedTextAlign = window.getComputedStyle(el.parentNode).textAlign; // ask the parent + var intendedTextAlign = computedTextAlign; + var naturalBound = null; + if (computedStyles.position !== 'sticky') { + naturalBound = core.translateRect(elRect, -canvasOrigin.left - (parseFloat(computedStyles.left) || 0), // could be 'auto' + -canvasOrigin.top - (parseFloat(computedStyles.top) || 0)); + } + if (el.hasAttribute('data-sticky-center')) { + intendedTextAlign = 'center'; + } + elGeoms.push({ + parentBound: parentBound, + naturalBound: naturalBound, + elWidth: elRect.width, + elHeight: elRect.height, + computedTextAlign: computedTextAlign, + intendedTextAlign: intendedTextAlign + }); + } + return elGeoms; + }; + StickyScroller.prototype.computeElDestinations = function (elGeoms, viewportWidth) { + var viewportLeft = this.scroller.getScrollFromLeft(); + var viewportTop = this.scroller.getScrollTop(); + var viewportRight = viewportLeft + viewportWidth; + return elGeoms.map(function (elGeom) { + var elWidth = elGeom.elWidth, elHeight = elGeom.elHeight, parentBound = elGeom.parentBound, naturalBound = elGeom.naturalBound; + var destLeft; // relative to canvas topleft + var destTop; // " + switch (elGeom.intendedTextAlign) { + case 'left': + destLeft = viewportLeft; + break; + case 'right': + destLeft = viewportRight - elWidth; + break; + case 'center': + destLeft = (viewportLeft + viewportRight) / 2 - elWidth / 2; + break; + } + destLeft = Math.min(destLeft, parentBound.right - elWidth); + destLeft = Math.max(destLeft, parentBound.left); + destTop = viewportTop; + destTop = Math.min(destTop, parentBound.bottom - elHeight); + destTop = Math.max(destTop, naturalBound.top); // better to use natural top for upper bound + return { left: destLeft, top: destTop }; + }); + }; + return StickyScroller; + }()); + function assignRelativePositions(els, elGeoms, elDestinations) { + els.forEach(function (el, i) { + var naturalBound = elGeoms[i].naturalBound; + core.applyStyle(el, { + position: 'relative', + left: elDestinations[i].left - naturalBound.left, + top: elDestinations[i].top - naturalBound.top + }); + }); + } + function assignStickyPositions(els, elGeoms, viewportWidth) { + els.forEach(function (el, i) { + var stickyLeft = 0; + if (elGeoms[i].intendedTextAlign === 'center') { + stickyLeft = (viewportWidth - elGeoms[i].elWidth) / 2; + // needs to be forced to left? + if (elGeoms[i].computedTextAlign === 'center') { + el.setAttribute('data-sticky-center', '') // remember for next queryElGeoms + ; + el.parentNode.style.textAlign = 'left'; + } + } + core.applyStyle(el, { + position: STICKY_PROP_VAL, + left: stickyLeft, + right: 0, + top: 0 + }); + }); + } + function computeStickyPropVal() { + var el = core.htmlToElement('<div style="position:-webkit-sticky;position:sticky"></div>'); + var val = el.style.position; + if (val.indexOf('sticky') !== -1) { + return val; + } + else { + return null; + } + } + + var TimeAxis = /** @class */ (function (_super) { + __extends(TimeAxis, _super); + function TimeAxis(context, headerContainerEl, bodyContainerEl) { + var _this = _super.call(this, context) || this; + var layout = _this.layout = new HeaderBodyLayout(headerContainerEl, bodyContainerEl, 'auto'); + var headerEnhancedScroller = layout.headerScroller.enhancedScroll; + var bodyEnhancedScroller = layout.bodyScroller.enhancedScroll; + // needs to go after layout, which has ScrollJoiner + _this.headStickyScroller = new StickyScroller(headerEnhancedScroller, _this.isRtl, false); // isVertical=false + _this.bodyStickyScroller = new StickyScroller(bodyEnhancedScroller, _this.isRtl, false); // isVertical=false + _this.header = new TimelineHeader(context, headerEnhancedScroller.canvas.contentEl); + _this.slats = new TimelineSlats(context, bodyEnhancedScroller.canvas.bgEl); + _this.nowIndicator = new TimelineNowIndicator(headerEnhancedScroller.canvas.el, bodyEnhancedScroller.canvas.el); + return _this; + } + TimeAxis.prototype.destroy = function () { + this.layout.destroy(); + this.header.destroy(); + this.slats.destroy(); + this.nowIndicator.unrender(); + this.headStickyScroller.destroy(); + this.bodyStickyScroller.destroy(); + _super.prototype.destroy.call(this); + }; + TimeAxis.prototype.render = function (props) { + var tDateProfile = this.tDateProfile = + buildTimelineDateProfile(props.dateProfile, this.view); // TODO: cache + this.header.receiveProps({ + dateProfile: props.dateProfile, + tDateProfile: tDateProfile + }); + this.slats.receiveProps({ + dateProfile: props.dateProfile, + tDateProfile: tDateProfile + }); + }; + // Now Indicator + // ------------------------------------------------------------------------------------------ + TimeAxis.prototype.getNowIndicatorUnit = function (dateProfile) { + // yuck + var tDateProfile = this.tDateProfile = + buildTimelineDateProfile(dateProfile, this.view); // TODO: cache + if (tDateProfile.isTimeScale) { + return core.greatestDurationDenominator(tDateProfile.slotDuration).unit; + } + }; + // will only execute if isTimeScale + TimeAxis.prototype.renderNowIndicator = function (date) { + if (core.rangeContainsMarker(this.tDateProfile.normalizedRange, date)) { + this.nowIndicator.render(this.dateToCoord(date), this.isRtl); + } + }; + // will only execute if isTimeScale + TimeAxis.prototype.unrenderNowIndicator = function () { + this.nowIndicator.unrender(); + }; + // Sizing + // ------------------------------------------------------------------------------------------ + TimeAxis.prototype.updateSize = function (isResize, totalHeight, isAuto) { + this.applySlotWidth(this.computeSlotWidth()); + // adjusts gutters. do after slot widths set + this.layout.setHeight(totalHeight, isAuto); + // pretty much just queries coords. do last + this.slats.updateSize(); + }; + TimeAxis.prototype.updateStickyScrollers = function () { + this.headStickyScroller.updateSize(); + this.bodyStickyScroller.updateSize(); + }; + TimeAxis.prototype.computeSlotWidth = function () { + var slotWidth = this.opt('slotWidth') || ''; + if (slotWidth === '') { + slotWidth = this.computeDefaultSlotWidth(this.tDateProfile); + } + return slotWidth; + }; + TimeAxis.prototype.computeDefaultSlotWidth = function (tDateProfile) { + var maxInnerWidth = 0; // TODO: harness core's `matchCellWidths` for this + this.header.innerEls.forEach(function (innerEl, i) { + maxInnerWidth = Math.max(maxInnerWidth, innerEl.getBoundingClientRect().width); + }); + var headingCellWidth = Math.ceil(maxInnerWidth) + 1; // assume no padding, and one pixel border + // in TimelineView.defaults we ensured that labelInterval is an interval of slotDuration + // TODO: rename labelDuration? + var slotsPerLabel = core.wholeDivideDurations(tDateProfile.labelInterval, tDateProfile.slotDuration); + var slotWidth = Math.ceil(headingCellWidth / slotsPerLabel); + var minWidth = window.getComputedStyle(this.header.slatColEls[0]).minWidth; + if (minWidth) { + minWidth = parseInt(minWidth, 10); + if (minWidth) { + slotWidth = Math.max(slotWidth, minWidth); + } + } + return slotWidth; + }; + TimeAxis.prototype.applySlotWidth = function (slotWidth) { + var _a = this, layout = _a.layout, tDateProfile = _a.tDateProfile; + var containerWidth = ''; + var containerMinWidth = ''; + var nonLastSlotWidth = ''; + if (slotWidth !== '') { + slotWidth = Math.round(slotWidth); + containerWidth = slotWidth * tDateProfile.slotDates.length; + containerMinWidth = ''; + nonLastSlotWidth = slotWidth; + var availableWidth = layout.bodyScroller.enhancedScroll.getClientWidth(); + if (availableWidth > containerWidth) { + containerMinWidth = availableWidth; + containerWidth = ''; + nonLastSlotWidth = Math.floor(availableWidth / tDateProfile.slotDates.length); + } + } + layout.headerScroller.enhancedScroll.canvas.setWidth(containerWidth); + layout.headerScroller.enhancedScroll.canvas.setMinWidth(containerMinWidth); + layout.bodyScroller.enhancedScroll.canvas.setWidth(containerWidth); + layout.bodyScroller.enhancedScroll.canvas.setMinWidth(containerMinWidth); + if (nonLastSlotWidth !== '') { + this.header.slatColEls.slice(0, -1).concat(this.slats.slatColEls.slice(0, -1)).forEach(function (el) { + el.style.width = nonLastSlotWidth + 'px'; + }); + } + }; + // returned value is between 0 and the number of snaps + TimeAxis.prototype.computeDateSnapCoverage = function (date) { + var _a = this, dateEnv = _a.dateEnv, tDateProfile = _a.tDateProfile; + var snapDiff = dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.snapDuration); + if (snapDiff < 0) { + return 0; + } + else if (snapDiff >= tDateProfile.snapDiffToIndex.length) { + return tDateProfile.snapCnt; + } + else { + var snapDiffInt = Math.floor(snapDiff); + var snapCoverage = tDateProfile.snapDiffToIndex[snapDiffInt]; + if (core.isInt(snapCoverage)) { // not an in-between value + snapCoverage += snapDiff - snapDiffInt; // add the remainder + } + else { + // a fractional value, meaning the date is not visible + // always round up in this case. works for start AND end dates in a range. + snapCoverage = Math.ceil(snapCoverage); + } + return snapCoverage; + } + }; + // for LTR, results range from 0 to width of area + // for RTL, results range from negative width of area to 0 + TimeAxis.prototype.dateToCoord = function (date) { + var tDateProfile = this.tDateProfile; + var snapCoverage = this.computeDateSnapCoverage(date); + var slotCoverage = snapCoverage / tDateProfile.snapsPerSlot; + var slotIndex = Math.floor(slotCoverage); + slotIndex = Math.min(slotIndex, tDateProfile.slotCnt - 1); + var partial = slotCoverage - slotIndex; + var _a = this.slats, innerCoordCache = _a.innerCoordCache, outerCoordCache = _a.outerCoordCache; + if (this.isRtl) { + return (outerCoordCache.rights[slotIndex] - + (innerCoordCache.getWidth(slotIndex) * partial)) - outerCoordCache.originClientRect.width; + } + else { + return (outerCoordCache.lefts[slotIndex] + + (innerCoordCache.getWidth(slotIndex) * partial)); + } + }; + TimeAxis.prototype.rangeToCoords = function (range) { + if (this.isRtl) { + return { right: this.dateToCoord(range.start), left: this.dateToCoord(range.end) }; + } + else { + return { left: this.dateToCoord(range.start), right: this.dateToCoord(range.end) }; + } + }; + // Scrolling + // ------------------------------------------------------------------------------------------ + TimeAxis.prototype.computeDateScroll = function (duration) { + var dateEnv = this.dateEnv; + var dateProfile = this.props.dateProfile; + var left = 0; + if (dateProfile) { + left = this.dateToCoord(dateEnv.add(core.startOfDay(dateProfile.activeRange.start), // startOfDay needed? + duration)); + // hack to overcome the left borders of non-first slat + if (!this.isRtl && left) { + left += 1; + } + } + return { left: left }; + }; + TimeAxis.prototype.queryDateScroll = function () { + var enhancedScroll = this.layout.bodyScroller.enhancedScroll; + return { + left: enhancedScroll.getScrollLeft() + }; + }; + TimeAxis.prototype.applyDateScroll = function (scroll) { + // TODO: lame we have to update both. use the scrolljoiner instead maybe + this.layout.bodyScroller.enhancedScroll.setScrollLeft(scroll.left || 0); + this.layout.headerScroller.enhancedScroll.setScrollLeft(scroll.left || 0); + }; + return TimeAxis; + }(core.Component)); + + var TimelineLaneEventRenderer = /** @class */ (function (_super) { + __extends(TimelineLaneEventRenderer, _super); + function TimelineLaneEventRenderer(context, masterContainerEl, timeAxis) { + var _this = _super.call(this, context) || this; + _this.masterContainerEl = masterContainerEl; + _this.timeAxis = timeAxis; + return _this; + } + TimelineLaneEventRenderer.prototype.renderSegHtml = function (seg, mirrorInfo) { + var view = this.context.view; + var eventRange = seg.eventRange; + var eventDef = eventRange.def; + var eventUi = eventRange.ui; + var isDraggable = view.computeEventDraggable(eventDef, eventUi); + var isResizableFromStart = seg.isStart && view.computeEventStartResizable(eventDef, eventUi); + var isResizableFromEnd = seg.isEnd && view.computeEventEndResizable(eventDef, eventUi); + var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd, mirrorInfo); + classes.unshift('fc-timeline-event', 'fc-h-event'); + var timeText = this.getTimeText(eventRange); + return '<a class="' + classes.join(' ') + '" style="' + core.cssToStr(this.getSkinCss(eventUi)) + '"' + + (eventDef.url ? + ' href="' + core.htmlEscape(eventDef.url) + '"' : + '') + + '>' + + (timeText ? + '<span class="fc-time-wrap">' + + '<span class="fc-time">' + + core.htmlEscape(timeText) + + '</span>' + + '</span>' + : + '') + + '<span class="fc-title-wrap">' + + '<span class="fc-title fc-sticky">' + + (eventDef.title ? core.htmlEscape(eventDef.title) : ' ') + + '</span>' + + '</span>' + + (isResizableFromStart ? + '<div class="fc-resizer fc-start-resizer"></div>' : + '') + + (isResizableFromEnd ? + '<div class="fc-resizer fc-end-resizer"></div>' : + '') + + '</a>'; + }; + TimelineLaneEventRenderer.prototype.computeDisplayEventTime = function () { + return !this.timeAxis.tDateProfile.isTimeScale; // because times should be obvious via axis + }; + TimelineLaneEventRenderer.prototype.computeDisplayEventEnd = function () { + return false; + }; + // Computes a default event time formatting string if `timeFormat` is not explicitly defined + TimelineLaneEventRenderer.prototype.computeEventTimeFormat = function () { + return { + hour: 'numeric', + minute: '2-digit', + omitZeroMinute: true, + meridiem: 'narrow' + }; + }; + TimelineLaneEventRenderer.prototype.attachSegs = function (segs, mirrorInfo) { + if (!this.el && this.masterContainerEl) { + this.el = core.createElement('div', { className: 'fc-event-container' }); + if (mirrorInfo) { + this.el.classList.add('fc-mirror-container'); + } + this.masterContainerEl.appendChild(this.el); + } + if (this.el) { + for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { + var seg = segs_1[_i]; + this.el.appendChild(seg.el); + } + } + }; + TimelineLaneEventRenderer.prototype.detachSegs = function (segs) { + for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { + var seg = segs_2[_i]; + core.removeElement(seg.el); + } + }; + // computes AND assigns (assigns the left/right at least). bad + TimelineLaneEventRenderer.prototype.computeSegSizes = function (segs) { + var timeAxis = this.timeAxis; + for (var _i = 0, segs_3 = segs; _i < segs_3.length; _i++) { + var seg = segs_3[_i]; + var coords = timeAxis.rangeToCoords(seg); // works because Seg has start/end + core.applyStyle(seg.el, { + left: (seg.left = coords.left), + right: -(seg.right = coords.right) + }); + } + }; + TimelineLaneEventRenderer.prototype.assignSegSizes = function (segs) { + if (!this.el) { + return; + } + // compute seg verticals + for (var _i = 0, segs_4 = segs; _i < segs_4.length; _i++) { + var seg = segs_4[_i]; + seg.height = core.computeHeightAndMargins(seg.el); + } + this.buildSegLevels(segs); // populates above/below props for computeOffsetForSegs + var totalHeight = computeOffsetForSegs(segs); // also assigns seg.top + core.applyStyleProp(this.el, 'height', totalHeight); + // assign seg verticals + for (var _a = 0, segs_5 = segs; _a < segs_5.length; _a++) { + var seg = segs_5[_a]; + core.applyStyleProp(seg.el, 'top', seg.top); + } + }; + TimelineLaneEventRenderer.prototype.buildSegLevels = function (segs) { + var segLevels = []; + segs = this.sortEventSegs(segs); + for (var _i = 0, segs_6 = segs; _i < segs_6.length; _i++) { + var unplacedSeg = segs_6[_i]; + unplacedSeg.above = []; + // determine the first level with no collisions + var level = 0; // level index + while (level < segLevels.length) { + var isLevelCollision = false; + // determine collisions + for (var _a = 0, _b = segLevels[level]; _a < _b.length; _a++) { + var placedSeg = _b[_a]; + if (timeRowSegsCollide(unplacedSeg, placedSeg)) { + unplacedSeg.above.push(placedSeg); + isLevelCollision = true; + } + } + if (isLevelCollision) { + level += 1; + } + else { + break; + } + } + // insert into the first non-colliding level. create if necessary + (segLevels[level] || (segLevels[level] = [])) + .push(unplacedSeg); + // record possible colliding segments below (TODO: automated test for this) + level += 1; + while (level < segLevels.length) { + for (var _c = 0, _d = segLevels[level]; _c < _d.length; _c++) { + var belowSeg = _d[_c]; + if (timeRowSegsCollide(unplacedSeg, belowSeg)) { + belowSeg.above.push(unplacedSeg); + } + } + level += 1; + } + } + return segLevels; + }; + return TimelineLaneEventRenderer; + }(core.FgEventRenderer)); + function computeOffsetForSegs(segs) { + var max = 0; + for (var _i = 0, segs_7 = segs; _i < segs_7.length; _i++) { + var seg = segs_7[_i]; + max = Math.max(max, computeOffsetForSeg(seg)); + } + return max; + } + function computeOffsetForSeg(seg) { + if ((seg.top == null)) { + seg.top = computeOffsetForSegs(seg.above); + } + return seg.top + seg.height; + } + function timeRowSegsCollide(seg0, seg1) { + return (seg0.left < seg1.right) && (seg0.right > seg1.left); + } + + var TimelineLaneFillRenderer = /** @class */ (function (_super) { + __extends(TimelineLaneFillRenderer, _super); + function TimelineLaneFillRenderer(context, masterContainerEl, timeAxis) { + var _this = _super.call(this, context) || this; + _this.masterContainerEl = masterContainerEl; + _this.timeAxis = timeAxis; + return _this; + } + TimelineLaneFillRenderer.prototype.attachSegs = function (type, segs) { + if (segs.length) { + var className = void 0; + if (type === 'businessHours') { + className = 'bgevent'; + } + else { + className = type.toLowerCase(); + } + // making a new container each time is OKAY + // all types of segs (background or business hours or whatever) are rendered in one pass + var containerEl = core.createElement('div', { className: 'fc-' + className + '-container' }); + this.masterContainerEl.appendChild(containerEl); + for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { + var seg = segs_1[_i]; + containerEl.appendChild(seg.el); + } + return [containerEl]; // return value + } + }; + TimelineLaneFillRenderer.prototype.computeSegSizes = function (segs) { + var timeAxis = this.timeAxis; + for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { + var seg = segs_2[_i]; + var coords = timeAxis.rangeToCoords(seg); + seg.left = coords.left; + seg.right = coords.right; + } + }; + TimelineLaneFillRenderer.prototype.assignSegSizes = function (segs) { + for (var _i = 0, segs_3 = segs; _i < segs_3.length; _i++) { + var seg = segs_3[_i]; + core.applyStyle(seg.el, { + left: seg.left, + right: -seg.right + }); + } + }; + return TimelineLaneFillRenderer; + }(core.FillRenderer)); + + var TimelineLane = /** @class */ (function (_super) { + __extends(TimelineLane, _super); + function TimelineLane(context, fgContainerEl, bgContainerEl, timeAxis) { + var _this = _super.call(this, context, bgContainerEl) // should el be bgContainerEl??? + || this; + _this.slicer = new TimelineLaneSlicer(); + _this.renderEventDrag = core.memoizeRendering(_this._renderEventDrag, _this._unrenderEventDrag); + _this.renderEventResize = core.memoizeRendering(_this._renderEventResize, _this._unrenderEventResize); + var fillRenderer = _this.fillRenderer = new TimelineLaneFillRenderer(context, bgContainerEl, timeAxis); + var eventRenderer = _this.eventRenderer = new TimelineLaneEventRenderer(context, fgContainerEl, timeAxis); + _this.mirrorRenderer = new TimelineLaneEventRenderer(context, fgContainerEl, timeAxis); + _this.renderBusinessHours = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'businessHours'), fillRenderer.unrender.bind(fillRenderer, 'businessHours')); + _this.renderDateSelection = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'highlight'), fillRenderer.unrender.bind(fillRenderer, 'highlight')); + _this.renderBgEvents = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'bgEvent'), fillRenderer.unrender.bind(fillRenderer, 'bgEvent')); + _this.renderFgEvents = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer)); + _this.renderEventSelection = core.memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]); + _this.timeAxis = timeAxis; + return _this; + } + TimelineLane.prototype.render = function (props) { + var slicedProps = this.slicer.sliceProps(props, props.dateProfile, this.timeAxis.tDateProfile.isTimeScale ? null : props.nextDayThreshold, this, this.timeAxis); + this.renderBusinessHours(slicedProps.businessHourSegs); + this.renderDateSelection(slicedProps.dateSelectionSegs); + this.renderBgEvents(slicedProps.bgEventSegs); + this.renderFgEvents(slicedProps.fgEventSegs); + this.renderEventSelection(slicedProps.eventSelection); + this.renderEventDrag(slicedProps.eventDrag); + this.renderEventResize(slicedProps.eventResize); + }; + TimelineLane.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.renderBusinessHours.unrender(); + this.renderDateSelection.unrender(); + this.renderBgEvents.unrender(); + this.renderFgEvents.unrender(); + this.renderEventSelection.unrender(); + this.renderEventDrag.unrender(); + this.renderEventResize.unrender(); + }; + TimelineLane.prototype._renderEventDrag = function (state) { + if (state) { + this.eventRenderer.hideByHash(state.affectedInstances); + this.mirrorRenderer.renderSegs(state.segs, { isDragging: true, sourceSeg: state.sourceSeg }); + } + }; + TimelineLane.prototype._unrenderEventDrag = function (state) { + if (state) { + this.eventRenderer.showByHash(state.affectedInstances); + this.mirrorRenderer.unrender(state.segs, { isDragging: true, sourceSeg: state.sourceSeg }); + } + }; + TimelineLane.prototype._renderEventResize = function (state) { + if (state) { + // HACK. eventRenderer and fillRenderer both use these segs. would compete over seg.el + var segsForHighlight = state.segs.map(function (seg) { + return __assign({}, seg); + }); + this.eventRenderer.hideByHash(state.affectedInstances); + this.fillRenderer.renderSegs('highlight', segsForHighlight); + this.mirrorRenderer.renderSegs(state.segs, { isDragging: true, sourceSeg: state.sourceSeg }); + } + }; + TimelineLane.prototype._unrenderEventResize = function (state) { + if (state) { + this.eventRenderer.showByHash(state.affectedInstances); + this.fillRenderer.unrender('highlight'); + this.mirrorRenderer.unrender(state.segs, { isDragging: true, sourceSeg: state.sourceSeg }); + } + }; + TimelineLane.prototype.updateSize = function (isResize) { + var _a = this, fillRenderer = _a.fillRenderer, eventRenderer = _a.eventRenderer, mirrorRenderer = _a.mirrorRenderer; + fillRenderer.computeSizes(isResize); + eventRenderer.computeSizes(isResize); + mirrorRenderer.computeSizes(isResize); + fillRenderer.assignSizes(isResize); + eventRenderer.assignSizes(isResize); + mirrorRenderer.assignSizes(isResize); + }; + return TimelineLane; + }(core.DateComponent)); + var TimelineLaneSlicer = /** @class */ (function (_super) { + __extends(TimelineLaneSlicer, _super); + function TimelineLaneSlicer() { + return _super !== null && _super.apply(this, arguments) || this; + } + TimelineLaneSlicer.prototype.sliceRange = function (origRange, timeAxis) { + var tDateProfile = timeAxis.tDateProfile; + var dateProfile = timeAxis.props.dateProfile; + var normalRange = normalizeRange(origRange, tDateProfile, timeAxis.dateEnv); + var segs = []; + // protect against when the span is entirely in an invalid date region + if (timeAxis.computeDateSnapCoverage(normalRange.start) < timeAxis.computeDateSnapCoverage(normalRange.end)) { + // intersect the footprint's range with the grid's range + var slicedRange = core.intersectRanges(normalRange, tDateProfile.normalizedRange); + if (slicedRange) { + segs.push({ + start: slicedRange.start, + end: slicedRange.end, + isStart: slicedRange.start.valueOf() === normalRange.start.valueOf() && isValidDate(slicedRange.start, tDateProfile, dateProfile, timeAxis.view), + isEnd: slicedRange.end.valueOf() === normalRange.end.valueOf() && isValidDate(core.addMs(slicedRange.end, -1), tDateProfile, dateProfile, timeAxis.view) + }); + } + } + return segs; + }; + return TimelineLaneSlicer; + }(core.Slicer)); + + var TimelineView = /** @class */ (function (_super) { + __extends(TimelineView, _super); + function TimelineView(context, viewSpec, dateProfileGenerator, parentEl) { + var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this; + _this.el.classList.add('fc-timeline'); + if (_this.opt('eventOverlap') === false) { + _this.el.classList.add('fc-no-overlap'); + } + _this.el.innerHTML = _this.renderSkeletonHtml(); + _this.timeAxis = new TimeAxis(_this.context, _this.el.querySelector('thead .fc-time-area'), _this.el.querySelector('tbody .fc-time-area')); + _this.lane = new TimelineLane(_this.context, _this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.contentEl, _this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.bgEl, _this.timeAxis); + context.calendar.registerInteractiveComponent(_this, { + el: _this.timeAxis.slats.el + }); + return _this; + } + TimelineView.prototype.destroy = function () { + this.timeAxis.destroy(); + this.lane.destroy(); + _super.prototype.destroy.call(this); + this.calendar.unregisterInteractiveComponent(this); + }; + TimelineView.prototype.renderSkeletonHtml = function () { + var theme = this.theme; + return "<table class=\"" + theme.getClass('tableGrid') + "\"> <thead class=\"fc-head\"> <tr> <td class=\"fc-time-area " + theme.getClass('widgetHeader') + "\"></td> </tr> </thead> <tbody class=\"fc-body\"> <tr> <td class=\"fc-time-area " + theme.getClass('widgetContent') + "\"></td> </tr> </tbody> </table>"; + }; + TimelineView.prototype.render = function (props) { + _super.prototype.render.call(this, props); // flags for updateSize, addScroll + this.timeAxis.receiveProps({ + dateProfile: props.dateProfile + }); + this.lane.receiveProps(__assign({}, props, { nextDayThreshold: this.nextDayThreshold })); + }; + TimelineView.prototype.updateSize = function (isResize, totalHeight, isAuto) { + this.timeAxis.updateSize(isResize, totalHeight, isAuto); + this.lane.updateSize(isResize); + }; + // Now Indicator + // ------------------------------------------------------------------------------------------ + TimelineView.prototype.getNowIndicatorUnit = function (dateProfile) { + return this.timeAxis.getNowIndicatorUnit(dateProfile); + }; + TimelineView.prototype.renderNowIndicator = function (date) { + this.timeAxis.renderNowIndicator(date); + }; + TimelineView.prototype.unrenderNowIndicator = function () { + this.timeAxis.unrenderNowIndicator(); + }; + // Scroll System + // ------------------------------------------------------------------------------------------ + TimelineView.prototype.computeDateScroll = function (duration) { + return this.timeAxis.computeDateScroll(duration); + }; + TimelineView.prototype.applyScroll = function (scroll, isResize) { + _super.prototype.applyScroll.call(this, scroll, isResize); // will call applyDateScroll + // avoid updating stickyscroll too often + // TODO: repeat code as ResourceTimelineView::updateSize + var calendar = this.calendar; + if (isResize || calendar.isViewUpdated || calendar.isDatesUpdated || calendar.isEventsUpdated) { + this.timeAxis.updateStickyScrollers(); + } + }; + TimelineView.prototype.applyDateScroll = function (scroll) { + this.timeAxis.applyDateScroll(scroll); + }; + TimelineView.prototype.queryScroll = function () { + var enhancedScroll = this.timeAxis.layout.bodyScroller.enhancedScroll; + return { + top: enhancedScroll.getScrollTop(), + left: enhancedScroll.getScrollLeft() + }; + }; + // Hit System + // ------------------------------------------------------------------------------------------ + TimelineView.prototype.buildPositionCaches = function () { + this.timeAxis.slats.updateSize(); + }; + TimelineView.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) { + var slatHit = this.timeAxis.slats.positionToHit(positionLeft); + if (slatHit) { + return { + component: this, + dateSpan: slatHit.dateSpan, + rect: { + left: slatHit.left, + right: slatHit.right, + top: 0, + bottom: elHeight + }, + dayEl: slatHit.dayEl, + layer: 0 + }; + } + }; + return TimelineView; + }(core.View)); + + var main = core.createPlugin({ + defaultView: 'timelineDay', + views: { + timeline: { + class: TimelineView, + eventResizableFromStart: true // how is this consumed for TimelineView tho? + }, + timelineDay: { + type: 'timeline', + duration: { days: 1 } + }, + timelineWeek: { + type: 'timeline', + duration: { weeks: 1 } + }, + timelineMonth: { + type: 'timeline', + duration: { months: 1 } + }, + timelineYear: { + type: 'timeline', + duration: { years: 1 } + } + } + }); + + exports.HeaderBodyLayout = HeaderBodyLayout; + exports.ScrollJoiner = ScrollJoiner; + exports.StickyScroller = StickyScroller; + exports.TimeAxis = TimeAxis; + exports.TimelineLane = TimelineLane; + exports.TimelineView = TimelineView; + exports.default = main; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); diff --git a/AKPlan/static/AKPlan/fullcalendar/timeline/main.min.css b/AKPlan/static/AKPlan/fullcalendar/timeline/main.min.css new file mode 100644 index 00000000..df72784b --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/timeline/main.min.css @@ -0,0 +1 @@ +.fc-scroller-clip{overflow:hidden;position:relative}.fc-no-scrollbars{background:rgba(255,255,255,0)}.fc-no-scrollbars::-webkit-scrollbar{width:0;height:0}.fc-scroller-canvas{position:relative;box-sizing:border-box;min-height:100%}.fc-scroller-canvas>.fc-bg{z-index:1}.fc-scroller-canvas>.fc-content{z-index:2;position:relative;border-style:solid;border-width:0}.fc-scroller-canvas.fc-gutter-left>.fc-content{border-left-width:1px;margin-left:-1px}.fc-scroller-canvas.fc-gutter-right>.fc-content{border-right-width:1px;margin-right:-1px}.fc-scroller-canvas.fc-gutter-top>.fc-content{border-top-width:1px;margin-top:-1px}.fc-rtl .fc-timeline{direction:rtl}.fc-scrolled .fc-head .fc-scroller{z-index:2}.fc-timeline.fc-scrolled .fc-head .fc-scroller{box-shadow:0 3px 4px rgba(0,0,0,.075)}.fc-timeline .fc-body .fc-scroller{z-index:1}.fc-timeline .fc-scroller-canvas>div>div>table,.fc-timeline .fc-scroller-canvas>div>table{border-style:hidden}.fc-timeline .fc-scroller-canvas>.fc-content>.fc-rows>table{border-bottom-style:none}.fc-timeline td,.fc-timeline th{white-space:nowrap}.fc-timeline .fc-cell-content{overflow:hidden}.fc-timeline .fc-cell-text{display:inline-block;padding-left:4px;padding-right:4px}.fc-timeline th{vertical-align:middle}.fc-timeline .fc-head .fc-cell-content{padding-top:3px;padding-bottom:3px}.fc-timeline .fc-head .fc-time-area .fc-cell-content{overflow:visible}.fc-time-area col{min-width:2.2em}.fc-ltr .fc-time-area .fc-chrono th{text-align:left}.fc-rtl .fc-time-area .fc-chrono th{text-align:right}.fc-time-area .fc-slats{position:absolute;z-index:1;top:0;left:0;right:0;bottom:0}.fc-time-area .fc-slats table{height:100%}.fc-time-area .fc-slats .fc-minor{border-style:dotted}.fc-time-area .fc-slats td{border-width:0 1px}.fc-ltr .fc-time-area .fc-slats td{border-right-width:0}.fc-rtl .fc-time-area .fc-slats td{border-left-width:0}.fc-time-area .fc-bgevent-container,.fc-time-area .fc-highlight-container{position:absolute;z-index:2;top:0;bottom:0;width:0}.fc-ltr .fc-time-area .fc-bgevent-container,.fc-ltr .fc-time-area .fc-highlight-container,.fc-ltr .fc-time-area .fc-mirror-container{left:0}.fc-rtl .fc-time-area .fc-bgevent-container,.fc-rtl .fc-time-area .fc-highlight-container,.fc-rtl .fc-time-area .fc-mirror-container{right:0}.fc-time-area .fc-bgevent,.fc-time-area .fc-highlight{position:absolute;top:0;bottom:0}.fc-timeline .fc-now-indicator{z-index:3;top:0}.fc-time-area .fc-now-indicator-arrow{margin:0 -6px;border-width:6px 5px 0;border-left-color:transparent;border-right-color:transparent}.fc-time-area .fc-now-indicator-line{margin:0 -1px;bottom:0;border-left-width:1px}.fc-time-area .fc-event-container{position:relative;z-index:2;width:0}.fc-time-area .fc-mirror-container{position:absolute;z-index:3;top:0}.fc-time-area .fc-event-container{padding-bottom:8px;top:-1px}.fc-time-area tr:first-child .fc-event-container{top:0}.fc-no-overlap .fc-time-area .fc-event-container{padding-bottom:0;top:0}.fc-timeline-event{position:absolute;display:flex;border-radius:0;padding:2px 1px;margin-bottom:1px}.fc-no-overlap .fc-timeline-event{padding-top:5px;padding-bottom:5px;margin-bottom:0}.fc-ltr .fc-timeline-event{flex-direction:row;margin-right:1px}.fc-rtl .fc-timeline-event{margin-left:1px}.fc-timeline-event .fc-time-wrap{flex-shrink:0;min-width:0}.fc-timeline-event .fc-title-wrap{flex-grow:1;min-width:0}.fc-timeline-event .fc-time,.fc-timeline-event .fc-title{display:inline-block;vertical-align:top;max-width:100%;padding:0 2px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;white-space:nowrap;overflow:hidden}.fc-timeline-event .fc-time{font-weight:700}.fc-timeline-event.fc-not-end:after,.fc-timeline-event.fc-not-start:before{content:"";align-self:center;width:0;height:0;margin:0 1px;border:5px solid #000;border-top-color:transparent;border-bottom-color:transparent;opacity:.5}.fc-ltr .fc-timeline-event.fc-not-start:before,.fc-rtl .fc-timeline-event.fc-not-end:after{border-left:0}.fc-ltr .fc-timeline-event.fc-not-end:after,.fc-rtl .fc-timeline-event.fc-not-start:before{border-right:0} \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/timeline/main.min.js b/AKPlan/static/AKPlan/fullcalendar/timeline/main.min.js new file mode 100644 index 00000000..ff54d973 --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/timeline/main.min.js @@ -0,0 +1,6 @@ +/*! +FullCalendar Timeline Plugin v4.3.0 +Docs & License: https://fullcalendar.io/scheduler +(c) 2019 Adam Shaw +*/ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@fullcalendar/core")):"function"==typeof define&&define.amd?define(["exports","@fullcalendar/core"],t):t((e=e||self).FullCalendarTimeline={},e.FullCalendar)}(this,function(e,t){"use strict";var r=function(e,t){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)};function n(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var i,o=function(){return(o=Object.assign||function(e){for(var t,r=1,n=arguments.length;r<n;r++)for(var i in t=arguments[r])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},l=function(){function e(){this.gutters={},this.el=t.htmlToElement('<div class="fc-scroller-canvas"> <div class="fc-content"></div> <div class="fc-bg"></div> </div>'),this.contentEl=this.el.querySelector(".fc-content"),this.bgEl=this.el.querySelector(".fc-bg")}return e.prototype.setGutters=function(e){e?o(this.gutters,e):this.gutters={},this.updateSize()},e.prototype.setWidth=function(e){this.width=e,this.updateSize()},e.prototype.setMinWidth=function(e){this.minWidth=e,this.updateSize()},e.prototype.clearWidth=function(){this.width=null,this.minWidth=null,this.updateSize()},e.prototype.updateSize=function(){var e=this.gutters,r=this.el;t.forceClassName(r,"fc-gutter-left",e.left),t.forceClassName(r,"fc-gutter-right",e.right),t.forceClassName(r,"fc-gutter-top",e.top),t.forceClassName(r,"fc-gutter-bottom",e.bottom),t.applyStyle(r,{paddingLeft:e.left||"",paddingRight:e.right||"",paddingTop:e.top||"",paddingBottom:e.bottom||"",width:null!=this.width?this.width+(e.left||0)+(e.right||0):"",minWidth:null!=this.minWidth?this.minWidth+(e.left||0)+(e.right||0):""}),t.applyStyle(this.bgEl,{left:e.left||"",right:e.right||"",top:e.top||"",bottom:e.bottom||""})},e}(),s=function(e){function r(r,n){var i=e.call(this,r,n)||this;return i.reportScroll=function(){i.isScrolling||i.reportScrollStart(),i.trigger("scroll"),i.isMoving=!0,i.requestMovingEnd()},i.reportScrollStart=function(){i.isScrolling||(i.isScrolling=!0,i.trigger("scrollStart",i.isTouching))},i.reportTouchStart=function(){i.isTouching=!0},i.reportTouchEnd=function(){i.isTouching&&(i.isTouching=!1,i.isTouchScrollEnabled&&i.unbindPreventTouchScroll(),i.isMoving||i.reportScrollEnd())},i.isScrolling=!1,i.isTouching=!1,i.isMoving=!1,i.isTouchScrollEnabled=!0,i.requestMovingEnd=t.debounce(i.reportMovingEnd,500),i.canvas=new l,i.el.appendChild(i.canvas.el),i.applyOverflow(),i.bindHandlers(),i}return n(r,e),r.prototype.destroy=function(){e.prototype.destroy.call(this),this.unbindHandlers()},r.prototype.disableTouchScroll=function(){this.isTouchScrollEnabled=!1,this.bindPreventTouchScroll()},r.prototype.enableTouchScroll=function(){this.isTouchScrollEnabled=!0,this.isTouching||this.unbindPreventTouchScroll()},r.prototype.bindPreventTouchScroll=function(){this.preventTouchScrollHandler||this.el.addEventListener("touchmove",this.preventTouchScrollHandler=t.preventDefault)},r.prototype.unbindPreventTouchScroll=function(){this.preventTouchScrollHandler&&(this.el.removeEventListener("touchmove",this.preventTouchScrollHandler),this.preventTouchScrollHandler=null)},r.prototype.bindHandlers=function(){this.el.addEventListener("scroll",this.reportScroll),this.el.addEventListener("touchstart",this.reportTouchStart,{passive:!0}),this.el.addEventListener("touchend",this.reportTouchEnd)},r.prototype.unbindHandlers=function(){this.el.removeEventListener("scroll",this.reportScroll),this.el.removeEventListener("touchstart",this.reportTouchStart,{passive:!0}),this.el.removeEventListener("touchend",this.reportTouchEnd)},r.prototype.reportMovingEnd=function(){this.isMoving=!1,this.isTouching||this.reportScrollEnd()},r.prototype.reportScrollEnd=function(){this.isScrolling&&(this.trigger("scrollEnd"),this.isScrolling=!1)},r.prototype.getScrollLeft=function(){var e=this.el,t=window.getComputedStyle(e).direction,r=e.scrollLeft;if("rtl"===t)switch(a()){case"positive":r=r+e.clientWidth-e.scrollWidth;break;case"reverse":r=-r}return r},r.prototype.setScrollLeft=function(e){var t=this.el;if("rtl"===window.getComputedStyle(t).direction)switch(a()){case"positive":e=e-t.clientWidth+t.scrollWidth;break;case"reverse":e=-e}t.scrollLeft=e},r.prototype.getScrollFromLeft=function(){var e=this.el,t=window.getComputedStyle(e).direction,r=e.scrollLeft;if("rtl"===t)switch(a()){case"negative":r=r-e.clientWidth+e.scrollWidth;break;case"reverse":r=-r-e.clientWidth+e.scrollWidth}return r},r}(t.ScrollComponent);function a(){return i||(i=function(){var e,r=t.htmlToElement('<div style=" position: absolute; top: -1000px; width: 1px; height: 1px; overflow: scroll; direction: rtl; font-size: 100px; ">A</div>');document.body.appendChild(r),r.scrollLeft>0?e="positive":(r.scrollLeft=1,e=r.scrollLeft>0?"reverse":"negative");return t.removeElement(r),e}())}t.EmitterMixin.mixInto(s);var c=function(){function e(e,r,n){this.isHScrollbarsClipped=!1,this.isVScrollbarsClipped=!1,"clipped-scroll"===e&&(e="scroll",this.isHScrollbarsClipped=!0),"clipped-scroll"===r&&(r="scroll",this.isVScrollbarsClipped=!0),this.enhancedScroll=new s(e,r),n.appendChild(this.el=t.createElement("div",{className:"fc-scroller-clip"})),this.el.appendChild(this.enhancedScroll.el)}return e.prototype.destroy=function(){t.removeElement(this.el)},e.prototype.updateSize=function(){var e=this.enhancedScroll,r=e.el,n=t.computeEdges(r),i={marginLeft:0,marginRight:0,marginTop:0,marginBottom:0};this.isVScrollbarsClipped&&(i.marginLeft=-n.scrollbarLeft,i.marginRight=-n.scrollbarRight),this.isHScrollbarsClipped&&(i.marginBottom=-n.scrollbarBottom),t.applyStyle(r,i),!this.isHScrollbarsClipped&&"hidden"!==e.overflowX||!this.isVScrollbarsClipped&&"hidden"!==e.overflowY||n.scrollbarLeft||n.scrollbarRight||n.scrollbarBottom?r.classList.remove("fc-no-scrollbars"):r.classList.add("fc-no-scrollbars")},e.prototype.setHeight=function(e){this.enhancedScroll.setHeight(e)},e.prototype.getScrollbarWidths=function(){var e=this.enhancedScroll.getScrollbarWidths();return this.isVScrollbarsClipped&&(e.left=0,e.right=0),this.isHScrollbarsClipped&&(e.bottom=0),e},e}(),d=function(){function e(e,t){this.axis=e,this.scrollers=t;for(var r=0,n=this.scrollers;r<n.length;r++){var i=n[r];this.initScroller(i)}}return e.prototype.initScroller=function(e){var t=this,r=e.enhancedScroll,n=function(){t.assignMasterScroller(e)};"wheel mousewheel DomMouseScroll MozMousePixelScroll".split(" ").forEach(function(e){r.el.addEventListener(e,n)}),r.on("scrollStart",function(){t.masterScroller||t.assignMasterScroller(e)}).on("scroll",function(){if(e===t.masterScroller)for(var n=0,i=t.scrollers;n<i.length;n++){var o=i[n];if(o!==e)switch(t.axis){case"horizontal":o.enhancedScroll.el.scrollLeft=r.el.scrollLeft;break;case"vertical":o.enhancedScroll.setScrollTop(r.getScrollTop())}}}).on("scrollEnd",function(){e===t.masterScroller&&t.unassignMasterScroller()})},e.prototype.assignMasterScroller=function(e){this.unassignMasterScroller(),this.masterScroller=e;for(var t=0,r=this.scrollers;t<r.length;t++){var n=r[t];n!==e&&n.enhancedScroll.disableTouchScroll()}},e.prototype.unassignMasterScroller=function(){if(this.masterScroller){for(var e=0,t=this.scrollers;e<t.length;e++){t[e].enhancedScroll.enableTouchScroll()}this.masterScroller=null}},e.prototype.update=function(){for(var e,t,r=this.scrollers.map(function(e){return e.getScrollbarWidths()}),n=0,i=0,o=0,l=0,s=0,a=r;s<a.length;s++)e=a[s],n=Math.max(n,e.left),i=Math.max(i,e.right),o=Math.max(o,e.top),l=Math.max(l,e.bottom);for(t=0;t<this.scrollers.length;t++){var c=this.scrollers[t];e=r[t],c.enhancedScroll.canvas.setGutters("horizontal"===this.axis?{left:n-e.left,right:i-e.right}:{top:o-e.top,bottom:l-e.bottom})}},e}(),h=function(){function e(e,t,r){this.headerScroller=new c("clipped-scroll","hidden",e),this.bodyScroller=new c("auto",r,t),this.scrollJoiner=new d("horizontal",[this.headerScroller,this.bodyScroller])}return e.prototype.destroy=function(){this.headerScroller.destroy(),this.bodyScroller.destroy()},e.prototype.setHeight=function(e,t){var r;r=t?"auto":e-this.queryHeadHeight(),this.bodyScroller.setHeight(r),this.headerScroller.updateSize(),this.bodyScroller.updateSize(),this.scrollJoiner.update()},e.prototype.queryHeadHeight=function(){return this.headerScroller.enhancedScroll.canvas.contentEl.getBoundingClientRect().height},e}(),u=function(e){function r(r,n){var i=e.call(this,r)||this;return n.appendChild(i.tableEl=t.createElement("table",{className:i.theme.getClass("tableGrid")})),i}return n(r,e),r.prototype.destroy=function(){t.removeElement(this.tableEl),e.prototype.destroy.call(this)},r.prototype.render=function(e){this.renderDates(e.tDateProfile)},r.prototype.renderDates=function(e){for(var r=this.dateEnv,n=this.theme,i=e.cellRows,o=i[i.length-1],l=t.asRoughMs(e.labelInterval)>t.asRoughMs(e.slotDuration),s=t.isSingleDay(e.slotDuration),a="<colgroup>",c=e.slotCnt-1;c>=0;c--)a+="<col/>";a+="</colgroup>",a+="<tbody>";for(var d=0,h=i;d<h.length;d++){var u=h[d];a+="<tr"+(l&&u===o?' class="fc-chrono"':"")+">";for(var p=0,f=u;p<f.length;p++){var g=f[p],m=[n.getClass("widgetHeader")];g.isWeekStart&&m.push("fc-em-cell"),s&&(m=m.concat(t.getDayClasses(g.date,this.props.dateProfile,this.context,!0))),a+='<th class="'+m.join(" ")+'" data-date="'+r.formatIso(g.date,{omitTime:!e.isTimeScale,omitTimeZoneOffset:!0})+'"'+(g.colspan>1?' colspan="'+g.colspan+'"':"")+'><div class="fc-cell-content">'+g.spanHtml+"</div></th>"}a+="</tr>"}a+="</tbody>",this.tableEl.innerHTML=a,this.slatColEls=t.findElements(this.tableEl,"col"),this.innerEls=t.findElements(this.tableEl.querySelector("tr:last-child"),"th .fc-cell-text"),t.findElements(this.tableEl.querySelectorAll("tr:not(:last-child)"),"th .fc-cell-text").forEach(function(e){e.classList.add("fc-sticky")})},r}(t.Component),p=function(e){function r(r,n){var i=e.call(this,r)||this;return n.appendChild(i.el=t.createElement("div",{className:"fc-slats"})),i}return n(r,e),r.prototype.destroy=function(){t.removeElement(this.el),e.prototype.destroy.call(this)},r.prototype.render=function(e){this.renderDates(e.tDateProfile)},r.prototype.renderDates=function(e){for(var r=this.theme,n=this.view,i=this.dateEnv,o=e.slotDates,l=e.isWeekStarts,s='<table class="'+r.getClass("tableGrid")+'"><colgroup>',a=0;a<o.length;a++)s+="<col/>";s+="</colgroup>",s+="<tbody><tr>";for(a=0;a<o.length;a++)s+=this.slatCellHtml(o[a],l[a],e);s+="</tr></tbody></table>",this.el.innerHTML=s,this.slatColEls=t.findElements(this.el,"col"),this.slatEls=t.findElements(this.el,"td");for(a=0;a<o.length;a++)n.publiclyTrigger("dayRender",[{date:i.toDate(o[a]),el:this.slatEls[a],view:n}]);this.outerCoordCache=new t.PositionCache(this.el,this.slatEls,!0,!1),this.innerCoordCache=new t.PositionCache(this.el,t.findChildren(this.slatEls,"div"),!0,!1)},r.prototype.slatCellHtml=function(e,r,n){var i,o=this.theme,l=this.dateEnv;return n.isTimeScale?(i=[]).push(t.isInt(l.countDurationsBetween(n.normalizedRange.start,e,n.labelInterval))?"fc-major":"fc-minor"):(i=t.getDayClasses(e,this.props.dateProfile,this.context)).push("fc-day"),i.unshift(o.getClass("widgetContent")),r&&i.push("fc-em-cell"),'<td class="'+i.join(" ")+'" data-date="'+l.formatIso(e,{omitTime:!n.isTimeScale,omitTimeZoneOffset:!0})+'"><div></div></td>'},r.prototype.updateSize=function(){this.outerCoordCache.build(),this.innerCoordCache.build()},r.prototype.positionToHit=function(e){var r=this.outerCoordCache,n=this.props.tDateProfile,i=r.leftToIndex(e);if(null!=i){var o=r.getWidth(i),l=this.isRtl?(r.rights[i]-e)/o:(e-r.lefts[i])/o,s=Math.floor(l*n.snapsPerSlot),a=this.dateEnv.add(n.slotDates[i],t.multiplyDuration(n.snapDuration,s));return{dateSpan:{range:{start:a,end:this.dateEnv.add(a,n.snapDuration)},allDay:!this.props.tDateProfile.isTimeScale},dayEl:this.slatColEls[i],left:r.lefts[i],right:r.rights[i]}}return null},r}(t.Component),f=18,g=6,m=200;t.config.MAX_TIMELINE_SLOTS=1e3;var v=[{years:1},{months:1},{days:1},{hours:1},{minutes:30},{minutes:15},{minutes:10},{minutes:5},{minutes:1},{seconds:30},{seconds:15},{seconds:10},{seconds:5},{seconds:1},{milliseconds:500},{milliseconds:100},{milliseconds:10},{milliseconds:1}];function y(e,r){var n=r.dateEnv,i={labelInterval:E(r,"slotLabelInterval"),slotDuration:E(r,"slotDuration")};!function(e,r,n){var i=r.currentRange;if(e.labelInterval){var o=n.countDurationsBetween(i.start,i.end,e.labelInterval);o>t.config.MAX_TIMELINE_SLOTS&&(console.warn("slotLabelInterval results in too many cells"),e.labelInterval=null)}if(e.slotDuration){var l=n.countDurationsBetween(i.start,i.end,e.slotDuration);l>t.config.MAX_TIMELINE_SLOTS&&(console.warn("slotDuration results in too many cells"),e.slotDuration=null)}if(e.labelInterval&&e.slotDuration){var s=t.wholeDivideDurations(e.labelInterval,e.slotDuration);(null===s||s<1)&&(console.warn("slotLabelInterval must be a multiple of slotDuration"),e.slotDuration=null)}}(i,e,n),D(i,e,n),function(e,r,n){var i=r.currentRange,o=e.slotDuration;if(!o){for(var l=D(e,r,n),s=0,a=v;s<a.length;s++){var c=a[s],d=t.createDuration(c),h=t.wholeDivideDurations(l,d);if(null!==h&&h>1&&h<=g){o=d;break}}if(o){var u=n.countDurationsBetween(i.start,i.end,o);u>m&&(o=null)}o||(o=l),e.slotDuration=o}}(i,e,n);var o=r.opt("slotLabelFormat"),l=Array.isArray(o)?o:null!=o?[o]:function(e,r,n,i){var o,l,s=e.labelInterval,a=t.greatestDurationDenominator(s).unit,c=i.opt("weekNumbers"),d=o=l=null;"week"!==a||c||(a="day");switch(a){case"year":d={year:"numeric"};break;case"month":w("years",r,n)>1&&(d={year:"numeric"}),o={month:"short"};break;case"week":w("years",r,n)>1&&(d={year:"numeric"}),o={week:"narrow"};break;case"day":w("years",r,n)>1?d={year:"numeric",month:"long"}:w("months",r,n)>1&&(d={month:"long"}),c&&(o={week:"short"}),l={weekday:"narrow",day:"numeric"};break;case"hour":c&&(d={week:"short"}),w("days",r,n)>1&&(o={weekday:"short",day:"numeric",month:"numeric",omitCommas:!0}),l={hour:"numeric",minute:"2-digit",omitZeroMinute:!0,meridiem:"short"};break;case"minute":t.asRoughMinutes(s)/60>=g?(d={hour:"numeric",meridiem:"short"},o=function(e){return":"+t.padStart(e.date.minute,2)}):d={hour:"numeric",minute:"numeric",meridiem:"short"};break;case"second":t.asRoughSeconds(s)/60>=g?(d={hour:"numeric",minute:"2-digit",meridiem:"lowercase"},o=function(e){return":"+t.padStart(e.date.second,2)}):d={hour:"numeric",minute:"2-digit",second:"2-digit",meridiem:"lowercase"};break;case"millisecond":d={hour:"numeric",minute:"2-digit",second:"2-digit",meridiem:"lowercase"},o=function(e){return"."+t.padStart(e.millisecond,3)}}return[].concat(d||[],o||[],l||[])}(i,e,n,r);i.headerFormats=l.map(function(e){return t.createFormatter(e)}),i.isTimeScale=Boolean(i.slotDuration.milliseconds);var s=null;if(!i.isTimeScale){var a=t.greatestDurationDenominator(i.slotDuration).unit;/year|month|week/.test(a)&&(s=a)}i.largeUnit=s,i.emphasizeWeeks=t.isSingleDay(i.slotDuration)&&w("weeks",e,n)>=2&&!r.opt("businessHours");var c,d,h=r.opt("snapDuration");h&&(c=t.createDuration(h),d=t.wholeDivideDurations(i.slotDuration,c)),null==d&&(c=i.slotDuration,d=1),i.snapDuration=c,i.snapsPerSlot=d;var u=t.asRoughMs(e.maxTime)-t.asRoughMs(e.minTime),p=S(e.renderRange.start,i,n),f=S(e.renderRange.end,i,n);i.isTimeScale&&(p=n.add(p,e.minTime),f=n.add(t.addDays(f,-1),e.maxTime)),i.timeWindowMs=u,i.normalizedRange={start:p,end:f};for(var y=[],T=p;T<f;)b(T,i,e,r)&&y.push(T),T=n.add(T,i.slotDuration);i.slotDates=y;var R=-1,x=0,M=[],z=[];for(T=p;T<f;)b(T,i,e,r)?(R++,M.push(R),z.push(x)):M.push(R+.5),T=n.add(T,i.snapDuration),x++;return i.snapDiffToIndex=M,i.snapIndexToDiff=z,i.snapCnt=R+1,i.slotCnt=i.snapCnt/i.snapsPerSlot,i.isWeekStarts=function(e,t){for(var r=e.slotDates,n=e.emphasizeWeeks,i=null,o=[],l=0,s=r;l<s.length;l++){var a=s[l],c=t.computeWeekNumber(a),d=n&&null!==i&&i!==c;i=c,o.push(d)}return o}(i,n),i.cellRows=function(e,r,n){for(var i=e.slotDates,o=e.headerFormats,l=o.map(function(e){return[]}),s=o.map(function(e){return e.getLargestUnit?e.getLargestUnit():null}),a=0;a<i.length;a++)for(var c=i[a],d=e.isWeekStarts[a],h=0;h<o.length;h++){var u=o[h],p=l[h],f=p[p.length-1],g=o.length>1&&h<o.length-1,m=null;if(g){var v=r.format(c,u);f&&f.text===v?f.colspan+=1:m=C(c,v,s[h],n)}else if(!f||t.isInt(r.countDurationsBetween(e.normalizedRange.start,c,e.labelInterval))){var v=r.format(c,u);m=C(c,v,s[h],n)}else f.colspan+=1;m&&(m.weekStart=d,p.push(m))}return l}(i,n,r),i}function S(e,r,n){var i=e;return r.isTimeScale||(i=t.startOfDay(i),r.largeUnit&&(i=n.startOf(i,r.largeUnit))),i}function b(e,r,n,i){if(i.dateProfileGenerator.isHiddenDay(e))return!1;if(r.isTimeScale){var o=t.startOfDay(e),l=e.valueOf()-o.valueOf()-t.asRoughMs(n.minTime);return(l=(l%864e5+864e5)%864e5)<r.timeWindowMs}return!0}function E(e,r){var n=e.opt(r);if(null!=n)return t.createDuration(n)}function D(e,r,n){var i=r.currentRange,o=e.labelInterval;if(!o){var l=void 0;if(e.slotDuration){for(var s=0,a=v;s<a.length;s++){l=a[s];var c=t.createDuration(l),d=t.wholeDivideDurations(c,e.slotDuration);if(null!==d&&d<=g){o=c;break}}o||(o=e.slotDuration)}else for(var h=0,u=v;h<u.length;h++){if(l=u[h],o=t.createDuration(l),n.countDurationsBetween(i.start,i.end,o)>=f)break}e.labelInterval=o}return o}function w(e,r,n){var i=r.currentRange,o=null;return"years"===e?o=n.diffWholeYears(i.start,i.end):"months"===e?o=n.diffWholeMonths(i.start,i.end):"weeks"===e?o=n.diffWholeMonths(i.start,i.end):"days"===e&&(o=t.diffWholeDays(i.start,i.end)),o||0}function C(e,r,n,i){return{text:r,spanHtml:t.buildGotoAnchorHtml(i,{date:e,type:n,forceOff:!n},{class:"fc-cell-text"},t.htmlEscape(r)),date:e,colspan:1,isWeekStart:!1}}var T,R=function(){function e(e,t){this.headParent=e,this.bodyParent=t}return e.prototype.render=function(e,r){var n=r?{right:-e}:{left:e};this.headParent.appendChild(this.arrowEl=t.createElement("div",{className:"fc-now-indicator fc-now-indicator-arrow",style:n})),this.bodyParent.appendChild(this.lineEl=t.createElement("div",{className:"fc-now-indicator fc-now-indicator-line",style:n}))},e.prototype.unrender=function(){this.arrowEl&&t.removeElement(this.arrowEl),this.lineEl&&t.removeElement(this.lineEl)},e}(),x=-1!==(T=t.htmlToElement('<div style="position:-webkit-sticky;position:sticky"></div>').style.position).indexOf("sticky")?T:null,M=/Edge/.test(navigator.userAgent),z="-webkit-sticky"===x,k="fc-sticky",P=function(){function e(e,r,n){var i=this;this.usingRelative=null,this.updateSize=function(){var e=Array.prototype.slice.call(i.scroller.canvas.el.querySelectorAll("."+k)),r=i.queryElGeoms(e),n=i.scroller.el.clientWidth;i.usingRelative?function(e,r,n){e.forEach(function(e,i){var o=r[i].naturalBound;t.applyStyle(e,{position:"relative",left:n[i].left-o.left,top:n[i].top-o.top})})}(e,r,i.computeElDestinations(r,n)):function(e,r,n){e.forEach(function(e,i){var o=0;"center"===r[i].intendedTextAlign&&(o=(n-r[i].elWidth)/2,"center"===r[i].computedTextAlign&&(e.setAttribute("data-sticky-center",""),e.parentNode.style.textAlign="left")),t.applyStyle(e,{position:x,left:o,right:0,top:0})})}(e,r,n)},this.scroller=e,this.usingRelative=!x||M&&r||(M||z)&&n,this.usingRelative&&e.on("scrollEnd",this.updateSize)}return e.prototype.destroy=function(){this.scroller.off("scrollEnd",this.updateSize)},e.prototype.queryElGeoms=function(e){for(var r=this.scroller.canvas.el.getBoundingClientRect(),n=[],i=0,o=e;i<o.length;i++){var l=o[i],s=t.translateRect(l.parentNode.getBoundingClientRect(),-r.left,-r.top),a=l.getBoundingClientRect(),c=window.getComputedStyle(l),d=window.getComputedStyle(l.parentNode).textAlign,h=d,u=null;"sticky"!==c.position&&(u=t.translateRect(a,-r.left-(parseFloat(c.left)||0),-r.top-(parseFloat(c.top)||0))),l.hasAttribute("data-sticky-center")&&(h="center"),n.push({parentBound:s,naturalBound:u,elWidth:a.width,elHeight:a.height,computedTextAlign:d,intendedTextAlign:h})}return n},e.prototype.computeElDestinations=function(e,t){var r=this.scroller.getScrollFromLeft(),n=this.scroller.getScrollTop(),i=r+t;return e.map(function(e){var t,o,l=e.elWidth,s=e.elHeight,a=e.parentBound,c=e.naturalBound;switch(e.intendedTextAlign){case"left":t=r;break;case"right":t=i-l;break;case"center":t=(r+i)/2-l/2}return t=Math.min(t,a.right-l),t=Math.max(t,a.left),o=n,o=Math.min(o,a.bottom-s),{left:t,top:o=Math.max(o,c.top)}})},e}();var I=function(e){function r(t,r,n){var i=e.call(this,t)||this,o=i.layout=new h(r,n,"auto"),l=o.headerScroller.enhancedScroll,s=o.bodyScroller.enhancedScroll;return i.headStickyScroller=new P(l,i.isRtl,!1),i.bodyStickyScroller=new P(s,i.isRtl,!1),i.header=new u(t,l.canvas.contentEl),i.slats=new p(t,s.canvas.bgEl),i.nowIndicator=new R(l.canvas.el,s.canvas.el),i}return n(r,e),r.prototype.destroy=function(){this.layout.destroy(),this.header.destroy(),this.slats.destroy(),this.nowIndicator.unrender(),this.headStickyScroller.destroy(),this.bodyStickyScroller.destroy(),e.prototype.destroy.call(this)},r.prototype.render=function(e){var t=this.tDateProfile=y(e.dateProfile,this.view);this.header.receiveProps({dateProfile:e.dateProfile,tDateProfile:t}),this.slats.receiveProps({dateProfile:e.dateProfile,tDateProfile:t})},r.prototype.getNowIndicatorUnit=function(e){var r=this.tDateProfile=y(e,this.view);if(r.isTimeScale)return t.greatestDurationDenominator(r.slotDuration).unit},r.prototype.renderNowIndicator=function(e){t.rangeContainsMarker(this.tDateProfile.normalizedRange,e)&&this.nowIndicator.render(this.dateToCoord(e),this.isRtl)},r.prototype.unrenderNowIndicator=function(){this.nowIndicator.unrender()},r.prototype.updateSize=function(e,t,r){this.applySlotWidth(this.computeSlotWidth()),this.layout.setHeight(t,r),this.slats.updateSize()},r.prototype.updateStickyScrollers=function(){this.headStickyScroller.updateSize(),this.bodyStickyScroller.updateSize()},r.prototype.computeSlotWidth=function(){var e=this.opt("slotWidth")||"";return""===e&&(e=this.computeDefaultSlotWidth(this.tDateProfile)),e},r.prototype.computeDefaultSlotWidth=function(e){var r=0;this.header.innerEls.forEach(function(e,t){r=Math.max(r,e.getBoundingClientRect().width)});var n=Math.ceil(r)+1,i=t.wholeDivideDurations(e.labelInterval,e.slotDuration),o=Math.ceil(n/i),l=window.getComputedStyle(this.header.slatColEls[0]).minWidth;return l&&(l=parseInt(l,10))&&(o=Math.max(o,l)),o},r.prototype.applySlotWidth=function(e){var t=this.layout,r=this.tDateProfile,n="",i="",o="";if(""!==e){n=(e=Math.round(e))*r.slotDates.length,i="",o=e;var l=t.bodyScroller.enhancedScroll.getClientWidth();l>n&&(i=l,n="",o=Math.floor(l/r.slotDates.length))}t.headerScroller.enhancedScroll.canvas.setWidth(n),t.headerScroller.enhancedScroll.canvas.setMinWidth(i),t.bodyScroller.enhancedScroll.canvas.setWidth(n),t.bodyScroller.enhancedScroll.canvas.setMinWidth(i),""!==o&&this.header.slatColEls.slice(0,-1).concat(this.slats.slatColEls.slice(0,-1)).forEach(function(e){e.style.width=o+"px"})},r.prototype.computeDateSnapCoverage=function(e){var r=this.dateEnv,n=this.tDateProfile,i=r.countDurationsBetween(n.normalizedRange.start,e,n.snapDuration);if(i<0)return 0;if(i>=n.snapDiffToIndex.length)return n.snapCnt;var o=Math.floor(i),l=n.snapDiffToIndex[o];return t.isInt(l)?l+=i-o:l=Math.ceil(l),l},r.prototype.dateToCoord=function(e){var t=this.tDateProfile,r=this.computeDateSnapCoverage(e)/t.snapsPerSlot,n=Math.floor(r),i=r-(n=Math.min(n,t.slotCnt-1)),o=this.slats,l=o.innerCoordCache,s=o.outerCoordCache;return this.isRtl?s.rights[n]-l.getWidth(n)*i-s.originClientRect.width:s.lefts[n]+l.getWidth(n)*i},r.prototype.rangeToCoords=function(e){return this.isRtl?{right:this.dateToCoord(e.start),left:this.dateToCoord(e.end)}:{left:this.dateToCoord(e.start),right:this.dateToCoord(e.end)}},r.prototype.computeDateScroll=function(e){var r=this.dateEnv,n=this.props.dateProfile,i=0;return n&&(i=this.dateToCoord(r.add(t.startOfDay(n.activeRange.start),e)),!this.isRtl&&i&&(i+=1)),{left:i}},r.prototype.queryDateScroll=function(){return{left:this.layout.bodyScroller.enhancedScroll.getScrollLeft()}},r.prototype.applyDateScroll=function(e){this.layout.bodyScroller.enhancedScroll.setScrollLeft(e.left||0),this.layout.headerScroller.enhancedScroll.setScrollLeft(e.left||0)},r}(t.Component),H=function(e){function r(t,r,n){var i=e.call(this,t)||this;return i.masterContainerEl=r,i.timeAxis=n,i}return n(r,e),r.prototype.renderSegHtml=function(e,r){var n=this.context.view,i=e.eventRange,o=i.def,l=i.ui,s=n.computeEventDraggable(o,l),a=e.isStart&&n.computeEventStartResizable(o,l),c=e.isEnd&&n.computeEventEndResizable(o,l),d=this.getSegClasses(e,s,a||c,r);d.unshift("fc-timeline-event","fc-h-event");var h=this.getTimeText(i);return'<a class="'+d.join(" ")+'" style="'+t.cssToStr(this.getSkinCss(l))+'"'+(o.url?' href="'+t.htmlEscape(o.url)+'"':"")+">"+(h?'<span class="fc-time-wrap"><span class="fc-time">'+t.htmlEscape(h)+"</span></span>":"")+'<span class="fc-title-wrap"><span class="fc-title fc-sticky">'+(o.title?t.htmlEscape(o.title):" ")+"</span></span>"+(a?'<div class="fc-resizer fc-start-resizer"></div>':"")+(c?'<div class="fc-resizer fc-end-resizer"></div>':"")+"</a>"},r.prototype.computeDisplayEventTime=function(){return!this.timeAxis.tDateProfile.isTimeScale},r.prototype.computeDisplayEventEnd=function(){return!1},r.prototype.computeEventTimeFormat=function(){return{hour:"numeric",minute:"2-digit",omitZeroMinute:!0,meridiem:"narrow"}},r.prototype.attachSegs=function(e,r){if(!this.el&&this.masterContainerEl&&(this.el=t.createElement("div",{className:"fc-event-container"}),r&&this.el.classList.add("fc-mirror-container"),this.masterContainerEl.appendChild(this.el)),this.el)for(var n=0,i=e;n<i.length;n++){var o=i[n];this.el.appendChild(o.el)}},r.prototype.detachSegs=function(e){for(var r=0,n=e;r<n.length;r++){var i=n[r];t.removeElement(i.el)}},r.prototype.computeSegSizes=function(e){for(var r=this.timeAxis,n=0,i=e;n<i.length;n++){var o=i[n],l=r.rangeToCoords(o);t.applyStyle(o.el,{left:o.left=l.left,right:-(o.right=l.right)})}},r.prototype.assignSegSizes=function(e){if(this.el){for(var r=0,n=e;r<n.length;r++){(s=n[r]).height=t.computeHeightAndMargins(s.el)}this.buildSegLevels(e);var i=L(e);t.applyStyleProp(this.el,"height",i);for(var o=0,l=e;o<l.length;o++){var s=l[o];t.applyStyleProp(s.el,"top",s.top)}}},r.prototype.buildSegLevels=function(e){for(var t=[],r=0,n=e=this.sortEventSegs(e);r<n.length;r++){var i=n[r];i.above=[];for(var o=0;o<t.length;){for(var l=!1,s=0,a=t[o];s<a.length;s++){var c=a[s];A(i,c)&&(i.above.push(c),l=!0)}if(!l)break;o+=1}for((t[o]||(t[o]=[])).push(i),o+=1;o<t.length;){for(var d=0,h=t[o];d<h.length;d++){var u=h[d];A(i,u)&&u.above.push(i)}o+=1}}return t},r}(t.FgEventRenderer);function L(e){for(var t=0,r=0,n=e;r<n.length;r++){var i=n[r];t=Math.max(t,W(i))}return t}function W(e){return null==e.top&&(e.top=L(e.above)),e.top+e.height}function A(e,t){return e.left<t.right&&e.right>t.left}var B=function(e){function r(t,r,n){var i=e.call(this,t)||this;return i.masterContainerEl=r,i.timeAxis=n,i}return n(r,e),r.prototype.attachSegs=function(e,r){if(r.length){var n=void 0;n="businessHours"===e?"bgevent":e.toLowerCase();var i=t.createElement("div",{className:"fc-"+n+"-container"});this.masterContainerEl.appendChild(i);for(var o=0,l=r;o<l.length;o++){var s=l[o];i.appendChild(s.el)}return[i]}},r.prototype.computeSegSizes=function(e){for(var t=this.timeAxis,r=0,n=e;r<n.length;r++){var i=n[r],o=t.rangeToCoords(i);i.left=o.left,i.right=o.right}},r.prototype.assignSegSizes=function(e){for(var r=0,n=e;r<n.length;r++){var i=n[r];t.applyStyle(i.el,{left:i.left,right:-i.right})}},r}(t.FillRenderer),O=function(e){function r(r,n,i,o){var l=e.call(this,r,i)||this;l.slicer=new N,l.renderEventDrag=t.memoizeRendering(l._renderEventDrag,l._unrenderEventDrag),l.renderEventResize=t.memoizeRendering(l._renderEventResize,l._unrenderEventResize);var s=l.fillRenderer=new B(r,i,o),a=l.eventRenderer=new H(r,n,o);return l.mirrorRenderer=new H(r,n,o),l.renderBusinessHours=t.memoizeRendering(s.renderSegs.bind(s,"businessHours"),s.unrender.bind(s,"businessHours")),l.renderDateSelection=t.memoizeRendering(s.renderSegs.bind(s,"highlight"),s.unrender.bind(s,"highlight")),l.renderBgEvents=t.memoizeRendering(s.renderSegs.bind(s,"bgEvent"),s.unrender.bind(s,"bgEvent")),l.renderFgEvents=t.memoizeRendering(a.renderSegs.bind(a),a.unrender.bind(a)),l.renderEventSelection=t.memoizeRendering(a.selectByInstanceId.bind(a),a.unselectByInstanceId.bind(a),[l.renderFgEvents]),l.timeAxis=o,l}return n(r,e),r.prototype.render=function(e){var t=this.slicer.sliceProps(e,e.dateProfile,this.timeAxis.tDateProfile.isTimeScale?null:e.nextDayThreshold,this,this.timeAxis);this.renderBusinessHours(t.businessHourSegs),this.renderDateSelection(t.dateSelectionSegs),this.renderBgEvents(t.bgEventSegs),this.renderFgEvents(t.fgEventSegs),this.renderEventSelection(t.eventSelection),this.renderEventDrag(t.eventDrag),this.renderEventResize(t.eventResize)},r.prototype.destroy=function(){e.prototype.destroy.call(this),this.renderBusinessHours.unrender(),this.renderDateSelection.unrender(),this.renderBgEvents.unrender(),this.renderFgEvents.unrender(),this.renderEventSelection.unrender(),this.renderEventDrag.unrender(),this.renderEventResize.unrender()},r.prototype._renderEventDrag=function(e){e&&(this.eventRenderer.hideByHash(e.affectedInstances),this.mirrorRenderer.renderSegs(e.segs,{isDragging:!0,sourceSeg:e.sourceSeg}))},r.prototype._unrenderEventDrag=function(e){e&&(this.eventRenderer.showByHash(e.affectedInstances),this.mirrorRenderer.unrender(e.segs,{isDragging:!0,sourceSeg:e.sourceSeg}))},r.prototype._renderEventResize=function(e){if(e){var t=e.segs.map(function(e){return o({},e)});this.eventRenderer.hideByHash(e.affectedInstances),this.fillRenderer.renderSegs("highlight",t),this.mirrorRenderer.renderSegs(e.segs,{isDragging:!0,sourceSeg:e.sourceSeg})}},r.prototype._unrenderEventResize=function(e){e&&(this.eventRenderer.showByHash(e.affectedInstances),this.fillRenderer.unrender("highlight"),this.mirrorRenderer.unrender(e.segs,{isDragging:!0,sourceSeg:e.sourceSeg}))},r.prototype.updateSize=function(e){var t=this.fillRenderer,r=this.eventRenderer,n=this.mirrorRenderer;t.computeSizes(e),r.computeSizes(e),n.computeSizes(e),t.assignSizes(e),r.assignSizes(e),n.assignSizes(e)},r}(t.DateComponent),N=function(e){function r(){return null!==e&&e.apply(this,arguments)||this}return n(r,e),r.prototype.sliceRange=function(e,r){var n=r.tDateProfile,i=r.props.dateProfile,o=function(e,r,n){if(!r.isTimeScale&&(e=t.computeVisibleDayRange(e),r.largeUnit)){var i=e;((e={start:n.startOf(e.start,r.largeUnit),end:n.startOf(e.end,r.largeUnit)}).end.valueOf()!==i.end.valueOf()||e.end<=e.start)&&(e={start:e.start,end:n.add(e.end,r.slotDuration)})}return e}(e,n,r.dateEnv),l=[];if(r.computeDateSnapCoverage(o.start)<r.computeDateSnapCoverage(o.end)){var s=t.intersectRanges(o,n.normalizedRange);s&&l.push({start:s.start,end:s.end,isStart:s.start.valueOf()===o.start.valueOf()&&b(s.start,n,i,r.view),isEnd:s.end.valueOf()===o.end.valueOf()&&b(t.addMs(s.end,-1),n,i,r.view)})}return l},r}(t.Slicer),_=function(e){function t(t,r,n,i){var o=e.call(this,t,r,n,i)||this;return o.el.classList.add("fc-timeline"),!1===o.opt("eventOverlap")&&o.el.classList.add("fc-no-overlap"),o.el.innerHTML=o.renderSkeletonHtml(),o.timeAxis=new I(o.context,o.el.querySelector("thead .fc-time-area"),o.el.querySelector("tbody .fc-time-area")),o.lane=new O(o.context,o.timeAxis.layout.bodyScroller.enhancedScroll.canvas.contentEl,o.timeAxis.layout.bodyScroller.enhancedScroll.canvas.bgEl,o.timeAxis),t.calendar.registerInteractiveComponent(o,{el:o.timeAxis.slats.el}),o}return n(t,e),t.prototype.destroy=function(){this.timeAxis.destroy(),this.lane.destroy(),e.prototype.destroy.call(this),this.calendar.unregisterInteractiveComponent(this)},t.prototype.renderSkeletonHtml=function(){var e=this.theme;return'<table class="'+e.getClass("tableGrid")+'"> <thead class="fc-head"> <tr> <td class="fc-time-area '+e.getClass("widgetHeader")+'"></td> </tr> </thead> <tbody class="fc-body"> <tr> <td class="fc-time-area '+e.getClass("widgetContent")+'"></td> </tr> </tbody> </table>'},t.prototype.render=function(t){e.prototype.render.call(this,t),this.timeAxis.receiveProps({dateProfile:t.dateProfile}),this.lane.receiveProps(o({},t,{nextDayThreshold:this.nextDayThreshold}))},t.prototype.updateSize=function(e,t,r){this.timeAxis.updateSize(e,t,r),this.lane.updateSize(e)},t.prototype.getNowIndicatorUnit=function(e){return this.timeAxis.getNowIndicatorUnit(e)},t.prototype.renderNowIndicator=function(e){this.timeAxis.renderNowIndicator(e)},t.prototype.unrenderNowIndicator=function(){this.timeAxis.unrenderNowIndicator()},t.prototype.computeDateScroll=function(e){return this.timeAxis.computeDateScroll(e)},t.prototype.applyScroll=function(t,r){e.prototype.applyScroll.call(this,t,r);var n=this.calendar;(r||n.isViewUpdated||n.isDatesUpdated||n.isEventsUpdated)&&this.timeAxis.updateStickyScrollers()},t.prototype.applyDateScroll=function(e){this.timeAxis.applyDateScroll(e)},t.prototype.queryScroll=function(){var e=this.timeAxis.layout.bodyScroller.enhancedScroll;return{top:e.getScrollTop(),left:e.getScrollLeft()}},t.prototype.buildPositionCaches=function(){this.timeAxis.slats.updateSize()},t.prototype.queryHit=function(e,t,r,n){var i=this.timeAxis.slats.positionToHit(e);if(i)return{component:this,dateSpan:i.dateSpan,rect:{left:i.left,right:i.right,top:0,bottom:n},dayEl:i.dayEl,layer:0}},t}(t.View),F=t.createPlugin({defaultView:"timelineDay",views:{timeline:{class:_,eventResizableFromStart:!0},timelineDay:{type:"timeline",duration:{days:1}},timelineWeek:{type:"timeline",duration:{weeks:1}},timelineMonth:{type:"timeline",duration:{months:1}},timelineYear:{type:"timeline",duration:{years:1}}}});e.HeaderBodyLayout=h,e.ScrollJoiner=d,e.StickyScroller=P,e.TimeAxis=I,e.TimelineLane=O,e.TimelineView=_,e.default=F,Object.defineProperty(e,"__esModule",{value:!0})}); \ No newline at end of file diff --git a/AKPlan/static/AKPlan/fullcalendar/timeline/package.json b/AKPlan/static/AKPlan/fullcalendar/timeline/package.json new file mode 100644 index 00000000..d7105eab --- /dev/null +++ b/AKPlan/static/AKPlan/fullcalendar/timeline/package.json @@ -0,0 +1,33 @@ +{ + "name": "@fullcalendar/timeline", + "version": "4.3.0", + "title": "FullCalendar Timeline Plugin", + "description": "Display events on a horizontal time axis (without resources)", + "keywords": [ + "calendar", + "event", + "full-sized" + ], + "homepage": "https://fullcalendar.io/scheduler", + "docs": "https://fullcalendar.io/docs/timeline-view-no-resources", + "bugs": "https://fullcalendar.io/reporting-bugs", + "repository": { + "type": "git", + "url": "https://github.com/fullcalendar/fullcalendar-scheduler.git", + "homepage": "https://github.com/fullcalendar/fullcalendar-scheduler" + }, + "license": "SEE LICENSE IN LICENSE.md", + "author": { + "name": "Adam Shaw", + "email": "arshaw@arshaw.com", + "url": "http://arshaw.com/" + }, + "copyright": "2019 Adam Shaw", + "peerDependencies": { + "@fullcalendar/core": "~4.3.0" + }, + "main": "main.js", + "module": "main.esm.js", + "unpkg": "main.min.js", + "types": "main.d.ts" +} -- GitLab From 87ee2d0fe6e27f6936491a29cd48ce96abc77669 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@cs.tu-darmstadt.de> Date: Sun, 1 Mar 2020 18:22:14 +0100 Subject: [PATCH 04/15] Add calendar view for slots to AK detail page --- AKPlan/templates/AKPlan/plan_akslot.html | 62 +++++++++++++++++++ .../templates/AKSubmission/ak_detail.html | 12 ++++ 2 files changed, 74 insertions(+) create mode 100644 AKPlan/templates/AKPlan/plan_akslot.html diff --git a/AKPlan/templates/AKPlan/plan_akslot.html b/AKPlan/templates/AKPlan/plan_akslot.html new file mode 100644 index 00000000..f8702036 --- /dev/null +++ b/AKPlan/templates/AKPlan/plan_akslot.html @@ -0,0 +1,62 @@ +{% load static %} +{% load tz %} +{% load i18n %} +{% get_current_language as LANGUAGE_CODE %} + +<link href='{% static 'AKPlan/fullcalendar/core/main.min.css' %}' rel='stylesheet' /> +<link href='{% static 'AKPlan/fullcalendar/daygrid/main.min.css' %}' rel='stylesheet' /> +<link href='{% static 'AKPlan/fullcalendar/timegrid/main.min.css' %}' rel='stylesheet' /> + +<script src='{% static 'AKPlan/fullcalendar/core/main.min.js' %}'></script> +{% with 'AKPlan/fullcalendar/core/locales/'|add:LANGUAGE_CODE|add:'.js' as locale_file %} +<script src="{% static locale_file %}"></script> +{% endwith %} +<script src='{% static 'AKPlan/fullcalendar/daygrid/main.min.js' %}'></script> +<script src='{% static 'AKPlan/fullcalendar/timegrid/main.min.js' %}'></script> +<script src='{% static 'AKPlan/fullcalendar/bootstrap/main.min.js' %}'></script> + +<script> + +document.addEventListener('DOMContentLoaded', function() { + var calendarEl = document.getElementById('akSlotCalendar'); + + var calendar = new FullCalendar.Calendar(calendarEl, { + plugins: [ 'timeGrid', 'bootstrap' ], + // Adapt to timezone of the connected event + timeZone: '{{ ak.event.timezone }}', + defaultView: 'timeGrid', + // Adapt to user selected loclae + locale: '{{ LANGUAGE_CODE }}', + // No header, not buttons + header: { + left: '', + center: '', + right: '' + }, + aspectRatio: 2.5, + themeSystem: 'bootstrap', + // Only show calendar view for the dates of the connected event + visibleRange: { + start: '{{ ak.event.start | timezone:ak.event.timezone | date:"Y-m-d H:i:s" }}', + end: '{{ ak.event.end | timezone:ak.event.timezone | date:"Y-m-d H:i:s"}}', + }, + allDaySlot: false, + nowIndicator: true, + eventTextColor: '#fff', + eventColor: '#127ba3', + // Create entries for all scheduled slots + events: [ + {% for slot in ak.akslot_set.all %} + {% if slot.start %} + {'title': '{{ slot.room }}', + 'start': '{{ slot.start | timezone:ak.event.timezone | date:"Y-m-d H:i:s" }}', + 'end': '{{ slot.end | timezone:ak.event.timezone | date:"Y-m-d H:i:s" }}'}, + {% endif %} + {% endfor %} + ] + }); + + calendar.render(); +}); + +</script> diff --git a/AKSubmission/templates/AKSubmission/ak_detail.html b/AKSubmission/templates/AKSubmission/ak_detail.html index b8e1c830..ddaaa60b 100644 --- a/AKSubmission/templates/AKSubmission/ak_detail.html +++ b/AKSubmission/templates/AKSubmission/ak_detail.html @@ -4,6 +4,8 @@ {% load fontawesome %} {% load tags_AKSubmission %} +{% load tags_AKModel %} + {% block title %}{% trans "AKs" %}: {{ ak.event.name }} - {% trans "AK" %}: {{ ak.name }}{% endblock %} @@ -14,6 +16,12 @@ <li class="breadcrumb-item active">{{ ak.name }}</li> {% endblock %} +{% if 'AKPlan'|check_app_installed %} + {% block imports %} + {% include "AKPlan/plan_akslot.html" %} + {% endblock %} +{% endif %} + {% block content %} {% include "AKSubmission/messages.html" %} @@ -60,6 +68,10 @@ <p style="margin-top: 30px;margin-bottom: 30px;">{{ ak.description }}</p> + {% if 'AKPlan'|check_app_installed %} + <div id='akSlotCalendar' style="margin-bottom: 50px;"></div> + {% endif %} + <table class="table"> <thead> -- GitLab From ff119c0d8df5c7f050befd3c7e297900c182a700 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@cs.tu-darmstadt.de> Date: Mon, 2 Mar 2020 02:19:56 +0100 Subject: [PATCH 05/15] Add basic schedule views (desktop/mobile and screen/projector) Add views Add templates Add urls Add translations Add three corresponding settings to central settings file Minor: Fix typo in plan_akslot --- AKPlan/locale/de_DE/LC_MESSAGES/django.po | 54 ++++++++ AKPlan/templates/AKPlan/plan_akslot.html | 2 +- AKPlan/templates/AKPlan/plan_index.html | 147 ++++++++++++++++++++++ AKPlan/templates/AKPlan/plan_screen.html | 116 +++++++++++++++++ AKPlan/templates/AKPlan/slots_table.html | 14 +++ AKPlan/urls.py | 14 +++ AKPlan/views.py | 69 +++++++++- AKPlanning/settings.py | 9 +- 8 files changed, 422 insertions(+), 3 deletions(-) create mode 100644 AKPlan/locale/de_DE/LC_MESSAGES/django.po create mode 100644 AKPlan/templates/AKPlan/plan_index.html create mode 100644 AKPlan/templates/AKPlan/plan_screen.html create mode 100644 AKPlan/templates/AKPlan/slots_table.html create mode 100644 AKPlan/urls.py diff --git a/AKPlan/locale/de_DE/LC_MESSAGES/django.po b/AKPlan/locale/de_DE/LC_MESSAGES/django.po new file mode 100644 index 00000000..fbb174f5 --- /dev/null +++ b/AKPlan/locale/de_DE/LC_MESSAGES/django.po @@ -0,0 +1,54 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-03-02 01:08+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: templates/AKPlan/plan_index.html:47 +msgid "Day" +msgstr "Tag" + +#: templates/AKPlan/plan_index.html:57 +msgid "Event" +msgstr "Veranstaltung" + +#: templates/AKPlan/plan_index.html:66 templates/AKPlan/plan_screen.html:64 +msgid "Room" +msgstr "Raum" + +#: templates/AKPlan/plan_index.html:106 +msgid "AK Plan" +msgstr "AK-Plan" + +#: templates/AKPlan/plan_index.html:112 +msgid "screen view" +msgstr "Anzeigeansicht" + +#: templates/AKPlan/plan_index.html:120 templates/AKPlan/plan_screen.html:99 +msgid "Current AKs" +msgstr "Aktuelle AKs" + +#: templates/AKPlan/plan_index.html:127 templates/AKPlan/plan_screen.html:104 +msgid "Next AKs" +msgstr "Nächste AKs" + +#: templates/AKPlan/plan_index.html:144 +msgid "Write to organizers of this event for questions and comments" +msgstr "Fragen oder Kommentare? Schreib den Orgas dieses Events eine Mail" + +#: templates/AKPlan/slots_table.html:12 +msgid "No AKs" +msgstr "Keine AKs" diff --git a/AKPlan/templates/AKPlan/plan_akslot.html b/AKPlan/templates/AKPlan/plan_akslot.html index f8702036..70514a63 100644 --- a/AKPlan/templates/AKPlan/plan_akslot.html +++ b/AKPlan/templates/AKPlan/plan_akslot.html @@ -25,7 +25,7 @@ document.addEventListener('DOMContentLoaded', function() { // Adapt to timezone of the connected event timeZone: '{{ ak.event.timezone }}', defaultView: 'timeGrid', - // Adapt to user selected loclae + // Adapt to user selected locale locale: '{{ LANGUAGE_CODE }}', // No header, not buttons header: { diff --git a/AKPlan/templates/AKPlan/plan_index.html b/AKPlan/templates/AKPlan/plan_index.html new file mode 100644 index 00000000..0559a096 --- /dev/null +++ b/AKPlan/templates/AKPlan/plan_index.html @@ -0,0 +1,147 @@ +{% extends "base.html" %} + +{% load fontawesome %} +{% load i18n %} +{% load tags_AKModel %} +{% load static %} +{% load tz %} + + +{% block imports %} + {% get_current_language as LANGUAGE_CODE %} + + <link href='{% static 'AKPlan/fullcalendar/core/main.css' %}' rel='stylesheet' /> + <link href='{% static 'AKPlan/fullcalendar/timeline/main.css' %}' rel='stylesheet' /> + <link href='{% static 'AKPlan/fullcalendar/resource-timeline/main.css' %}' rel='stylesheet' /> + <link href='{% static 'AKPlan/fullcalendar/resource-timeline/main.min.css' %}' rel='stylesheet' /> + + <script src='{% static 'AKPlan/fullcalendar/core/main.js' %}'></script> + {% with 'AKPlan/fullcalendar/core/locales/'|add:LANGUAGE_CODE|add:'.js' as locale_file %} + <script src="{% static locale_file %}"></script> + {% endwith %} + <script src='{% static 'AKPlan/fullcalendar/timeline/main.js' %}'></script> + <script src='{% static 'AKPlan/fullcalendar/resource-common/main.js' %}'></script> + <script src='{% static 'AKPlan/fullcalendar/resource-timeline/main.js' %}'></script> + <script src='{% static 'AKPlan/fullcalendar/bootstrap/main.js' %}'></script> + + <script> + document.addEventListener('DOMContentLoaded', function() { + var planEl = document.getElementById('planCalendar'); + + var plan = new FullCalendar.Calendar(planEl, { + plugins: ['resourceTimeline', 'bootstrap'], + timeZone: '{{ event.timezone }}', + header: { + left: 'today prev,next', + center: 'title', + right: 'resourceTimelineDay,resourceTimelineEvent' + }, + aspectRatio: 2, + themeSystem: 'bootstrap', + // Adapt to user selected locale + locale: '{{ LANGUAGE_CODE }}', + defaultView: 'resourceTimelineEvent', + views: { + resourceTimelineDay: { + type: 'resourceTimeline', + buttonText: '{% trans "Day" %}', + slotDuration: '01:00', + scrollTime: '08:00', + }, + resourceTimelineEvent: { + type: 'resourceTimeline', + visibleRange: { + start: '{{ event.start | timezone:event.timezone | date:"Y-m-d H:i:s" }}', + end: '{{ event.end | timezone:event.timezone | date:"Y-m-d H:i:s"}}', + }, + buttonText: '{% trans "Event" %}', + } + }, + editable: false, + allDaySlot: false, + nowIndicator: true, + eventTextColor: '#fff', + eventColor: '#127ba3', + resourceAreaWidth: '15%', + resourceLabelText: '{% trans "Room" %}', + resources: [ + {% for room in rooms %} + { + 'id': '{{ room.title }}', + 'title': '{{ room.title }}' + }, + {% endfor %} + ], + events: [ + {% for slot in akslots %} + {% if slot.room and slot.start %} + { + 'title': '{{ slot.ak.name }}', + 'start': '{{ slot.start | timezone:event.timezone | date:"Y-m-d H:i:s" }}', + 'end': '{{ slot.end | timezone:event.timezone | date:"Y-m-d H:i:s" }}', + 'resourceId': '{{ slot.room.title }}', + }, + {% endif %} + {% endfor %} + ], + schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source', + }); + + plan.render(); + }); + </script> +{% endblock imports %} + + +{% block breadcrumbs %} + <li class="breadcrumb-item"> + {% if 'AKDashboard'|check_app_installed %} + <a href="{% url 'dashboard:dashboard' %}">AKPlanning</a> + {% else %} + AKPlanning + {% endif %} +</li> +<li class="breadcrumb-item">{{ event.slug }}</li> + <li class="breadcrumb-item"><a + href="{% url 'plan:plan_overview' event_slug=event.slug %}">{% trans "AK Plan" %}</a></li> +{% endblock %} + + +{% block content %} + <div class="float-right"> + <a href="{% url 'plan:plan_screen' event_slug=event.slug %}" class="btn btn-success">{% fontawesome_icon 'desktop' %} {% trans "screen view" %}</a> + </div> + + <h1>Plan: {{ event }}</h1> + + {% timezone event.timezone %} + <div class="row" style="margin-top:30px;"> + <div class="col-md-6"> + <h2><a name="currentAKs">{% trans "Current AKs" %}:</a></h2> + {% with akslots_now as slots %} + {% include "AKPlan/slots_table.html" %} + {% endwith %} + </div> + + <div class="col-md-6"> + <h2><a name="currentAKs">{% trans "Next AKs" %}:</a></h2> + {% with akslots_next as slots %} + {% include "AKPlan/slots_table.html" %} + {% endwith %} + </div> + + <div class="col-md-12"> + <div id="planCalendar" style="margin-top:30px;"></div> + </div> + </div> + {% endtimezone %} +{% endblock %} + + +{% block footer_custom %} + {% if event.contact_email %} + <h4> + <a href="mailto:{{ event.contact_email }}">{% fontawesome_icon "envelope" %} {% trans "Write to organizers of this event for questions and comments" %}</a> + </h4> + {% endif %} +{% endblock %} diff --git a/AKPlan/templates/AKPlan/plan_screen.html b/AKPlan/templates/AKPlan/plan_screen.html new file mode 100644 index 00000000..8d21d59b --- /dev/null +++ b/AKPlan/templates/AKPlan/plan_screen.html @@ -0,0 +1,116 @@ +{% load static %} +{% load i18n %} +{% load bootstrap4 %} +{% load fontawesome %} +{% load tags_AKModel %} +{% load tz %} + + +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>{% block title %}AK Planning{% endblock %}</title> + + {# Load Bootstrap CSS and JavaScript as well as font awesome #} + {% bootstrap_css %} + {% bootstrap_javascript jquery='slim' %} + {% fontawesome_stylesheet %} + + <link rel="stylesheet" href="{% static 'common/css/custom.css' %}"> + + {% get_current_language as LANGUAGE_CODE %} + + <link href='{% static 'AKPlan/fullcalendar/core/main.css' %}' rel='stylesheet' /> + <link href='{% static 'AKPlan/fullcalendar/timeline/main.css' %}' rel='stylesheet' /> + <link href='{% static 'AKPlan/fullcalendar/resource-timeline/main.css' %}' rel='stylesheet' /> + <link href='{% static 'AKPlan/fullcalendar/resource-timeline/main.min.css' %}' rel='stylesheet' /> + + <script src='{% static 'AKPlan/fullcalendar/core/main.js' %}'></script> + {% with 'AKPlan/fullcalendar/core/locales/'|add:LANGUAGE_CODE|add:'.js' as locale_file %} + <script src="{% static locale_file %}"></script> + {% endwith %} + <script src='{% static 'AKPlan/fullcalendar/timeline/main.js' %}'></script> + <script src='{% static 'AKPlan/fullcalendar/resource-common/main.js' %}'></script> + <script src='{% static 'AKPlan/fullcalendar/resource-timeline/main.js' %}'></script> + <script src='{% static 'AKPlan/fullcalendar/bootstrap/main.js' %}'></script> + + <script> + document.addEventListener('DOMContentLoaded', function() { + var planEl = document.getElementById('planCalendar'); + + var plan = new FullCalendar.Calendar(planEl, { + plugins: [ 'resourceTimeline', 'bootstrap'], + timeZone: '{{ event.timezone }}', + header: false, + themeSystem: 'bootstrap', + // Adapt to user selected locale + locale: '{{ LANGUAGE_CODE }}', + type: 'resourceTimeline', + slotDuration: '01:00', + defaultView: 'resourceTimeline', + visibleRange: { + start: '{{ start | timezone:event.timezone | date:"Y-m-d H:i:s" }}', + end: '{{ end | timezone:event.timezone | date:"Y-m-d H:i:s"}}', + }, + scrollTime: '{{ start | timezone:event.timezone | date:"H:i:s" }}', + editable: false, + allDaySlot: false, + nowIndicator: true, + eventTextColor: '#fff', + eventColor: '#127ba3', + height: 'parent', + resourceAreaWidth: '15%', + resourceLabelText: '{% trans "Room" %}', + resources: [ + {% for room in rooms %} + { + 'id': '{{ room.title }}', + 'title': '{{ room.title }}' + }, + {% endfor %} + ], + events: [ + {% for slot in akslots %} + {% if slot.room and slot.start %} + { + 'title': '{{ slot.ak.name }}', + 'start': '{{ slot.start | timezone:event.timezone | date:"Y-m-d H:i:s" }}', + 'end': '{{ slot.end | timezone:event.timezone | date:"Y-m-d H:i:s" }}', + 'resourceId': '{{ slot.room.title }}', + }, + {% endif %} + {% endfor %} + ], + schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source', + }); + + plan.render(); + }); + </script> + +</head> +<body> + {% timezone event.timezone %} + <div class="row" style="height:100vh;margin:0;padding:1vh;"> + <div class="col-md-3"> + <h1>Plan: {{ event }}</h1> + + <h2><a name="currentAKs">{% trans "Current AKs" %}:</a></h2> + {% with akslots_now as slots %} + {% include "AKPlan/slots_table.html" %} + {% endwith %} + + <h2><a name="currentAKs">{% trans "Next AKs" %}:</a></h2> + {% with akslots_next as slots %} + {% include "AKPlan/slots_table.html" %} + {% endwith %} + </div> + <div class="col-md-9" style="height:98vh;"> + <div id="planCalendar"></div> + </div> + </div> + {% endtimezone %} + +</body> +</html> diff --git a/AKPlan/templates/AKPlan/slots_table.html b/AKPlan/templates/AKPlan/slots_table.html new file mode 100644 index 00000000..cb246dbd --- /dev/null +++ b/AKPlan/templates/AKPlan/slots_table.html @@ -0,0 +1,14 @@ +{% load i18n %} + + +<table class="table table-striped"> + {% for akslot in slots %} + <tr> + <td><b><a href="{% url 'submit:ak_detail' event_slug=event.slug pk=akslot.ak.pk %}">{{ akslot.ak.name }}</a></b></td> + <td>{{ akslot.start | time:"H:i" }} - {{ akslot.end | time:"H:i" }}</td> + <td>{{ akslot.room }}</td> + </tr> + {% empty %} + {% trans "No AKs" %} + {% endfor %} +</table> diff --git a/AKPlan/urls.py b/AKPlan/urls.py new file mode 100644 index 00000000..dacc519e --- /dev/null +++ b/AKPlan/urls.py @@ -0,0 +1,14 @@ +from django.urls import path, include +from . import views + +app_name = "plan" + +urlpatterns = [ + path( + '<slug:event_slug>/plan/', + include([ + path('', views.PlanIndexView.as_view(), name='plan_overview'), + path('screen/', views.PlanScreenView.as_view(), name='plan_screen'), + ]) + ), +] diff --git a/AKPlan/views.py b/AKPlan/views.py index 60f00ef0..d82ffe43 100644 --- a/AKPlan/views.py +++ b/AKPlan/views.py @@ -1 +1,68 @@ -# Create your views here. +from datetime import timedelta + +from django.conf import settings +from django.utils.datetime_safe import datetime +from django.views.generic import ListView + +from AKModel.models import AKSlot +from AKModel.views import FilterByEventSlugMixin + + +class PlanIndexView(FilterByEventSlugMixin, ListView): + model = AKSlot + template_name = "AKPlan/plan_index.html" + context_object_name = "akslots" + ordering = "start" + + def get_queryset(self): + # Ignore slots not scheduled yet + return super().get_queryset().filter(start__isnull=False) + + def get_context_data(self, *, object_list=None, **kwargs): + context = super().get_context_data(object_list=object_list, **kwargs) + + context["event"] = self.event + + current_timestamp = datetime.now().astimezone(self.event.timezone) + + context["akslots_now"] = [] + context["akslots_next"] = [] + rooms = set() + + # Get list of current and next slots + for akslot in context["akslots"]: + # Construct a list of all rooms used by these slots on the fly + if akslot.room is not None: + rooms.add(akslot.room) + + # Recent AKs: Started but not ended yet + if akslot.start <= current_timestamp <= akslot.end: + context["akslots_now"].append(akslot) + # Next AKs: Not started yet, list will be filled in order until threshold is reached + elif akslot.start > current_timestamp: + if len(context["akslots_next"]) < settings.PLAN_MAX_NEXT_AKS: + context["akslots_next"].append(akslot) + + # Sort list of rooms by title + context["rooms"] = sorted(rooms, key=lambda x: x.title) + + return context + + +class PlanScreenView(PlanIndexView): + template_name = "AKPlan/plan_screen.html" + + def get_queryset(self): + # Determine interesting range (some hours ago until some hours in the future as specified in the settings) + self.start = datetime.now().astimezone(self.event.timezone) - timedelta(hours=settings.PLAN_BEAMER_HOURS_RETROSPECT) + self.end = self.start + timedelta(hours=(settings.PLAN_BEAMER_HOURS_RETROSPECT + settings.PLAN_BEAMER_HOURS_FUTURE)) + + # Restrict AK slots to relevant ones + # This will automatically filter all rooms not needed for the selected range in the orginal get_context method + return super().get_queryset().filter(start__gt=self.start, start__lt=self.end) + + def get_context_data(self, *, object_list=None, **kwargs): + context = super().get_context_data(object_list=object_list, **kwargs) + context["start"] = self.start + context["end"] = self.end + return context diff --git a/AKPlanning/settings.py b/AKPlanning/settings.py index 17370e86..40120d42 100644 --- a/AKPlanning/settings.py +++ b/AKPlanning/settings.py @@ -36,7 +36,7 @@ INSTALLED_APPS = [ 'AKDashboard.apps.AkdashboardConfig', 'AKSubmission.apps.AksubmissionConfig', 'AKScheduling.apps.AkschedulingConfig', - # 'AKPlan.apps.AkplanConfig', + 'AKPlan.apps.AkplanConfig', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', @@ -46,6 +46,7 @@ INSTALLED_APPS = [ 'bootstrap4', 'fontawesome', 'timezone_field', + 'rest_framework', ] MIDDLEWARE = [ @@ -156,4 +157,10 @@ FOOTER_INFO = { "impress_url": "" } +# How many AKs should be visible as next AKs +PLAN_MAX_NEXT_AKS = 10 +# Specify range of plan for screen/projector view +PLAN_SCREEN_HOURS_RETROSPECT = 3 +PLAN_SCREEN_HOURS_FUTURE = 18 + include(optional("settings/*.py")) -- GitLab From c4836caa344765a0d1f5bbd1db087fdcd8fe1d2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@cs.tu-darmstadt.de> Date: Mon, 2 Mar 2020 23:40:10 +0100 Subject: [PATCH 06/15] Rename screen view to AK wall Adapt filenames, references and URLs Adapt settings keys Adapt translations Fix wrong settings keys in wall view --- AKPlan/locale/de_DE/LC_MESSAGES/django.po | 12 ++++++------ AKPlan/templates/AKPlan/plan_index.html | 2 +- .../AKPlan/{plan_screen.html => plan_wall.html} | 0 AKPlan/urls.py | 2 +- AKPlan/views.py | 6 +++--- AKPlanning/settings.py | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) rename AKPlan/templates/AKPlan/{plan_screen.html => plan_wall.html} (100%) diff --git a/AKPlan/locale/de_DE/LC_MESSAGES/django.po b/AKPlan/locale/de_DE/LC_MESSAGES/django.po index fbb174f5..90548ac6 100644 --- a/AKPlan/locale/de_DE/LC_MESSAGES/django.po +++ b/AKPlan/locale/de_DE/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-03-02 01:08+0000\n" +"POT-Creation-Date: 2020-03-02 22:35+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -25,7 +25,7 @@ msgstr "Tag" msgid "Event" msgstr "Veranstaltung" -#: templates/AKPlan/plan_index.html:66 templates/AKPlan/plan_screen.html:64 +#: templates/AKPlan/plan_index.html:66 templates/AKPlan/plan_wall.html:64 msgid "Room" msgstr "Raum" @@ -34,14 +34,14 @@ msgid "AK Plan" msgstr "AK-Plan" #: templates/AKPlan/plan_index.html:112 -msgid "screen view" -msgstr "Anzeigeansicht" +msgid "AK Wall" +msgstr "AK-Wall" -#: templates/AKPlan/plan_index.html:120 templates/AKPlan/plan_screen.html:99 +#: templates/AKPlan/plan_index.html:120 templates/AKPlan/plan_wall.html:99 msgid "Current AKs" msgstr "Aktuelle AKs" -#: templates/AKPlan/plan_index.html:127 templates/AKPlan/plan_screen.html:104 +#: templates/AKPlan/plan_index.html:127 templates/AKPlan/plan_wall.html:104 msgid "Next AKs" msgstr "Nächste AKs" diff --git a/AKPlan/templates/AKPlan/plan_index.html b/AKPlan/templates/AKPlan/plan_index.html index 0559a096..4d552e7b 100644 --- a/AKPlan/templates/AKPlan/plan_index.html +++ b/AKPlan/templates/AKPlan/plan_index.html @@ -109,7 +109,7 @@ {% block content %} <div class="float-right"> - <a href="{% url 'plan:plan_screen' event_slug=event.slug %}" class="btn btn-success">{% fontawesome_icon 'desktop' %} {% trans "screen view" %}</a> + <a href="{% url 'plan:plan_wall' event_slug=event.slug %}" class="btn btn-success">{% fontawesome_icon 'desktop' %} {% trans "AK Wall" %}</a> </div> <h1>Plan: {{ event }}</h1> diff --git a/AKPlan/templates/AKPlan/plan_screen.html b/AKPlan/templates/AKPlan/plan_wall.html similarity index 100% rename from AKPlan/templates/AKPlan/plan_screen.html rename to AKPlan/templates/AKPlan/plan_wall.html diff --git a/AKPlan/urls.py b/AKPlan/urls.py index dacc519e..2206cd0e 100644 --- a/AKPlan/urls.py +++ b/AKPlan/urls.py @@ -8,7 +8,7 @@ urlpatterns = [ '<slug:event_slug>/plan/', include([ path('', views.PlanIndexView.as_view(), name='plan_overview'), - path('screen/', views.PlanScreenView.as_view(), name='plan_screen'), + path('wall/', views.PlanScreenView.as_view(), name='plan_wall'), ]) ), ] diff --git a/AKPlan/views.py b/AKPlan/views.py index d82ffe43..b1b598cc 100644 --- a/AKPlan/views.py +++ b/AKPlan/views.py @@ -50,12 +50,12 @@ class PlanIndexView(FilterByEventSlugMixin, ListView): class PlanScreenView(PlanIndexView): - template_name = "AKPlan/plan_screen.html" + template_name = "AKPlan/plan_wall.html" def get_queryset(self): # Determine interesting range (some hours ago until some hours in the future as specified in the settings) - self.start = datetime.now().astimezone(self.event.timezone) - timedelta(hours=settings.PLAN_BEAMER_HOURS_RETROSPECT) - self.end = self.start + timedelta(hours=(settings.PLAN_BEAMER_HOURS_RETROSPECT + settings.PLAN_BEAMER_HOURS_FUTURE)) + self.start = datetime.now().astimezone(self.event.timezone) - timedelta(hours=settings.PLAN_WALL_HOURS_RETROSPECT) + self.end = self.start + timedelta(hours=(settings.PLAN_WALL_HOURS_RETROSPECT + settings.PLAN_WALL_HOURS_FUTURE)) # Restrict AK slots to relevant ones # This will automatically filter all rooms not needed for the selected range in the orginal get_context method diff --git a/AKPlanning/settings.py b/AKPlanning/settings.py index 40120d42..bea3d55a 100644 --- a/AKPlanning/settings.py +++ b/AKPlanning/settings.py @@ -160,7 +160,7 @@ FOOTER_INFO = { # How many AKs should be visible as next AKs PLAN_MAX_NEXT_AKS = 10 # Specify range of plan for screen/projector view -PLAN_SCREEN_HOURS_RETROSPECT = 3 -PLAN_SCREEN_HOURS_FUTURE = 18 +PLAN_WALL_HOURS_RETROSPECT = 3 +PLAN_WALL_HOURS_FUTURE = 18 include(optional("settings/*.py")) -- GitLab From ed77c4b49a92d036c514c1bd21d6a9d004f58bd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@fachschaft.informatik.tu-darmstadt.de> Date: Wed, 4 Mar 2020 00:12:36 +0100 Subject: [PATCH 07/15] Port AKPlan to fontawesome 5 --- AKPlan/templates/AKPlan/plan_index.html | 6 +++--- AKPlan/templates/AKPlan/plan_wall.html | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/AKPlan/templates/AKPlan/plan_index.html b/AKPlan/templates/AKPlan/plan_index.html index 4d552e7b..bb8214e3 100644 --- a/AKPlan/templates/AKPlan/plan_index.html +++ b/AKPlan/templates/AKPlan/plan_index.html @@ -1,6 +1,6 @@ {% extends "base.html" %} -{% load fontawesome %} +{% load fontawesome_5 %} {% load i18n %} {% load tags_AKModel %} {% load static %} @@ -109,7 +109,7 @@ {% block content %} <div class="float-right"> - <a href="{% url 'plan:plan_wall' event_slug=event.slug %}" class="btn btn-success">{% fontawesome_icon 'desktop' %} {% trans "AK Wall" %}</a> + <a href="{% url 'plan:plan_wall' event_slug=event.slug %}" class="btn btn-success">{% fa5_icon 'desktop' 'fas' %} {% trans "AK Wall" %}</a> </div> <h1>Plan: {{ event }}</h1> @@ -141,7 +141,7 @@ {% block footer_custom %} {% if event.contact_email %} <h4> - <a href="mailto:{{ event.contact_email }}">{% fontawesome_icon "envelope" %} {% trans "Write to organizers of this event for questions and comments" %}</a> + <a href="mailto:{{ event.contact_email }}">{% fa5_icon "envelope" "far" %} {% trans "Write to organizers of this event for questions and comments" %}</a> </h4> {% endif %} {% endblock %} diff --git a/AKPlan/templates/AKPlan/plan_wall.html b/AKPlan/templates/AKPlan/plan_wall.html index 8d21d59b..ca089605 100644 --- a/AKPlan/templates/AKPlan/plan_wall.html +++ b/AKPlan/templates/AKPlan/plan_wall.html @@ -1,7 +1,7 @@ {% load static %} {% load i18n %} {% load bootstrap4 %} -{% load fontawesome %} +{% load fontawesome_5 %} {% load tags_AKModel %} {% load tz %} @@ -15,7 +15,7 @@ {# Load Bootstrap CSS and JavaScript as well as font awesome #} {% bootstrap_css %} {% bootstrap_javascript jquery='slim' %} - {% fontawesome_stylesheet %} + {% fontawesome_5_static %} <link rel="stylesheet" href="{% static 'common/css/custom.css' %}"> -- GitLab From c547cb6a9b78eb5eb53d9db446707fd478ca9f7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@fachschaft.informatik.tu-darmstadt.de> Date: Wed, 4 Mar 2020 00:13:31 +0100 Subject: [PATCH 08/15] Fix dashboard links & improve decoupling Adapt dashboard links to new URL structure of plan Introduce conditional loading of paths to central URL file --- AKDashboard/templates/AKDashboard/dashboard.html | 4 ++-- AKPlanning/urls.py | 13 ++++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/AKDashboard/templates/AKDashboard/dashboard.html b/AKDashboard/templates/AKDashboard/dashboard.html index 5f4df6f2..1e54236d 100644 --- a/AKDashboard/templates/AKDashboard/dashboard.html +++ b/AKDashboard/templates/AKDashboard/dashboard.html @@ -25,14 +25,14 @@ {% if 'AKPlan'|check_app_installed %} <a class="dashboard-box btn btn-primary" - href="{% url 'plan:ak_plan_current_next' event_slug=event.slug %}"> + href="{% url 'plan:plan_overview' event_slug=event.slug %}"> <div class="col-sm-12 col-md-3 col-lg-2 dashboard-button"> <span class="fa fa-list-ul"></span> <span class='text'>{% trans 'Current AKs' %}</span> </div> </a> <a class="dashboard-box btn btn-primary" - href="{% url 'plan:ak_plan_timeline' event_slug=event.slug %}"> + href="{% url 'plan:plan_wall' event_slug=event.slug %}"> <div class="col-sm-12 col-md-3 col-lg-2 dashboard-button"> <span class="fa fa-calendar"></span> <span class='text'>{% trans "AK Wall" %}</span> diff --git a/AKPlanning/urls.py b/AKPlanning/urls.py index 76f8b94e..c7c04a38 100644 --- a/AKPlanning/urls.py +++ b/AKPlanning/urls.py @@ -13,12 +13,19 @@ Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ +from django.apps import apps from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), - path('', include('AKSubmission.urls', namespace='submit')), - path('', include('AKDashboard.urls', namespace='dashboard')), - path('i18n/', include('django.conf.urls.i18n')), + path('i18n/', include('django.conf.urls.i18n')) ] + +# Load URLs dynamically (only if components are active) +if apps.is_installed("AKSubmission"): + urlpatterns.append(path('', include('AKSubmission.urls', namespace='submit'))) +if apps.is_installed("AKDashboard"): + urlpatterns.append(path('', include('AKDashboard.urls', namespace='dashboard'))) +if apps.is_installed("AKPlan"): + urlpatterns.append(path('', include('AKPlan.urls', namespace='plan'))) -- GitLab From 40a7f7679c7de049842e9f19c704b27df6fbc129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@fachschaft.informatik.tu-darmstadt.de> Date: Wed, 4 Mar 2020 00:43:56 +0100 Subject: [PATCH 09/15] Refactor for better re-usability Introduce common base template for plan views Move breadcrumbs to own file for easy referencing Load common fullcalendar base files in base template Introduce new block for other fullcalendar operations --- AKPlan/templates/AKPlan/plan_base.html | 27 +++++++++++++++ AKPlan/templates/AKPlan/plan_breadcrumbs.html | 14 ++++++++ AKPlan/templates/AKPlan/plan_index.html | 33 +++---------------- 3 files changed, 45 insertions(+), 29 deletions(-) create mode 100644 AKPlan/templates/AKPlan/plan_base.html create mode 100644 AKPlan/templates/AKPlan/plan_breadcrumbs.html diff --git a/AKPlan/templates/AKPlan/plan_base.html b/AKPlan/templates/AKPlan/plan_base.html new file mode 100644 index 00000000..e97b7dac --- /dev/null +++ b/AKPlan/templates/AKPlan/plan_base.html @@ -0,0 +1,27 @@ +{% extends "base.html" %} + +{% load fontawesome_5 %} +{% load i18n %} +{% load static %} + +{% block imports %} + {% get_current_language as LANGUAGE_CODE %} + + <link href='{% static 'AKPlan/fullcalendar/core/main.css' %}' rel='stylesheet' /> + + <script src='{% static 'AKPlan/fullcalendar/core/main.js' %}'></script> + {% with 'AKPlan/fullcalendar/core/locales/'|add:LANGUAGE_CODE|add:'.js' as locale_file %} + <script src="{% static locale_file %}"></script> + {% endwith %} + <script src='{% static 'AKPlan/fullcalendar/bootstrap/main.js' %}'></script> + + {% block fullcalendar %}{% endblock %} +{% endblock imports %} + +{% block footer_custom %} + {% if event.contact_email %} + <h4> + <a href="mailto:{{ event.contact_email }}">{% fa5_icon "envelope" "far" %} {% trans "Write to organizers of this event for questions and comments" %}</a> + </h4> + {% endif %} +{% endblock %} diff --git a/AKPlan/templates/AKPlan/plan_breadcrumbs.html b/AKPlan/templates/AKPlan/plan_breadcrumbs.html new file mode 100644 index 00000000..c5ca3c1a --- /dev/null +++ b/AKPlan/templates/AKPlan/plan_breadcrumbs.html @@ -0,0 +1,14 @@ +{% load i18n %} +{% load tags_AKModel %} + +<li class="breadcrumb-item"> + {% if 'AKDashboard'|check_app_installed %} + <a href="{% url 'dashboard:dashboard' %}">AKPlanning</a> + {% else %} + AKPlanning + {% endif %} +</li> +<li class="breadcrumb-item">{{ event.slug }}</li> +<li class="breadcrumb-item"> + <a href="{% url 'plan:plan_overview' event_slug=event.slug %}">{% trans "AK Plan" %}</a> +</li> diff --git a/AKPlan/templates/AKPlan/plan_index.html b/AKPlan/templates/AKPlan/plan_index.html index bb8214e3..520c678e 100644 --- a/AKPlan/templates/AKPlan/plan_index.html +++ b/AKPlan/templates/AKPlan/plan_index.html @@ -1,28 +1,21 @@ -{% extends "base.html" %} +{% extends "AKPlan/plan_base.html" %} {% load fontawesome_5 %} {% load i18n %} -{% load tags_AKModel %} {% load static %} {% load tz %} -{% block imports %} +{% block fullcalendar %} {% get_current_language as LANGUAGE_CODE %} - <link href='{% static 'AKPlan/fullcalendar/core/main.css' %}' rel='stylesheet' /> <link href='{% static 'AKPlan/fullcalendar/timeline/main.css' %}' rel='stylesheet' /> <link href='{% static 'AKPlan/fullcalendar/resource-timeline/main.css' %}' rel='stylesheet' /> <link href='{% static 'AKPlan/fullcalendar/resource-timeline/main.min.css' %}' rel='stylesheet' /> - <script src='{% static 'AKPlan/fullcalendar/core/main.js' %}'></script> - {% with 'AKPlan/fullcalendar/core/locales/'|add:LANGUAGE_CODE|add:'.js' as locale_file %} - <script src="{% static locale_file %}"></script> - {% endwith %} <script src='{% static 'AKPlan/fullcalendar/timeline/main.js' %}'></script> <script src='{% static 'AKPlan/fullcalendar/resource-common/main.js' %}'></script> <script src='{% static 'AKPlan/fullcalendar/resource-timeline/main.js' %}'></script> - <script src='{% static 'AKPlan/fullcalendar/bootstrap/main.js' %}'></script> <script> document.addEventListener('DOMContentLoaded', function() { @@ -90,20 +83,11 @@ plan.render(); }); </script> -{% endblock imports %} +{% endblock %} {% block breadcrumbs %} - <li class="breadcrumb-item"> - {% if 'AKDashboard'|check_app_installed %} - <a href="{% url 'dashboard:dashboard' %}">AKPlanning</a> - {% else %} - AKPlanning - {% endif %} -</li> -<li class="breadcrumb-item">{{ event.slug }}</li> - <li class="breadcrumb-item"><a - href="{% url 'plan:plan_overview' event_slug=event.slug %}">{% trans "AK Plan" %}</a></li> + {% include "AKPlan/plan_breadcrumbs.html" %} {% endblock %} @@ -136,12 +120,3 @@ </div> {% endtimezone %} {% endblock %} - - -{% block footer_custom %} - {% if event.contact_email %} - <h4> - <a href="mailto:{{ event.contact_email }}">{% fa5_icon "envelope" "far" %} {% trans "Write to organizers of this event for questions and comments" %}</a> - </h4> - {% endif %} -{% endblock %} -- GitLab From d6a755c95e176ef494c130babe6e47bc6f776515 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@fachschaft.informatik.tu-darmstadt.de> Date: Wed, 4 Mar 2020 00:57:15 +0100 Subject: [PATCH 10/15] Move event & room encoding and add more information to visualization Move encoding to own files that can be included Add url for linking to detail page to event encoding Add color coding for category and track to event encoding Introduce room hierarchy (building + room) --- AKPlan/templates/AKPlan/encode_events.html | 17 +++++++++++++++++ AKPlan/templates/AKPlan/encode_rooms.html | 15 +++++++++++++++ AKPlan/templates/AKPlan/plan_index.html | 22 ++-------------------- AKPlan/templates/AKPlan/plan_wall.html | 13 +------------ AKPlan/views.py | 6 ++++++ AKPlanning/settings.py | 2 ++ 6 files changed, 43 insertions(+), 32 deletions(-) create mode 100644 AKPlan/templates/AKPlan/encode_events.html create mode 100644 AKPlan/templates/AKPlan/encode_rooms.html diff --git a/AKPlan/templates/AKPlan/encode_events.html b/AKPlan/templates/AKPlan/encode_events.html new file mode 100644 index 00000000..2cb97b19 --- /dev/null +++ b/AKPlan/templates/AKPlan/encode_events.html @@ -0,0 +1,17 @@ +{% load tz %} + +[ + {% for slot in slots %} + {% if slot.start %} + { + 'title': '{{ slot.ak.name }}', + 'start': '{{ slot.start | timezone:event.timezone | date:"Y-m-d H:i:s" }}', + 'end': '{{ slot.end | timezone:event.timezone | date:"Y-m-d H:i:s" }}', + 'resourceId': '{{ slot.room.title }}', + 'backgroundColor': '{{ slot.ak.category.color }}', + 'borderColor': '{{ slot.ak.track.color }}', + 'url': '{% url 'submit:ak_detail' event_slug=event.slug pk=slot.ak.pk %}' + }, + {% endif %} + {% endfor %} +] diff --git a/AKPlan/templates/AKPlan/encode_rooms.html b/AKPlan/templates/AKPlan/encode_rooms.html new file mode 100644 index 00000000..55138df0 --- /dev/null +++ b/AKPlan/templates/AKPlan/encode_rooms.html @@ -0,0 +1,15 @@ +[ + {% for room in rooms %} + { + 'id': '{{ room.title }}', + 'title': '{{ room.title }}', + 'parentId': '{{ room.building }}', + }, + {% endfor %} + {% for building in buildings %} + { + 'id': '{{ building }}', + 'title': '{{ building }}', + }, + {% endfor %} +] diff --git a/AKPlan/templates/AKPlan/plan_index.html b/AKPlan/templates/AKPlan/plan_index.html index 520c678e..032d8eda 100644 --- a/AKPlan/templates/AKPlan/plan_index.html +++ b/AKPlan/templates/AKPlan/plan_index.html @@ -57,26 +57,8 @@ eventColor: '#127ba3', resourceAreaWidth: '15%', resourceLabelText: '{% trans "Room" %}', - resources: [ - {% for room in rooms %} - { - 'id': '{{ room.title }}', - 'title': '{{ room.title }}' - }, - {% endfor %} - ], - events: [ - {% for slot in akslots %} - {% if slot.room and slot.start %} - { - 'title': '{{ slot.ak.name }}', - 'start': '{{ slot.start | timezone:event.timezone | date:"Y-m-d H:i:s" }}', - 'end': '{{ slot.end | timezone:event.timezone | date:"Y-m-d H:i:s" }}', - 'resourceId': '{{ slot.room.title }}', - }, - {% endif %} - {% endfor %} - ], + resources: {% include "AKPlan/encode_rooms.html" %}, + events: {% with akslots as slots %}{% include "AKPlan/encode_events.html" %}{% endwith %}, schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source', }); diff --git a/AKPlan/templates/AKPlan/plan_wall.html b/AKPlan/templates/AKPlan/plan_wall.html index ca089605..7507e88f 100644 --- a/AKPlan/templates/AKPlan/plan_wall.html +++ b/AKPlan/templates/AKPlan/plan_wall.html @@ -70,18 +70,7 @@ }, {% endfor %} ], - events: [ - {% for slot in akslots %} - {% if slot.room and slot.start %} - { - 'title': '{{ slot.ak.name }}', - 'start': '{{ slot.start | timezone:event.timezone | date:"Y-m-d H:i:s" }}', - 'end': '{{ slot.end | timezone:event.timezone | date:"Y-m-d H:i:s" }}', - 'resourceId': '{{ slot.room.title }}', - }, - {% endif %} - {% endfor %} - ], + events: {% with akslots as slots %}{% include "AKPlan/encode_events.html" %}{% endwith %}, schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source', }); diff --git a/AKPlan/views.py b/AKPlan/views.py index b1b598cc..e1b61915 100644 --- a/AKPlan/views.py +++ b/AKPlan/views.py @@ -28,12 +28,16 @@ class PlanIndexView(FilterByEventSlugMixin, ListView): context["akslots_now"] = [] context["akslots_next"] = [] rooms = set() + buildings = set() # Get list of current and next slots for akslot in context["akslots"]: # Construct a list of all rooms used by these slots on the fly if akslot.room is not None: rooms.add(akslot.room) + # Store buildings for hierarchical view + if akslot.room.building != '': + buildings.add(akslot.room.building) # Recent AKs: Started but not ended yet if akslot.start <= current_timestamp <= akslot.end: @@ -45,6 +49,8 @@ class PlanIndexView(FilterByEventSlugMixin, ListView): # Sort list of rooms by title context["rooms"] = sorted(rooms, key=lambda x: x.title) + if settings.PLAN_SHOW_HIERARCHY: + context["buildings"] = sorted(buildings) return context diff --git a/AKPlanning/settings.py b/AKPlanning/settings.py index 57cb81e5..fc67a542 100644 --- a/AKPlanning/settings.py +++ b/AKPlanning/settings.py @@ -162,5 +162,7 @@ PLAN_MAX_NEXT_AKS = 10 # Specify range of plan for screen/projector view PLAN_WALL_HOURS_RETROSPECT = 3 PLAN_WALL_HOURS_FUTURE = 18 +# Should the plan use a hierarchy of buildings and rooms? +PLAN_SHOW_HIERARCHY = True include(optional("settings/*.py")) -- GitLab From 4590d41e2b5286cd2eecda670f75c731d72cc047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@fachschaft.informatik.tu-darmstadt.de> Date: Wed, 4 Mar 2020 01:57:11 +0100 Subject: [PATCH 11/15] Introduce detail views for room and track plans --- AKPlan/locale/de_DE/LC_MESSAGES/django.po | 39 +++++++++++------ AKPlan/templates/AKPlan/plan_detail.html | 53 +++++++++++++++++++++++ AKPlan/templates/AKPlan/plan_index.html | 22 +++++++++- AKPlan/templates/AKPlan/plan_room.html | 53 +++++++++++++++++++++++ AKPlan/templates/AKPlan/plan_track.html | 53 +++++++++++++++++++++++ AKPlan/urls.py | 2 + AKPlan/views.py | 25 ++++++++++- 7 files changed, 231 insertions(+), 16 deletions(-) create mode 100644 AKPlan/templates/AKPlan/plan_detail.html create mode 100644 AKPlan/templates/AKPlan/plan_room.html create mode 100644 AKPlan/templates/AKPlan/plan_track.html diff --git a/AKPlan/locale/de_DE/LC_MESSAGES/django.po b/AKPlan/locale/de_DE/LC_MESSAGES/django.po index 90548ac6..234e7500 100644 --- a/AKPlan/locale/de_DE/LC_MESSAGES/django.po +++ b/AKPlan/locale/de_DE/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-03-02 22:35+0000\n" +"POT-Creation-Date: 2020-03-04 00:53+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -17,37 +17,50 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: templates/AKPlan/plan_index.html:47 +#: templates/AKPlan/plan_base.html:24 +msgid "Write to organizers of this event for questions and comments" +msgstr "Fragen oder Kommentare? Schreib den Orgas dieses Events eine Mail" + +#: templates/AKPlan/plan_breadcrumbs.html:13 +msgid "AK Plan" +msgstr "AK-Plan" + +#: templates/AKPlan/plan_index.html:40 msgid "Day" msgstr "Tag" -#: templates/AKPlan/plan_index.html:57 +#: templates/AKPlan/plan_index.html:50 msgid "Event" msgstr "Veranstaltung" -#: templates/AKPlan/plan_index.html:66 templates/AKPlan/plan_wall.html:64 +#: templates/AKPlan/plan_index.html:59 templates/AKPlan/plan_room.html:8 +#: templates/AKPlan/plan_room.html:44 templates/AKPlan/plan_wall.html:64 msgid "Room" msgstr "Raum" -#: templates/AKPlan/plan_index.html:106 -msgid "AK Plan" -msgstr "AK-Plan" +#: templates/AKPlan/plan_index.html:80 templates/AKPlan/plan_room.html:34 +msgid "Rooms" +msgstr "Räume" + +#: templates/AKPlan/plan_index.html:88 templates/AKPlan/plan_track.html:34 +msgid "Tracks" +msgstr "Tracks" -#: templates/AKPlan/plan_index.html:112 +#: templates/AKPlan/plan_index.html:96 msgid "AK Wall" msgstr "AK-Wall" -#: templates/AKPlan/plan_index.html:120 templates/AKPlan/plan_wall.html:99 +#: templates/AKPlan/plan_index.html:106 templates/AKPlan/plan_wall.html:88 msgid "Current AKs" msgstr "Aktuelle AKs" -#: templates/AKPlan/plan_index.html:127 templates/AKPlan/plan_wall.html:104 +#: templates/AKPlan/plan_index.html:113 templates/AKPlan/plan_wall.html:93 msgid "Next AKs" msgstr "Nächste AKs" -#: templates/AKPlan/plan_index.html:144 -msgid "Write to organizers of this event for questions and comments" -msgstr "Fragen oder Kommentare? Schreib den Orgas dieses Events eine Mail" +#: templates/AKPlan/plan_track.html:8 templates/AKPlan/plan_track.html:44 +msgid "Track" +msgstr "Track" #: templates/AKPlan/slots_table.html:12 msgid "No AKs" diff --git a/AKPlan/templates/AKPlan/plan_detail.html b/AKPlan/templates/AKPlan/plan_detail.html new file mode 100644 index 00000000..c1ce04ef --- /dev/null +++ b/AKPlan/templates/AKPlan/plan_detail.html @@ -0,0 +1,53 @@ +{% extends "AKPlan/plan_base.html" %} + +{% load fontawesome_5 %} +{% load i18n %} +{% load static %} +{% load tz %} + + +{% block fullcalendar %} + {% get_current_language as LANGUAGE_CODE %} + + <link href='{% static 'AKPlan/fullcalendar/daygrid/main.min.css' %}' rel='stylesheet' /> + <link href='{% static 'AKPlan/fullcalendar/timegrid/main.min.css' %}' rel='stylesheet' /> + + <script src='{% static 'AKPlan/fullcalendar/daygrid/main.min.js' %}'></script> + <script src='{% static 'AKPlan/fullcalendar/timegrid/main.min.js' %}'></script> + + <script> + document.addEventListener('DOMContentLoaded', function() { + var calendarEl = document.getElementById('planCalendar'); + + var calendar = new FullCalendar.Calendar(calendarEl, { + plugins: [ 'timeGrid', 'bootstrap' ], + // Adapt to timezone of the connected event + timeZone: '{{ event.timezone }}', + defaultView: 'timeGrid', + // Adapt to user selected locale + locale: '{{ LANGUAGE_CODE }}', + // No header, not buttons + header: { + left: '', + center: '', + right: '' + }, + aspectRatio: 2, + themeSystem: 'bootstrap', + // Only show calendar view for the dates of the connected event + visibleRange: { + start: '{{ event.start | timezone:event.timezone | date:"Y-m-d H:i:s" }}', + end: '{{ event.end | timezone:event.timezone | date:"Y-m-d H:i:s"}}', + }, + allDaySlot: false, + nowIndicator: true, + eventTextColor: '#fff', + eventColor: '#127ba3', + // Create entries for all scheduled slots + events: {% block encode %}{% endblock %} + }); + + calendar.render(); + }); + </script> +{% endblock %} diff --git a/AKPlan/templates/AKPlan/plan_index.html b/AKPlan/templates/AKPlan/plan_index.html index 032d8eda..75b0cf86 100644 --- a/AKPlan/templates/AKPlan/plan_index.html +++ b/AKPlan/templates/AKPlan/plan_index.html @@ -75,7 +75,27 @@ {% block content %} <div class="float-right"> - <a href="{% url 'plan:plan_wall' event_slug=event.slug %}" class="btn btn-success">{% fa5_icon 'desktop' 'fas' %} {% trans "AK Wall" %}</a> + <ul class="nav nav-pills"> + <li class="nav-item dropdown"> + <a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">{% trans "Rooms" %}</a> + <div class="dropdown-menu" style=""> + {% for r in event.room_set.all %} + <a class="dropdown-item" href="{% url "plan:plan_room" event_slug=event.slug pk=r.pk %}">{{ r }}</a> + {% endfor %} + </div> + </li> + <li class="nav-item dropdown"> + <a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">{% trans "Tracks" %}</a> + <div class="dropdown-menu"> + {% for t in event.aktrack_set.all %} + <a class="dropdown-item" href="{% url "plan:plan_track" event_slug=event.slug pk=t.pk %}">{{ t }}</a> + {% endfor %} + </div> + </li> + <li class="nav-item"> + <a class="nav-link active" href="{% url 'plan:plan_wall' event_slug=event.slug %}">{% fa5_icon 'desktop' 'fas' %} {% trans "AK Wall" %}</a> + </li> + </ul> </div> <h1>Plan: {{ event }}</h1> diff --git a/AKPlan/templates/AKPlan/plan_room.html b/AKPlan/templates/AKPlan/plan_room.html new file mode 100644 index 00000000..6f956563 --- /dev/null +++ b/AKPlan/templates/AKPlan/plan_room.html @@ -0,0 +1,53 @@ +{% extends "AKPlan/plan_detail.html" %} + +{% load tz %} +{% load i18n %} + +{% block breadcrumbs %} + {% include "AKPlan/plan_breadcrumbs.html" %} + <li class="breadcrumb-item">{% trans "Room" %}</li> + <li class="breadcrumb-item">{{ room.title }}</li> +{% endblock %} + + +{% block encode %} +[ + {% for slot in room.akslot_set.all %} + {% if slot.start %} + {'title': '{{ slot.ak }}', + 'start': '{{ slot.start | timezone:event.timezone | date:"Y-m-d H:i:s" }}', + 'end': '{{ slot.end | timezone:event.timezone | date:"Y-m-d H:i:s" }}', + 'url': '{% url 'submit:ak_detail' event_slug=event.slug pk=slot.ak.pk %}', + 'borderColor': '{{ slot.ak.track.color }}', + 'color': '{{ slot.ak.category.color }}', + }, + {% endif %} + {% endfor %} +] +{% endblock %} + + +{% block content %} + <div class="float-right"> + <ul class="nav nav-pills"> + <li class="nav-item dropdown"> + <a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">{% trans "Rooms" %}</a> + <div class="dropdown-menu" style=""> + {% for r in event.room_set.all %} + <a class="dropdown-item" href="{% url "plan:plan_room" event_slug=event.slug pk=r.pk %}">{{ r }}</a> + {% endfor %} + </div> + </li> + </ul> + </div> + + <h1>Plan: {{ event }} -- {% trans "Room" %}: {{ room }}</h1> + + {% timezone event.timezone %} + <div class="row" style="margin-top:30px;clear:both;"> + <div class="col-md-12"> + <div id="planCalendar"></div> + </div> + </div> + {% endtimezone %} +{% endblock %} diff --git a/AKPlan/templates/AKPlan/plan_track.html b/AKPlan/templates/AKPlan/plan_track.html new file mode 100644 index 00000000..da452573 --- /dev/null +++ b/AKPlan/templates/AKPlan/plan_track.html @@ -0,0 +1,53 @@ +{% extends "AKPlan/plan_detail.html" %} + +{% load tz %} +{% load i18n %} + +{% block breadcrumbs %} + {% include "AKPlan/plan_breadcrumbs.html" %} + <li class="breadcrumb-item">{% trans "Track" %}</li> + <li class="breadcrumb-item">{{ track }}</li> +{% endblock %} + + +{% block encode %} +[ + {% for slot in slots %} + {% if slot.start %} + {'title': '{{ slot.ak }} @ {{ slot.room }}', + 'start': '{{ slot.start | timezone:event.timezone | date:"Y-m-d H:i:s" }}', + 'end': '{{ slot.end | timezone:event.timezone | date:"Y-m-d H:i:s" }}', + 'url': '{% url 'submit:ak_detail' event_slug=event.slug pk=slot.ak.pk %}', + 'color': '{{ track.color }}', + 'borderColor': '{{ slot.ak.category.color }}', + }, + {% endif %} + {% endfor %} +] +{% endblock %} + + +{% block content %} + <div class="float-right"> + <ul class="nav nav-pills"> + <li class="nav-item dropdown"> + <a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">{% trans "Tracks" %}</a> + <div class="dropdown-menu"> + {% for t in event.aktrack_set.all %} + <a class="dropdown-item" href="{% url "plan:plan_track" event_slug=event.slug pk=t.pk %}">{{ t }}</a> + {% endfor %} + </div> + </li> + </ul> + </div> + + <h1>Plan: {{ event }} -- {% trans "Track" %}: {{ track }}</h1> + + {% timezone event.timezone %} + <div class="row" style="margin-top:30px;clear: both;"> + <div class="col-md-12"> + <div id="planCalendar"></div> + </div> + </div> + {% endtimezone %} +{% endblock %} diff --git a/AKPlan/urls.py b/AKPlan/urls.py index 2206cd0e..d45f64c7 100644 --- a/AKPlan/urls.py +++ b/AKPlan/urls.py @@ -9,6 +9,8 @@ urlpatterns = [ include([ path('', views.PlanIndexView.as_view(), name='plan_overview'), path('wall/', views.PlanScreenView.as_view(), name='plan_wall'), + path('room/<int:pk>/', views.PlanRoomView.as_view(), name='plan_room'), + path('track/<int:pk>/', views.PlanTrackView.as_view(), name='plan_track'), ]) ), ] diff --git a/AKPlan/views.py b/AKPlan/views.py index e1b61915..f96a9726 100644 --- a/AKPlan/views.py +++ b/AKPlan/views.py @@ -2,9 +2,9 @@ from datetime import timedelta from django.conf import settings from django.utils.datetime_safe import datetime -from django.views.generic import ListView +from django.views.generic import ListView, DetailView -from AKModel.models import AKSlot +from AKModel.models import AKSlot, Room, AKTrack from AKModel.views import FilterByEventSlugMixin @@ -72,3 +72,24 @@ class PlanScreenView(PlanIndexView): context["start"] = self.start context["end"] = self.end return context + + +class PlanRoomView(FilterByEventSlugMixin, DetailView): + template_name = "AKPlan/plan_room.html" + model = Room + context_object_name = "room" + + +class PlanTrackView(FilterByEventSlugMixin, DetailView): + template_name = "AKPlan/plan_track.html" + model = AKTrack + context_object_name = "track" + + def get_context_data(self, *, object_list=None, **kwargs): + context = super().get_context_data(object_list=object_list, **kwargs) + + context["slots"] = [] + for ak in context["track"].ak_set.all(): + context["slots"].extend(ak.akslot_set.all()) + + return context -- GitLab From 68b2ef2068f94097c238bcce43ddc39e22f318bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@fachschaft.informatik.tu-darmstadt.de> Date: Sun, 3 May 2020 18:37:17 +0200 Subject: [PATCH 12/15] Fix css import of AK submission page --- AKSubmission/templates/AKSubmission/submit_new.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AKSubmission/templates/AKSubmission/submit_new.html b/AKSubmission/templates/AKSubmission/submit_new.html index b177d801..682a477f 100644 --- a/AKSubmission/templates/AKSubmission/submit_new.html +++ b/AKSubmission/templates/AKSubmission/submit_new.html @@ -9,7 +9,7 @@ {% block imports %} <link rel="stylesheet" href="{% static 'common/vendor/chosen-js/chosen.css' %}"> - <link rel="stylesheet" href="{% static 'common/css/bootstrap-choosen.css' %}"> + <link rel="stylesheet" href="{% static 'common/css/bootstrap-chosen.css' %}"> {% endblock %} {% block breadcrumbs %} @@ -51,4 +51,4 @@ $('.chosen-select').chosen(); }); </script> -{% endblock %} \ No newline at end of file +{% endblock %} -- GitLab From 7a458e70b6c9d6df0c6c0567ca146d426f93a2a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@fachschaft.informatik.tu-darmstadt.de> Date: Sun, 3 May 2020 20:26:04 +0200 Subject: [PATCH 13/15] Introduce color coding for recently changed akslots in plan Add new helper property to model Add and use template tag for color coding Add helpfer functions for color blending (gradient and simple) Also show timestamp of last edit in admin view Introduce setting to control which changes will be higlighted --- AKModel/admin.py | 2 + AKModel/models.py | 11 +++- AKPlan/templates/AKPlan/encode_events.html | 5 +- AKPlan/templatetags/__init__.py | 0 AKPlan/templatetags/color_gradients.py | 61 ++++++++++++++++++++++ AKPlan/templatetags/tags_AKPlan.py | 20 +++++++ AKPlanning/settings.py | 2 + 7 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 AKPlan/templatetags/__init__.py create mode 100644 AKPlan/templatetags/color_gradients.py create mode 100644 AKPlan/templatetags/tags_AKPlan.py diff --git a/AKModel/admin.py b/AKModel/admin.py index 8d60bc7e..8446259d 100644 --- a/AKModel/admin.py +++ b/AKModel/admin.py @@ -74,6 +74,8 @@ admin.site.register(Room) @admin.register(AKSlot) class AKSlotAdmin(admin.ModelAdmin): + readonly_fields = ['updated'] + def get_form(self, request, obj=None, change=False, **kwargs): # Use timezone of associated event if obj is not None and obj.event.timezone: diff --git a/AKModel/models.py b/AKModel/models.py index 997e85e2..24ceb4d7 100644 --- a/AKModel/models.py +++ b/AKModel/models.py @@ -1,8 +1,8 @@ -# Create your models here. import datetime import itertools from django.db import models +from django.utils import timezone from django.utils.text import slugify from django.utils.translation import gettext_lazy as _ from timezone_field import TimeZoneField @@ -301,3 +301,12 @@ class AKSlot(models.Model): Retrieve end time of the AK slot """ return self.start + datetime.timedelta(hours=float(self.duration)) + + @property + def seconds_since_last_update(self): + """ + Return minutes since last update + :return: minutes since last update + :rtype: float + """ + return (timezone.now() - self.updated).total_seconds() diff --git a/AKPlan/templates/AKPlan/encode_events.html b/AKPlan/templates/AKPlan/encode_events.html index 2cb97b19..c38a4652 100644 --- a/AKPlan/templates/AKPlan/encode_events.html +++ b/AKPlan/templates/AKPlan/encode_events.html @@ -1,4 +1,5 @@ {% load tz %} +{% load tags_AKPlan %} [ {% for slot in slots %} @@ -8,8 +9,8 @@ 'start': '{{ slot.start | timezone:event.timezone | date:"Y-m-d H:i:s" }}', 'end': '{{ slot.end | timezone:event.timezone | date:"Y-m-d H:i:s" }}', 'resourceId': '{{ slot.room.title }}', - 'backgroundColor': '{{ slot.ak.category.color }}', - 'borderColor': '{{ slot.ak.track.color }}', + 'backgroundColor': '{{ slot|highlight_change_colors }}', + 'borderColor': '{{ slot.ak.category.color }}', 'url': '{% url 'submit:ak_detail' event_slug=event.slug pk=slot.ak.pk %}' }, {% endif %} diff --git a/AKPlan/templatetags/__init__.py b/AKPlan/templatetags/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/AKPlan/templatetags/color_gradients.py b/AKPlan/templatetags/color_gradients.py new file mode 100644 index 00000000..1a9f96fd --- /dev/null +++ b/AKPlan/templatetags/color_gradients.py @@ -0,0 +1,61 @@ +# gradients based on http://bsou.io/posts/color-gradients-with-python + + +def hex_to_rgb(hex): + """ + Convert hex color to RGB color code + :param hex: hex encoded color + :type hex: str + :return: rgb encoded version of given color + :rtype: list[int] + """ + # Pass 16 to the integer function for change of base + return [int(hex[i:i+2], 16) for i in range(1,6,2)] + + +def rgb_to_hex(rgb): + """ + Convert rgb color (list) to hex encoding (str) + :param rgb: rgb encoded color + :type rgb: list[int] + :return: hex encoded version of given color + :rtype: str + """ + # Components need to be integers for hex to make sense + rgb = [int(x) for x in rgb] + return "#"+"".join(["0{0:x}".format(v) if v < 16 else + "{0:x}".format(v) for v in rgb]) + + +def linear_blend(start_hex, end_hex, position): + """ + Create a linear blend between two colors and return color code on given position of the range from 0 to 1 + :param start_hex: hex representation of start color + :type start_hex: str + :param end_hex: hex representation of end color + :type end_hex: str + :param position: position in range from 0 to 1 + :type position: float + :return: hex encoded interpolated color + :rtype: str + """ + s = hex_to_rgb(start_hex) + f = hex_to_rgb(end_hex) + blended = [int(s[j] + position * (f[j] - s[j])) for j in range(3)] + return rgb_to_hex(blended) + + +def darken(start_hex, amount): + """ + Darken the given color by the given amount (sensitivity will be cut in half) + + :param start_hex: original color + :type start_hex: str + :param amount: how much to darken (1.0 -> 50% darker) + :type amount: float + :return: darker version of color + :rtype: str + """ + start_rbg = hex_to_rgb(start_hex) + darker = [int(s * (1 - amount * .5)) for s in start_rbg] + return rgb_to_hex(darker) diff --git a/AKPlan/templatetags/tags_AKPlan.py b/AKPlan/templatetags/tags_AKPlan.py new file mode 100644 index 00000000..5618fd57 --- /dev/null +++ b/AKPlan/templatetags/tags_AKPlan.py @@ -0,0 +1,20 @@ +from django import template + +from AKPlan.templatetags.color_gradients import darken +from AKPlanning import settings + +register = template.Library() + + +@register.filter +def highlight_change_colors(akslot): + seconds_since_update = akslot.seconds_since_last_update + + # Last change long ago? Use default color + if seconds_since_update > settings.PLAN_MAX_HIGHLIGHT_UPDATE_SECONDS: + return akslot.ak.category.color + + # Recent change? Calculate gradient blend between red and + recentness = seconds_since_update / settings.PLAN_MAX_HIGHLIGHT_UPDATE_SECONDS + return darken("#b71540", recentness) + # return linear_blend("#b71540", "#000000", recentness) diff --git a/AKPlanning/settings.py b/AKPlanning/settings.py index fc67a542..32eb423d 100644 --- a/AKPlanning/settings.py +++ b/AKPlanning/settings.py @@ -164,5 +164,7 @@ PLAN_WALL_HOURS_RETROSPECT = 3 PLAN_WALL_HOURS_FUTURE = 18 # Should the plan use a hierarchy of buildings and rooms? PLAN_SHOW_HIERARCHY = True +# For which time (in seconds) should changes of akslots be highlighted in plan? +PLAN_MAX_HIGHLIGHT_UPDATE_SECONDS = 2 * 60 * 60 include(optional("settings/*.py")) -- GitLab From 1198feb559af3cb3c469340007f728119b9d3a1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@fachschaft.informatik.tu-darmstadt.de> Date: Sat, 9 May 2020 18:05:21 +0200 Subject: [PATCH 14/15] Activate plan app --- AKPlanning/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AKPlanning/settings.py b/AKPlanning/settings.py index 32eb423d..621abaaa 100644 --- a/AKPlanning/settings.py +++ b/AKPlanning/settings.py @@ -36,7 +36,7 @@ INSTALLED_APPS = [ 'AKDashboard.apps.AkdashboardConfig', 'AKSubmission.apps.AksubmissionConfig', 'AKScheduling.apps.AkschedulingConfig', - # 'AKPlan.apps.AkplanConfig', + 'AKPlan.apps.AkplanConfig', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', -- GitLab From 8abc2f602d14d82e653132d9d6d1fe24c3805959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@fachschaft.informatik.tu-darmstadt.de> Date: Sat, 9 May 2020 19:16:18 +0200 Subject: [PATCH 15/15] Show conflicts, prerequisites & conflicts on AK detail page --- .../templates/AKSubmission/ak_detail.html | 29 +++++++++++++++++++ .../AKSubmission/ak_linked_list_inline.html | 8 +++++ 2 files changed, 37 insertions(+) create mode 100644 AKSubmission/templates/AKSubmission/ak_linked_list_inline.html diff --git a/AKSubmission/templates/AKSubmission/ak_detail.html b/AKSubmission/templates/AKSubmission/ak_detail.html index 50279250..02030ffc 100644 --- a/AKSubmission/templates/AKSubmission/ak_detail.html +++ b/AKSubmission/templates/AKSubmission/ak_detail.html @@ -63,6 +63,35 @@ {{ ak.reso | bool_symbol }} </td> </tr> + {% if ak.requirements.count > 0 %} + <tr> + <td>{% trans "Requirements" %}</td> + <td> + {% for requirement in ak.requirements.all %} + {% if forloop.counter0 > 0 %} + , + {% endif %} + {{ requirement }} + {% endfor %} + </td> + </tr> + {% endif %} + {% if ak.conflicts.count > 0 %} + <tr> + <td>{% trans "Conflicting AKs" %}</td> + <td> + {% include "AKSubmission/ak_linked_list_inline.html" with aks=ak.conflicts slug=ak.event.slug %} + </td> + </tr> + {% endif %} + {% if ak.prerequisites.count > 0 %} + <tr> + <td>{% trans "Prerequisite AKs" %}</td> + <td> + {% include "AKSubmission/ak_linked_list_inline.html" with aks=ak.prerequisites slug=ak.event.slug %} + </td> + </tr> + {% endif %} </table> <p style="margin-top: 30px;margin-bottom: 30px;">{{ ak.description }}</p> diff --git a/AKSubmission/templates/AKSubmission/ak_linked_list_inline.html b/AKSubmission/templates/AKSubmission/ak_linked_list_inline.html new file mode 100644 index 00000000..f5b504f7 --- /dev/null +++ b/AKSubmission/templates/AKSubmission/ak_linked_list_inline.html @@ -0,0 +1,8 @@ +{% for ak in aks.all %} + {% if forloop.counter0 > 0 %} + , + {% endif %} + <a href="{% url 'submit:ak_detail' event_slug=slug pk=ak.pk %}">{{ ak }}</a> +{% empty %} + - +{% endfor %} -- GitLab