diff --git a/Gruntfile.js b/Gruntfile.js
index 275e7b9..844bc7d 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -1,8 +1,10 @@
var _ = require('underscore');
+
module.exports = function(grunt) {
+
// Load required NPM tasks.
// You must first run `npm install` in the project's root directory to get these dependencies.
grunt.loadNpmTasks('grunt-contrib-concat');
@@ -10,33 +12,28 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-compress');
grunt.loadNpmTasks('grunt-contrib-clean');
- grunt.loadNpmTasks('grunt-contrib-watch'); // Very useful for development. See README.
+ var fileIndex = require('./files.js'); // lists of source/dependency files
+ var loaderUtils = require('./build/loader.js');
+
// read config files, and combine into one "meta" object
var packageConfig = grunt.file.readJSON('package.json');
var componentConfig = grunt.file.readJSON('component.json');
var pluginConfig = grunt.file.readJSON('fullcalendar.jquery.json');
var meta = _.extend({}, packageConfig, componentConfig, pluginConfig);
-
- var config = { // this will eventually get passed to grunt.initConfig
+ // this will eventually get passed to grunt.initConfig
+ var config = {
meta: meta, // do this primarily for templating (<%= %>)
-
- // initialize multitasks
- concat: {},
+ concat: {}, // initialize multitasks...
uglify: {},
copy: {},
compress: {},
- clean: {},
- watch: {} // we will add watch tasks whenever we do concats, so files get re-concatenated upon save
+ clean: {}
};
- // files that the demos might need in the distributable
- var depFiles = require('./build/deps.js');
-
-
/* Important Top-Level Tasks
----------------------------------------------------------------------------------------------------*/
@@ -44,125 +41,51 @@ module.exports = function(grunt) {
grunt.registerTask('dist', 'Create a distributable ZIP file', [
'clean:build',
- 'submodules',
+ 'concat',
'uglify',
- 'copy:deps',
+ 'copy:dependencies',
'copy:demos',
'copy:misc',
'compress'
]);
- grunt.registerTask('dev', 'Build necessary files for developing and debugging', 'submodules');
- grunt.registerTask('submodules', 'Build all FullCalendar submodules', [
- 'main',
- 'gcal'
- ]);
-
-
- /* Main FullCalendar Submodule
+ /* Concatenate Submodules
----------------------------------------------------------------------------------------------------*/
- grunt.registerTask('main', 'Build the main FullCalendar submodule', [
- 'concat:mainJs',
- 'concat:mainCss',
- 'concat:mainPrintCss'
- ]);
+ _.each(fileIndex.fullcalendar, function(submodule, name) {
- // JavaScript
+ if (submodule.js) {
+ config.concat[name + '-js'] = {
+ options: {
+ process: true // replace template variables
+ },
+ src: submodule.js,
+ dest: 'build/out/fullcalendar/' + name + '.js'
+ };
+ }
- config.concat.mainJs = {
- options: {
- process: true // replace template variables
- },
- src: [
- 'src/intro.js',
- 'src/defaults.js',
- 'src/main.js',
- 'src/Calendar.js',
- 'src/Header.js',
- 'src/EventManager.js',
- 'src/date_util.js',
- 'src/util.js',
- 'src/basic/MonthView.js',
- 'src/basic/BasicWeekView.js',
- 'src/basic/BasicDayView.js',
- 'src/basic/BasicView.js',
- 'src/basic/BasicEventRenderer.js',
- 'src/agenda/AgendaWeekView.js',
- 'src/agenda/AgendaDayView.js',
- 'src/agenda/AgendaView.js',
- 'src/agenda/AgendaEventRenderer.js',
- 'src/common/View.js',
- 'src/common/DayEventRenderer.js',
- 'src/common/SelectionManager.js',
- 'src/common/OverlayManager.js',
- 'src/common/CoordinateGrid.js',
- 'src/common/HoverListener.js',
- 'src/common/HorizontalPositionCache.js',
- 'src/outro.js'
- ],
- dest: 'build/out/fullcalendar/fullcalendar.js'
- };
+ if (submodule.css) {
+ config.concat[name + '-css'] = {
+ options: {
+ process: true // replace template variables
+ },
+ src: submodule.css,
+ dest: 'build/out/fullcalendar/' + name + '.css'
+ };
+ }
- config.watch.mainJs = {
- files: config.concat.mainJs.src,
- tasks: 'concat:mainJs'
- };
+ if (submodule.printCss) {
+ config.concat[name + '-print-css'] = {
+ options: {
+ process: true // replace template variables
+ },
+ src: submodule.printCss,
+ dest: 'build/out/fullcalendar/' + name + '.print.css'
+ };
+ }
- // CSS
-
- config.concat.mainCss = {
- options: {
- process: true // replace template variables
- },
- src: [
- 'src/main.css',
- 'src/common/common.css',
- 'src/basic/basic.css',
- 'src/agenda/agenda.css'
- ],
- dest: 'build/out/fullcalendar/fullcalendar.css'
- };
-
- config.watch.mainCss = {
- files: config.concat.mainCss.src,
- tasks: 'concat:mainCss'
- };
-
- // CSS (for printing)
-
- config.concat.mainPrintCss = {
- options: {
- process: true // replace template variables
- },
- src: 'src/common/print.css',
- dest: 'build/out/fullcalendar/fullcalendar.print.css'
- };
-
- config.watch.mainPrintCss = {
- files: config.concat.mainPrintCss.src,
- tasks: 'concat:mainPrintCss'
- };
-
-
- /* Google Calendar Submodule
- ----------------------------------------------------------------------------------------------------*/
-
- grunt.registerTask('gcal', 'Build the Google Calendar submodule', 'concat:gcalJs');
-
- config.concat.gcalJs = {
- options: {
- process: true // replace template variables
- },
- src: 'src/gcal/gcal.js',
- dest: 'build/out/fullcalendar/gcal.js'
- };
-
- config.watch.gcalJs = {
- files: config.concat.gcalJs.src,
- tasks: 'concat:gcalJs'
- };
+ });
/* Minify the JavaScript
@@ -173,7 +96,7 @@ module.exports = function(grunt) {
preserveComments: 'some' // keep comments starting with /*!
},
expand: true,
- src: 'build/out/fullcalendar/fullcalendar.js',
+ src: 'build/out/fullcalendar/*.js',
ext: '.min.js'
}
@@ -181,12 +104,14 @@ module.exports = function(grunt) {
/* Copy Dependencies
----------------------------------------------------------------------------------------------------*/
- config.copy.deps = {
+ config.copy.dependencies = {
expand: true,
flatten: true,
- src: depFiles,
- dest: 'build/out/jquery/' // all depenencies will go in the jquery/ directory for now
- // (because we only have jquery and jquery-ui)
+ src: [
+ fileIndex['jquery'].js,
+ fileIndex['jquery-ui'].js
+ ],
+ dest: 'build/out/jquery/'
};
@@ -195,11 +120,15 @@ module.exports = function(grunt) {
config.copy.demos = {
options: {
- // while copying demo files over, rewrite "); // all dependencies are in jquery/ for now
- }
- return tags.join("\n");
- }
-
/* Copy Misc Files
----------------------------------------------------------------------------------------------------*/
@@ -272,11 +166,11 @@ module.exports = function(grunt) {
grunt.registerTask('component', 'Build the FullCalendar component for the Bower package manager', [
'clean:component',
- 'submodules',
+ 'concat',
'uglify', // we want the minified JS in there
'copy:component',
- 'copy:componentReadme',
- 'componentConfig'
+ 'copy:component-readme',
+ 'component.json'
]);
config.copy.component = {
@@ -286,12 +180,12 @@ module.exports = function(grunt) {
dest: 'build/component/',
};
- config.copy.componentReadme = {
+ config.copy['component-readme'] = {
src: 'build/component-readme.md',
dest: 'build/component/readme.md'
};
- grunt.registerTask('componentConfig', function() {
+ grunt.registerTask('component.json', function() {
grunt.file.write(
'build/component/component.json',
JSON.stringify(
diff --git a/build/deps.js b/build/deps.js
deleted file mode 100644
index 13cb07e..0000000
--- a/build/deps.js
+++ /dev/null
@@ -1,53 +0,0 @@
-
-/*
- * This file defines the JS dependencies required to run a barebones FullCalendar example.
- *
- * Additionally, if run from Node (i.e. the build system), this file will serve as a module that
- * exports the dependency file list.
- *
- * Additionally, if run from a browser, this file will write a \n");
- }
-
-}
\ No newline at end of file
diff --git a/build/loader.js b/build/loader.js
new file mode 100644
index 0000000..a1568b5
--- /dev/null
+++ b/build/loader.js
@@ -0,0 +1,312 @@
+(function() {
+
+
+/*
+ * Modules that will be implicitly included
+ */
+var DEFAULT_MODULES = [ 'jquery', 'jquery-ui', 'fullcalendar'/*the submodule*/ ];
+
+
+/*
+ * Generate HTML script/link tags for loading resources.
+ *
+ * @param {String} root
+ * Path to the project or distributable's root directory from the HTML file running this script.
+ *
+ * @param {Object} fileIndex
+ * File location information for each module/submodule (everything in files.js).
+ *
+ * @param {String} moduleString
+ * A comma-separated string with names of additional modules to load.
+ *
+ * @param {string} [buildType]
+ * unspecified - use source JS/CSS files
+ * "concat" - use concatenated JS/CSS files
+ * "min" - use minified JS files, concatenated CSS files
+ * "dist" - use minified JS files, concatenated CSS files, and write paths for distributable
+ */
+function buildTags(root, fileIndex, moduleString, buildType) {
+
+ var extraModuleNames = moduleString ? moduleString.split(',') : [];
+ var moduleNames = DEFAULT_MODULES.concat(extraModuleNames);
+
+ var jsPaths = [];
+ var cssPaths = [];
+ var printCssPaths = [];
+
+ var buildRoot;
+ if (buildType == 'dist') {
+ buildRoot = root; // in the distributable, the build root IS the root
+ }
+ else {
+ buildRoot = root + '/build/out';
+ }
+
+ each(moduleNames, function(moduleName) {
+
+ var submodule = fileIndex.fullcalendar[moduleName];
+ var module = submodule || fileIndex[moduleName];
+
+ if (module) {
+
+ var js = arrayify(module.js);
+ var css = arrayify(module.css);
+ var printCss = arrayify(module.printCss);
+
+ if (buildType && submodule) {
+ //
+ // paths for a "built" fullcalendar submodule
+ //
+ if (js.length) {
+ jsPaths.push(buildRoot + '/fullcalendar/' + moduleName + (buildType == 'concat' ? '' : '.min') + '.js');
+ }
+ if (css.length) {
+ cssPaths.push(buildRoot + '/fullcalendar/' + moduleName + '.css');
+ }
+ if (printCss.length) {
+ printCssPaths.push(buildRoot + '/fullcalendar/' + moduleName + '.print.css');
+ }
+ }
+ else if (buildType == 'dist' && !submodule) {
+ //
+ // 3rd-party paths in the distributable (they all go in jquery/ for now)
+ //
+ each(js, function(path) {
+ jsPaths.push(buildRoot + '/jquery/' + basename(path));
+ });
+ each(css, function(path) {
+ cssPaths.push(buildRoot + '/jquery/' + basename(path));
+ });
+ each(printCss, function(path) {
+ printCssPaths.push(buildRoot + '/jquery/' + basename(path));
+ });
+ }
+ else {
+ //
+ // paths for development
+ //
+ each(js, function(path) {
+ if (!/(intro|outro)\.js$/.test(path)) { // don't write syntactically incorrect intro.js/outro.js
+ jsPaths.push(root + '/' + path);
+ }
+ });
+ each(css, function(path) {
+ cssPaths.push(root + '/' + path);
+ });
+ each(printCss, function(path) {
+ printCssPaths.push(root + '/' + path);
+ });
+ }
+ }
+ });
+
+ return [].concat(
+ map(cssPaths, buildCssTag),
+ map(printCssPaths, buildPrintCssTag),
+ map(jsPaths, buildJsTag)
+ )
+ .join('\n');
+}
+
+
+/* When run in a browser...
+====================================================================================================*/
+
+
+/*
+ * Writes script/link tags for resources.
+ * Attributes can be added to loader.js's script tag to change its behavior:
+ * data-modules="..." (a comma-separated list of additional modules to load)
+ * data-debug="true"
+ */
+function run() {
+
+ var thisScript = getLastScript();
+ var src = thisScript.getAttribute('src');
+ var cwd = dirname(src);
+ var projectRoot = dirname(cwd);
+ var moduleString = thisScript.getAttribute('data-modules');
+ var debugEnabled = !!thisScript.getAttribute('data-debug');
+ var buildType = getQueryStringVar('build');
+
+ if (debugEnabled) {
+ buildType = buildType || getCookieVar('build'); // fall back to cookie
+ initDebug(buildType);
+ }
+
+ loadScript(projectRoot + '/files.js', function(fileIndex) {
+ document.write(
+ buildTags(projectRoot, fileIndex, moduleString, buildType)
+ );
+ });
+}
+
+
+/*
+ * Installs a build-switching