Uncaught TypeError: $(...).fullCalendar is not a function error

Uncaught TypeError: $(...).fullCalendar is not a function error

我有一个带有显示 2 个日历的 FullCalendar 库的小代码。一个在第一个选项卡上,一个在第二个选项卡上。两个日历都显示了,但是,页面加载时不可见的日历显示不正确。

完整代码:https://codepen.io/MadBoyEvo/pen/rNxQQYP

所以我想我会刷新或快速将视图从当前视图更改为新视图,然后在选项卡切换时返回当前视图,但无论我做什么都不起作用。

<script type="text/javascript">var tabs = tabbis.init({
        tabGroup: "[data-tabs]",
        paneGroup: "[data-panes]",
        tabActive: "active",
        paneActive: "active",
        callback: function (tab, pane) {
            // console.log("TAB id:" + tab.id);
            // console.log(pane.id);
            // console.log(tableid);
            // this makes sure to refresh tables on tab change to make sure they have buttons and everything
            // it's a bit heavy as it touches all tables, may require some improvements in future to consider
            // which tab has which table
            try {
                var tableid = document.getElementById(tab.id + "-Content").querySelector('table[id^="DT-"]').id;
                $("#" + tableid).DataTable().columns.adjust().responsive.recalc();
            } catch (e) {
                console.log('No datatables available.');
            }
            
            // this code here doesn't work
            var view = $('#Calendar-on26xq0w').fullCalendar('getView');
            alert("The view's title is " + view.title);
        }
    });

    // in theory should take care of removing local storage for tabbis
    // some errors occurs if the local storage is not cleaned after a while
    window.addEventListener("unload", tabbis.remove, false);
</script><!-- JS Elastic Tabbis END -->

出现错误:Uncaught TypeError: $(...).fullCalendar is not a function

我尝试将 calendar.js 脚本从上到下移动到失败的脚本代码之前或之后,但没有任何帮助。

我有点 JS 菜鸟,所以我有点不清楚为什么它不起作用。我对数据表(Try/catch)使用了类似的方法,它工作正常(如果加载了数据表)

编辑:

我已经尝试搜索日历 ID - 我可以找到它,但是在第 3 行可以看到同样的错误。

var calendarid = document.getElementById(tab.id + "-Content").querySelector('div[id^="Calendar-"]').id;
alert("The calendarid " + calendarid);
var view = $('#' + calendarid).fullCalendar('getView');
alert("The view's title is " + view.title);

该错误表明您尝试 运行 fullCalendar() 功能的元素不可用。这意味着在文档中找不到 ID 为 Calendar-on26xq0w 的 HTML 元素。

您可以在 用户 尝试切换到下一个选项卡时即时创建 calendar2。监听 tab 上的 change event 并根据 calendarID.

初始化第二个 calendar
 var calendarid = document.getElementById(tab.id + "-Content").querySelector('div[id^="Calendar-"]').id;
                    // alert("The calendarid " + calendarid);
                  if(calendarid == 'Calendar-3fso0g65') {
                    loadCalendarFirst(calendarid);
                  } else {
                    loadCalendarSecond(calendarid);
                  }
                    

我添加了下面两个方法,需要的时候调用

<script>
        function loadCalendarFirst(claendarID) {
          var calendarEl = document.getElementById(claendarID);
                    var calendar = new FullCalendar.Calendar(calendarEl,
                        {
                            "headerToolbar": {
                                "left": "prev,next,today",
                                "right": "dayGridMonth,timeGridWeek,timeGridDay,listMonth",
                                "center": "title"
                            },
                            "initialView": "listWeek",
                            "initialDate": "2020-07-19",
                            "nowIndicator": true,
                            "navLinks": true,
                            "businessHours": false,
                            "editable": false,
                            "events": [
                                {
                                    "title": "Active Directory Meeting",
                                    "description": "We will talk about stuff",
                                    "start": "2020-07-19T10:07:02"
                                },
                                {
                                    "title": "Lunch",
                                    "description": "Very long lunch",
                                    "start": "2020-07-21T07:07:02",
                                    "end": "2020-07-22T10:07:02"
                                }
                            ],
                            "dayMaxEventRows": true,
                            "weekNumbers": true,
                            "weekNumberCalculation": "ISO",
                            "selectable": true,
                            "selectMirror": true,
                            "buttonIcons": false,
                            "views": {
                                "listWeek": {
                                    "buttonText": "list week"
                                },
                                "listMonth": {
                                    "buttonText": "list month"
                                },
                                "listDay": {
                                    "buttonText": "list day"
                                }
                            },
                            eventRender: function (info) {
                                var tooltip = new Tooltip(info.el, {
                                    title: info.event.extendedProps.description,
                                    placement: 'top',
                                    trigger: 'hover',
                                    container: 'body'
                                });
                            }
                        }
                    );
                    calendar.render();
        }
        
        function loadCalendarSecond(calendarID) {
                    var calendarEl = document.getElementById(calendarID);
                    var calendar = new FullCalendar.Calendar(calendarEl,
                        {
                            "headerToolbar": {
                                "left": "prev,next,today",
                                "right": "dayGridMonth,timeGridWeek,timeGridDay,listMonth",
                                "center": "title"
                            },
                            "initialDate": "2020-07-19",
                            "nowIndicator": true,
                            "navLinks": true,
                            "businessHours": false,
                            "editable": false,
                            "events": [
                                {
                                    "title": "Active Directory Meeting",
                                    "description": "We will talk about stuff",
                                    "start": "2020-07-19T10:07:02"
                                },
                                {
                                    "title": "Lunch",
                                    "description": "Very long lunch",
                                    "start": "2020-07-21T07:07:02",
                                    "end": "2020-07-22T10:07:02"
                                }
                            ],
                            "dayMaxEventRows": true,
                            "weekNumbers": true,
                            "weekNumberCalculation": "ISO",
                            "selectable": true,
                            "selectMirror": true,
                            "buttonIcons": false,
                            "views": {
                                "listWeek": {
                                    "buttonText": "list week"
                                },
                                "listMonth": {
                                    "buttonText": "list month"
                                },
                                "listDay": {
                                    "buttonText": "list day"
                                }
                            },
                            eventRender: function (info) {
                                var tooltip = new Tooltip(info.el, {
                                    title: info.event.extendedProps.description,
                                    placement: 'top',
                                    trigger: 'hover',
                                    container: 'body'
                                });
                            }
                        }
                    );
                    calendar.render();
        }
        
        loadCalendarFirst('Calendar-3fso0g65');
      </script>

