jQuery Removal

Adam Shaw edited this page Mar 13, 2018 · 1 revision

The first milestone is to create:

  • object-oriented initialization API
  • everywhere the API exposes jQuery objects should now expose raw DOM nodes
  • everywhere the API exposes jQuery Event objects should now expose native JavaScript Events.

This is considered a breaking API change and will warrant a bump to the next major version. Depending on how fast this project gets done, I'd like to bundle other breaking API changes into the next major release as well. In fact, I'd like to revamp a lot of settings and callbacks, in addition to revamping how timezones and ambiguous moments work.

Here are the major subprojects for the conversion:

  • replacing use of jQuery's $.ajax
  • removing lots of jQuery utility methods like $.each and $.grep
  • and of course, replacing all jQuery DOM operations and event-handling

I envision the very last step being the removal of the $().fullCalendar initializer and the $.fullCalendar root namespace.

Technical Approach Tidbits

Removal of jQuery's AJAX system begs the question: do we want to start introducing additional dependencies to do the heavy lifting of the vacant functionality?

I want to err on the side of keep dependencies really light, even rolling our own basic utilites if we need to. But providing hooks in the API if people want to do more advanced stuff. For example, instead of introducing axios to handle AJAX, we'll make use of a really light XHR wrapper instead (like xhr) but give people the option to use axios by leveraging the events callback, which might need tweaking to improve ease of use for this scenario.

Many third party libs these days rely on polyfills, especially a Promise polyfill. I'd like to avoid using these until FullCalendar drops support for IE <= 11. We can just use callbacks instead of Promises for now.

Tests Tests Tests!

Completing the first milestone will entail all tests passing! This will require modifications to a lot of the existing tests!

Tests will need to compensate for the API changes described above, but tests can continue to use jQuery, jasmine-jquery, and jquery simulate! These are considered test utilities. jQuery will be moved from a dependency to a dev dependency.

One exception is our use of jquery-mockjax. This is tied into jQuery's $.ajax system, which will be removed, so we'll need to mock XMLHttpRequest instead (maybe with this).

How to rewrite legacy initialization calls in tests

First, please glance at the general article for Writing Automated Tests.

Because the $().fullCalendar() initialization method will no longer be available, tests will need to compensate. This will be the first struggle in adapting the existing tests. Fortunately, there's already a system in place. Sadly, it will be a rather tedious process.

Look at this file: tests/legacy/background-events.js

See how there's an affix() to attach the DOM node, and there's an options object, and the describe and it statements accumulate values onto the options object? And then it gets passed into the $().fullCalendar constructor?

Well, here's an example of the more modern way to do it: tests/view-dates/dateAlignment.js

  • pushOptions(options) - will cause all initCalendar calls within the current describe block to receive these options. CANNOT be used within an it() statement. For that, pass options into initCalendar instead...
  • initCalendar(options?) - will initialize the calendar with the accumulated options. You can also optionally pass in additional options.

There are also some more advanced techniques. These methods let you iterate through parallel sets of options:

  • describeOptions(optionName, descriptionAndValueHash, callback) - example
  • describeOptions(descriptionAndOptionsHash, callback) - example
  • describeTimezones(callback) - like describeOptions, but preconfigured to do the 4 different types of timezones
  • describeValues(hash, callback) - like describeOptions, but simply iterates over the given hash and makes implicit describe statements. does not accumulate options.

For methods calls, something like this...

$('#cal').fullCalendar('updateEvent', eventObj);

Will become this...


As you can see, the currentCalendar object is available for you in any it() statement.

To access the current calendar's DOM nodes, take something that was previously like this:

var slats = $('#cal .fc-slat');

And convert it to this:

var slats = $(currentCalendar.el).find('.fc-slats');
// please wrap currentCalendar.el in $() as it won't always be a jQuery object

References to spyOn that look like this:

it('receives correct args AND can modify the element', function(done) {
	options.events = [ {
		title: 'my event',
		start: '2014-11-12T09:00:00'
	} ];
	options.eventRender = function(event, element, view) {
		element.css('font-size', '20px');
	spyOn(options, 'eventRender').and.callThrough();

Will become this...

it('receives correct args AND can modify the element', function(done) {
	var options = {
		events: [ {
			title: 'my event',
			start: '2014-11-12T09:00:00'
		} ],
		eventRender: function(event, element, view) {
			element.css('font-size', '20px');
	spyOn(options, 'eventRender').and.callThrough();

Here is an example of a conversion: https://github.com/fullcalendar/fullcalendar/commit/1c673b658a849ddd082c634697d41d79abd3d48f

If you'd like to help, please email arshaw at fullcalendar.io and join the Google Group: https://groups.google.com/forum/#!forum/fullcalendar

To keep track on who's working on what (in terms of converting $().fullCalendar() calls in legacy tests), use this spreadsheet (you'll get write access when you join the Google Group):

Spreadsheet: Converting Constructors in Legacy Tests

Please keep all these renovated test files in the tests/legacy/ directory for now.

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.