PageSourceSearch

https://www.natura2000.fr/modules/contrib/fullcalendar_view/js/fullcalendar_view.js?tdfabd

js natura2000.fr collected 2026-09-24 18:38:17 UTC 15,737 bytes, 455 lines download raw bytes

1/**
2 * @file
3 * Fullcalendar View plugin JavaScript file.
4 */
5
6// Jquery wrapper for drupal to avoid conflicts between libraries.
7(function ($, Drupal, drupalSettings) {
8  var initialLocaleCode = 'en';
9  // Dialog index.
10  var dialogIndex = 0;
11  // Dialog objects.
12  var dialogs = [];
13  // Date entry clicked.
14  var slotDate;
15
16  /**
17   * @see https://fullcalendar.io/docs/v4/eventSourceSuccess
18   */
19  function eventSourceSuccessRenderingBackground(content) {
20    for(let i = 0; i < content.length; i++){
21      content[i].rendering = 'background';
22    }
23  }
24
25  /**
26   * Event render handler
27   */
28  function eventRender (info) {
29    let viewIndex = parseInt(this.el.getAttribute('data-calendar-view-index'));
30    let viewSettings = drupalSettings.fullCalendarView[viewIndex];
31
32    if (info.el.classList.contains('fc-bgevent')) {
33      info.el.setAttribute('title', Drupal.checkPlain(info.event.title));
34    }
35
36    // Event title html markup.
37    let eventTitleEle = info.el.getElementsByClassName('fc-title');
38    if(eventTitleEle.length > 0) {
39      eventTitleEle[0].innerHTML = info.event.title;
40    }
41    // Event list tile html markup.
42    let eventListTitleEle = info.el.getElementsByClassName('fc-list-item-title');
43    if(eventListTitleEle.length > 0) {
44      if (info.event.url) {
45        eventListTitleEle[0].innerHTML = '<a href="' + encodeURI(info.event.url) + '">' + info.event.title + '</a>';
46      }
47      else {
48        eventListTitleEle[0].innerHTML = info.event.title;
49      }
50    }
51    // Modal popup
52    if (viewSettings.dialogModal) {
53      if ($(info.el).is('a')) {
54        $(info.el).addClass('use-ajax');
55        if (!viewSettings.dialogCanvas) {
56          $(info.el).attr('data-dialog-type', 'modal');
57        }
58        else {
59          $(info.el).attr('data-dialog-type', 'dialog');
60          $(info.el).attr('data-dialog-renderer', 'off_canvas');
61        }
62        $(info.el).attr('data-dialog-options', viewSettings.dialog_modal_options);
63        $(info.el).attr('href', $(info.el).attr('href').replaceAll('&amp;', '&'));
64      }
65      else {
66        $(info.el).find('a').each(function(){
67          if (!viewSettings.dialogCanvas) {
68            $(this).attr('data-dialog-type', 'modal');
69          }
70          else {
71            $(this).attr('data-dialog-type', 'dialog');
72            $(this).attr('data-dialog-renderer', 'off_canvas');
73          }
74          $(this).attr('data-dialog-options', viewSettings.dialog_modal_options);
75          $(this).addClass('use-ajax');
76          $(this).attr('href', $(this).attr('href').replaceAll('&amp;', '&'));
77        });
78      }
79    }
80  }
81  /**
82   * Event resize handler
83   */
84  function eventResize(info) {
85    const end = info.event.end;
86    const start = info.event.start;
87    let strEnd = '';
88    let strStart = '';
89    let viewIndex = parseInt(this.el.getAttribute("data-calendar-view-index"));
90    let viewSettings = drupalSettings.fullCalendarView[viewIndex];
91    const formatSettings = {
92        month: '2-digit',
93        year: 'numeric',
94        day: '2-digit',
95        hour: '2-digit',
96        minute: '2-digit',
97        second: '2-digit',
98        timeZone: 'UTC',
99        locale: 'sv-SE'
100      };
101    // define the end date string in 'YYYY-MM-DD' format.
102    if (end) {
103      // The end date of an all-day event is exclusive.
104      // For example, the end of 2018-09-03
105      // will appear to 2018-09-02 in the calendar.
106      // So we need one day subtract
107      // to ensure the day stored in Drupal
108      // is the same as when it appears in
109      // the calendar.
110      if (end.getUTCHours() == 0 && end.getUTCMinutes() == 0 && end.getUTCSeconds() == 0) {
111        end.setDate(end.getDate() - 1);
112      }
113      // String of the end date.
114      strEnd = FullCalendar.formatDate(end, formatSettings);
115    }
116    // define the start date string in 'YYYY-MM-DD' format.
117    if (start) {
118      strStart = FullCalendar.formatDate(start, formatSettings);
119    }
120    const title = info.event.title.replace(/(<([^>]+)>)/ig,"");;
121    const msg = Drupal.t('@title end is now @event_end. Do you want to save this change?', {
122      '@title': title,
123      '@event_end': strEnd
124    });
125
126    if (
127        viewSettings.updateConfirm === 1 &&
128        !confirm(msg)
129    ) {
130      info.revert();
131    }
132    else {
133      /**
134       * Perform ajax call for event update in database.
135       */
136      jQuery
137        .post(
138          drupalSettings.path.baseUrl +
139            "fullcalendar-view-event-update",
140          {
141            eid: info.event.extendedProps.eid,
142            entity_type: viewSettings.entityType,
143            start: strStart,
144            end: strEnd,
145            start_field: viewSettings.startField,
146            end_field: viewSettings.endField,
147            token: viewSettings.token
148          }
149        )
150        .done(function(data) {
151          if (data !== '1') {
152            alert("Error: " + data);
153            info.revert();
154          }
155        });
156    }
157  }
158
159  // Day entry click call back function.
160  function dayClickCallback(info) {
161    slotDate = info.dateStr;
162  }
163
164  // Event click call back function.
165  function eventClick(info) {
166    slotDate = null;
167    info.jsEvent.preventDefault();
168    let thisEvent = info.event;
169    let viewIndex = parseInt(this.el.getAttribute("data-calendar-view-index"));
170    let viewSettings = drupalSettings.fullCalendarView[viewIndex];
171    let des = thisEvent.extendedProps.des;
172    // Show the event detail in a pop up dialog.
173    if (viewSettings.dialogWindow) {
174      let dataDialogOptionsDetails = {};
175      if ( des == '') {
176        return false;
177      }
178
179      const jsFrame = new JSFrame({
180        parentElement:info.el,//Set the parent element to which the jsFrame is attached here
181      });
182      // Position offset.
183      let posOffset = dialogIndex * 20;
184      // Dialog options.
185      let dialogOptions = JSON.parse(viewSettings.dialog_options);
186      dialogOptions.left += posOffset + info.jsEvent.pageX;
187      dialogOptions.top += posOffset + info.jsEvent.pageY;
188      dialogOptions.title = dialogOptions.title ? dialogOptions.title : thisEvent.title.replace(/(<([^>]+)>)/ig,"");
189      dialogOptions.html = des;
190      //Create window
191      dialogs[dialogIndex] = jsFrame.create(dialogOptions);
192
193      dialogs[dialogIndex].show();
194      dialogIndex++;
195      Drupal.ajax.bindAjaxLinks(document.body);
196
197      return false;
198    }
199    // Open a new window to show the details of the event.
200    if (thisEvent.url) {
201      let eventURL = new URL(thisEvent.url, location.origin);
202      if (eventURL.origin === "null") {
203        // Invalid URL.
204        return false;
205      }
206      if (viewSettings.openEntityInNewTab) {
207        // Open a new window to show the details of the event.
208       window.open(thisEvent.url);
209       return false;
210      }
211      else {
212        // Open in same window
213        window.location.href = thisEvent.url;
214        return false;
215      }
216    }
217
218    return false;
219  }
220
221  // Event drop call back function.
222  function eventDrop(info) {
223    const end = info.event.end;
224    const start = info.event.start;
225    let strEnd = '';
226    let strStart = '';
227    let viewIndex = parseInt(this.el.getAttribute("data-calendar-view-index"));
228    let viewSettings = drupalSettings.fullCalendarView[viewIndex];
229    const formatSettings = {
230        month: '2-digit',
231        year: 'numeric',
232        day: '2-digit',
233        hour: '2-digit',
234        minute: '2-digit',
235        second: '2-digit',
236        timeZone: 'UTC',
237        locale: 'sv-SE'
238      };
239    // define the end date string in 'YYYY-MM-DD' format.
240    if (end) {
241      // The end date of an all-day event is exclusive.
242      // For example, the end of 2018-09-03
243      // will appear to 2018-09-02 in the calendar.
244      // So we need one day subtract
245      // to ensure the day stored in Drupal
246      // is the same as when it appears in
247      // the calendar.
248      if (end.getUTCHours() == 0 && end.getUTCMinutes() == 0 && end.getUTCSeconds() == 0) {
249        end.setDate(end.getDate() - 1);
250      }
251      // String of the end date.
252      strEnd = FullCalendar.formatDate(end, formatSettings);
253    }
254    // define the start date string in 'YYYY-MM-DD' format.
255    if (start) {
256      strStart = FullCalendar.formatDate(start, formatSettings);
257    }
258    const title = info.event.title.replace(/(<([^>]+)>)/ig,"");;
259    const msg = Drupal.t('@title start is now @event_start and end is now @event_end - Do you want to save this change?', {
260      '@title': title,
261      '@event_start': strStart,
262      '@event_end': strEnd
263    });
264
265    if (
266        viewSettings.updateConfirm === 1 &&
267        !confirm(msg)
268    ) {
269      info.revert();
270    }
271    else {
272      /**
273       * Perform ajax call for event update in database.
274       */
275      jQuery
276        .post(
277          drupalSettings.path.baseUrl +
278            "fullcalendar-view-event-update",
279          {
280            eid: info.event.extendedProps.eid,
281            entity_type: viewSettings.entityType,
282            start: strStart,
283            end: strEnd,
284            start_field: viewSettings.startField,
285            end_field: viewSettings.endField,
286            token: viewSettings.token
287          }
288        )
289        .done(function(data) {
290          if (data !== '1') {
291            alert("Error: " + data);
292            info.revert();
293          }
294        });
295
296    }
297  }
298
299  function datesRender (info) {
300    Drupal.attachBehaviors(info.el);
301  }
302  function datesDestroy (info) {
303    Drupal.detachBehaviors(info.el);
304  }
305
306  // Build the calendar objects.
307  function buildCalendars() {
308    $('.js-drupal-fullcalendar')
309    .each(function() {
310      let calendarEl = this;
311      let viewIndex = parseInt(calendarEl.getAttribute("data-calendar-view-index"));
312      let viewSettings = drupalSettings.fullCalendarView[viewIndex];
313      var calendarOptions = JSON.parse(viewSettings.calendar_options);
314      // Switch default view at mobile widths.
315      if (calendarOptions.mobileWidth !== undefined && calendarOptions.defaultMobileView !== undefined && $(window).width() <= calendarOptions.mobileWidth) {
316       calendarOptions.defaultView = calendarOptions.defaultMobileView;
317      }
318      // Bind the render event handler.
319      calendarOptions.eventRender = eventRender;
320      // Bind the resize event handler.
321      calendarOptions.eventResize = eventResize;
322      // Bind the day click handler.
323      calendarOptions.dateClick = dayClickCallback;
324      // Bind the event click handler.
325      calendarOptions.eventClick = eventClick;
326      // Bind the drop event handler.
327      calendarOptions.eventDrop = eventDrop;
328      // Trigger Drupal behaviors when calendar events are updated.
329      calendarOptions.datesRender = datesRender;
330      // Trigger Drupal behaviors when calendar events are destroyed.
331      calendarOptions.datesDestroy = datesDestroy;
332      // Language select element.
333      var localeSelectorEl = document.getElementById('locale-selector-' + viewIndex);
334
335      if (viewSettings.fetchGoogleHolidays === true) {
336        calendarOptions.plugins = calendarOptions.plugins || [];
337        calendarOptions.plugins.push('googleCalendar');
338        calendarOptions.googleCalendarApiKey = viewSettings.googleCalendarAPIKey;
339        calendarOptions.eventSources = calendarOptions.eventSources || [];
340
341        calendarOptions.eventSources.push({
342          id: viewSettings.googleCalendarGroup,
343          googleCalendarId: viewSettings.googleCalendarGroup,
344          rendering: viewSettings.renderGoogleHolidaysAsBackgroun
344d ? 'background' : '',
345          success: viewSettings.renderGoogleHolidaysAsBackground ? eventSourceSuccessRenderingBackground : null,
346        });
347      }
348
349      // Allow passing a default date via query string.
350      const params = (new URL(document.location)).searchParams;
351      const initialDate = params.get('initialDate')
352      if (initialDate) {
353        calendarOptions.defaultDate = initialDate;
354      }
355
356      // Initial the calendar.
357      if (calendarEl) {
358        if (drupalSettings.calendar) {
359          drupalSettings.calendar[viewIndex] = new FullCalendar.Calendar(calendarEl, calendarOptions);
360        }
361        else {
362          drupalSettings.calendar = [];
363          drupalSettings.calendar[viewIndex] = new FullCalendar.Calendar(calendarEl, calendarOptions);
364        }
365        let calendarObj = drupalSettings.calendar[viewIndex];
366        calendarObj.render();
367        // Language dropdown box.
368        if (viewSettings.languageSelector) {
369          // build the locale selector's options
370          calendarObj.getAvailableLocaleCodes().forEach(function(localeCode) {
371            var optionEl = document.createElement('option');
372            optionEl.value = localeCode;
373            optionEl.selected = localeCode == calendarOptions.locale;
374            optionEl.innerText = localeCode;
375            localeSelectorEl.appendChild(optionEl);
376          });
377          // when the selected option changes, dynamically change the calendar option
378          localeSelectorEl.addEventListener('change', function() {
379            if (this.value) {
380              let viewIndex = parseInt(this.getAttribute("data-calendar-view-index"));
381              drupalSettings.calendar[viewIndex].setOption('locale', this.value);
382            }
383          });
384        }
385        else if (localeSelectorEl){
386          localeSelectorEl.style.display = "none";
387        }
388
389        // Double click event.
390        calendarEl.addEventListener('dblclick' , function(e) {
391          let viewIndex = parseInt(this.getAttribute("data-calendar-view-index"));
392          let viewSettings = drupalSettings.fullCalendarView[viewIndex];
393          // New event window can be open if following conditions match.
394          // * The new event content type are specified.
395          // * Allow to create a new event by double click.
396          // * User has the permission to create a new event.
397          // * The add form for the new event type is known.
398          if (
399              slotDate &&
400              viewSettings.eventBundleType &&
401              viewSettings.dblClickToCreate &&
402              viewSettings.addForm !== ""
403            ) {
404              // Open a new window to create a new event (content).
405              window.open(
406                  drupalSettings.path.baseUrl +
407                  viewSettings.addForm +
408                  "?start=" +
409                  slotDate +
410                  "&start_field=" +
411                  viewSettings.startField +
412                  "&destination=" + window.location.pathname,
413                "_blank"
414              );
415            }
416
417        });
418      }
419    });
420  }
421
422  // document.ready event does not work with BigPipe.
423  // The workaround is to ckeck the document state
424  // every 100 milliseconds until it is completed.
425  // @see https://www.drupal.org/project/drupal/issues/2794099#comment-13274828
426  var checkReadyState = setInterval(function() {
427    if (
428        document.readyState === "complete" &&
429        $('.js-drupal-fullcalendar').length > 0
430        ) {
431      clearInterval(checkReadyState);
432      // Build calendar objects.
433      buildCalendars();
434    }
435  }, 100);
436
437  // After an Ajax call, the calendar objects need to rebuild,
438  // to reflect the changes, such as Ajax filter.
439  $( document ).ajaxComplete(function( event, request, settings ) {
440    // Remove the existing calendars except updating Ajax events.
441    if (
442        drupalSettings.calendar &&
443        settings.url !== '/fullcalendar-view-event-update' &&
444        settings.url.indexOf('_wrapper_format=drupal_modal') < 0
445        ) {
446      // Rebuild the calendars.
447      drupalSettings.calendar.forEach(function(calendar) {
448        calendar.destroy();
449      });
450      //Re-build calendars.
451      buildCalendars();
452    }
453  });
454 
455})(jQuery, Drupal, drupalSettings);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.