这是Updated Plunker

感谢@ADyson 的评论让我能够理解我的问题:

  • FullCalendar V5 没有我尝试使用的方法

If you're using fullcalendar v5 as per your tag, then $('#Calendar-on26xq0w').fullCalendar will never work - that's the syntax from fullCalendar v3 (back when it was a jQuery plugin, hence the jQuery-style selector to initialise the object). If you want to call a method in v4 or v5 then you need a reference to the object you created when initialising the calendar, and then to get the current view you can simply write calendar.view (it's a property not a function) - see fullcalendar.io/docs/Calendar-view . (There's no such function as getView in v5 either.)

在最顶部定义了空对象

<!-- JS FullCalendar Basic START -->
<script type="text/javascript">var calendarTracker = {

    };
</script><!-- JS FullCalendar Basic END -->
<!-- CSS FullCalendar Basic START -->

接下来是我创建的每个日历

<script>document.addEventListener('DOMContentLoaded', function () {
        var calendarEl = document.getElementById('Calendar-c43nxqpi');
        var calendar = new FullCalendar.Calendar(calendarEl,
            {
                "headerToolbar": {
                    "left": "prev,next,today",
                    "right": "dayGridMonth,timeGridWeek,timeGridDay,listMonth",
                    "center": "title"
                },
                "initialView": "listWeek",
                "initialDate": "2020-07-20",
                "nowIndicator": true,
                "navLinks": true,
                "businessHours": false,
                "editable": false,
                "events": [
                    {
                        "title": "Active Directory Meeting",
                        "description": "We will talk about stuff",
                        "start": "2020-07-20T11:43:35"
                    },
                    {
                        "title": "Lunch",
                        "description": "Very long lunch",
                        "start": "2020-07-22T08:43:35",
                        "end": "2020-07-23T11:43:35"
                    }
                ],
                "dayMaxEventRows": true,
                "weekNumbers": true,
                "weekNumberCalculation": "ISO",
                "selectable": true,
                "selectMirror": true,
                "buttonIcons": false,
                "views": {
                    "listWeek": {
                        "buttonText": "list week"
                    },
                    "listMonth": {
                        "buttonText": "list month"
                    },
                    "listDay": {
                        "buttonText": "list day"
                    }
                },
                eventRender: function (info) {
                    var tooltip = new Tooltip(info.el, {
                        title: info.event.extendedProps.description,
                        placement: 'top',
                        trigger: 'hover',
                        container: 'body'
                    });
                }
            }
        );
        calendar.render();
        calendarTracker['Calendar-c43nxqpi'] = calendar;
    }); 
</script>

我已经根据它的 html ID 使用密钥存储了这个日历对象。

calendarTracker['Calendar-c43nxqpi'] = calendar;

终于在标签切换上了

<script type="text/javascript">var tabs = tabbis.init({
    tabGroup: "[data-tabs]",
    paneGroup: "[data-panes]",
    tabActive: "active",
    paneActive: "active",
    callback: function (tab, pane) {
        // We need to make same thing for calendar
        function redrawCalendar(calendar) {
            //console.log(calendarTracker[calendar.id].view);
            calendarTracker[calendar.id].changeView(calendarTracker[calendar.id].view.type);
            console.log('Redrawing view for' + calendar.id)
        }

        try {
            var calendar = document.getElementById(tab.id + "-Content").querySelectorAll('div[id^="Calendar-"]');
            calendar.forEach(redrawCalendar)
        } catch (e) {
            console.log('No calendars available.');
        }
    }
});

// in theory should take care of removing local storage for tabbis
// some errors occurs if the local storage is not cleaned after a while
window.addEventListener("unload", tabbis.remove, false);
</script>

我基本上是使用 querySelectorAll 在给定的选项卡上找到所有日历,然后对于选项卡上的每个日历我是 运行 redrawCalendar 函数,该函数基于 HTML DOM ID 找到正确的日历对象,并重置其视图以确保视觉部分已启动并再次 运行。