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>
感谢@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.)
- 我无法使用查询 DOM 对象并将其以某种方式传递给 FullCalendar,就像我尝试做的那样
- 我实际上要做的是创建对象 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects 并存储相关的 JS 对象。
在最顶部定义了空对象
<!-- 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 找到正确的日历对象,并重置其视图以确保视觉部分已启动并再次 运行。
我有一个带有显示 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
.
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>
感谢@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.)
- 我无法使用查询 DOM 对象并将其以某种方式传递给 FullCalendar,就像我尝试做的那样
- 我实际上要做的是创建对象 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects 并存储相关的 JS 对象。
在最顶部定义了空对象
<!-- 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 找到正确的日历对象,并重置其视图以确保视觉部分已启动并再次 运行。