Adam Shaw пре 8 година
родитељ
комит
982d6ac274
8 измењених фајлова са 86 додато и 76 уклоњено
  1. 33 2
      src/Calendar.js
  2. 1 1
      src/Calendar.moment.js
  3. 23 49
      src/Calendar.options.js
  4. 6 6
      src/Calendar.render.js
  5. 14 11
      src/Calendar.view-spec.js
  6. 4 3
      src/Toolbar.js
  7. 1 1
      src/locale.js
  8. 4 3
      src/theme/Theme.js

+ 33 - 2
src/Calendar.js

@@ -6,6 +6,7 @@ var Calendar = FC.Calendar = Class.extend(EmitterMixin, ListenerMixin, {
 	currentDate: null, // unzoned moment. private (public API should use getDate instead)
 	theme: null,
 	constraints: null,
+	optionsManager: null,
 	businessHourGenerator: null,
 	loadingLevel: 0, // number of simultaneous loading tasks
 
@@ -20,7 +21,7 @@ var Calendar = FC.Calendar = Class.extend(EmitterMixin, ListenerMixin, {
 		this.viewsByType = {};
 		this.viewSpecCache = {};
 
-		this.initOptionsInternals(overrides);
+		this.optionsManager = new OptionsManager(this, overrides);
 		this.initMomentInternals(); // needs to happen after options hash initialized
 		this.initCurrentDate();
 		this.initEventManager();
@@ -79,6 +80,36 @@ var Calendar = FC.Calendar = Class.extend(EmitterMixin, ListenerMixin, {
 	},
 
 
+	// Options Public API
+	// -----------------------------------------------------------------------------------------------------------------
+
+
+	// public getter/setter
+	option: function(name, value) {
+		var newOptionHash;
+
+		if (typeof name === 'string') {
+			if (value === undefined) { // getter
+				return this.optionsManager.get(name);
+			}
+			else { // setter for individual option
+				newOptionHash = {};
+				newOptionHash[name] = value;
+				this.optionsManager.add(newOptionHash);
+			}
+		}
+		else if (typeof name === 'object') { // compound setter with object input
+			this.optionsManager.add(name);
+		}
+	},
+
+
+	// private getter
+	opt: function(name) {
+		return this.optionsManager.get(name);
+	},
+
+
 	// View
 	// -----------------------------------------------------------------------------------------------------------------
 
@@ -102,7 +133,7 @@ var Calendar = FC.Calendar = Class.extend(EmitterMixin, ListenerMixin, {
 		if (dateOrRange) {
 
 			if (dateOrRange.start && dateOrRange.end) { // a range
-				this.recordOptionOverrides({ // will not rerender
+				this.optionsManager.recordOverrides({ // will not rerender
 					visibleRange: dateOrRange
 				});
 			}

+ 1 - 1
src/Calendar.moment.js

@@ -14,7 +14,7 @@ Calendar.mixin({
 
 		// Called immediately, and when any of the options change.
 		// Happens before any internal objects rebuild or rerender, because this is very core.
-		this.optionsModel.watch('buildingMomentLocale', [
+		this.optionsManager.watch('buildingMomentLocale', [
 			'?locale', '?monthNames', '?monthNamesShort', '?dayNames', '?dayNamesShort',
 			'?firstDay', '?weekNumberCalculation'
 		], function(opts) {

+ 23 - 49
src/Calendar.options.js

@@ -1,55 +1,28 @@
-/*
-Options binding/triggering system.
-*/
-Calendar.mixin({
 
+var OptionsManager = Model.extend({
+
+	_calendar: null, // avoid
 	dirDefaults: null, // option defaults related to LTR or RTL
 	localeDefaults: null, // option defaults related to current locale
 	overrides: null, // option overrides given to the fullCalendar constructor
 	dynamicOverrides: null, // options set with dynamic setter method. higher precedence than view overrides.
-	optionsModel: null, // all defaults combined with overrides
 
 
-	initOptionsInternals: function(overrides) {
+	constructor: function(_calendar, overrides) {
+		Model.call(this); // super
+
+		this._calendar = _calendar;
 		this.overrides = $.extend({}, overrides); // make a copy
 		this.dynamicOverrides = {};
-		this.optionsModel = new Model();
-
-		this.populateOptionsHash();
+		this.compute();
 	},
 
 
-	// public getter/setter
-	option: function(name, value) {
-		var newOptionHash;
-
-		if (typeof name === 'string') {
-			if (value === undefined) { // getter
-				return this.optionsModel.get(name);
-			}
-			else { // setter for individual option
-				newOptionHash = {};
-				newOptionHash[name] = value;
-				this.setOptions(newOptionHash);
-			}
-		}
-		else if (typeof name === 'object') { // compound setter with object input
-			this.setOptions(name);
-		}
-	},
-
-
-	// private getter
-	opt: function(name) {
-		return this.optionsModel.get(name);
-	},
-
-
-	setOptions: function(newOptionHash) {
+	add: function(newOptionHash) { // was setOptions
 		var optionCnt = 0;
 		var optionName;
 
-		this.recordOptionOverrides(newOptionHash); // will trigger optionsModel watchers
+		this.recordOverrides(newOptionHash); // will trigger this model's watchers
 
 		for (optionName in newOptionHash) {
 			optionCnt++;
@@ -59,36 +32,36 @@ Calendar.mixin({
 		// if only one option change, `optionName` will be its name.
 		if (optionCnt === 1) {
 			if (optionName === 'height' || optionName === 'contentHeight' || optionName === 'aspectRatio') {
-				this.updateViewSize(true); // isResize=true
+				this._calendar.updateViewSize(true); // isResize=true
 				return;
 			}
 			else if (optionName === 'defaultDate') {
 				return; // can't change date this way. use gotoDate instead
 			}
 			else if (optionName === 'businessHours') {
-				return; // optionsModel already reacts to this
+				return; // this model already reacts to this
 			}
 			else if (optionName === 'timezone') {
-				this.view.flash('initialEvents');
+				this._calendar.view.flash('initialEvents');
 				return;
 			}
 		}
 
 		// catch-all. rerender the header and footer and rebuild/rerender the current view
-		this.renderHeader();
-		this.renderFooter();
+		this._calendar.renderHeader();
+		this._calendar.renderFooter();
 
 		// even non-current views will be affected by this option change. do before rerender
 		// TODO: detangle
-		this.viewsByType = {};
+		this._calendar.viewsByType = {};
 
-		this.reinitView();
+		this._calendar.reinitView();
 	},
 
 
 	// Computes the flattened options hash for the calendar and assigns to `this.options`.
 	// Assumes this.overrides and this.dynamicOverrides have already been initialized.
-	populateOptionsHash: function() {
+	compute: function() {
 		var locale, localeDefaults;
 		var isRTL, dirDefaults;
 		var rawOptions;
@@ -123,20 +96,21 @@ Calendar.mixin({
 		]);
 		populateInstanceComputableOptions(rawOptions); // fill in gaps with computed options
 
-		this.optionsModel.reset(rawOptions);
+		this.reset(rawOptions);
 	},
 
 
 	// stores the new options internally, but does not rerender anything.
-	recordOptionOverrides: function(newOptionHash) {
+	recordOverrides: function(newOptionHash) {
 		var optionName;
 
 		for (optionName in newOptionHash) {
 			this.dynamicOverrides[optionName] = newOptionHash[optionName];
 		}
 
-		this.viewSpecCache = {}; // the dynamic override invalidates the options in this cache, so just clear it
-		this.populateOptionsHash(); // this.options needs to be recomputed after the dynamic override
+		this._calendar.viewSpecCache = {}; // the dynamic override invalidates the options in this cache, so just clear it
+		this.compute(); // this.options needs to be recomputed after the dynamic override
 	}
 
+
 });

+ 6 - 6
src/Calendar.render.js

@@ -49,9 +49,9 @@ Calendar.mixin({
 		});
 
 		// called immediately, and upon option change
-		this.optionsModel.watch('settingTheme', [ '?theme', '?themeSystem' ], function(opts) {
+		this.optionsManager.watch('settingTheme', [ '?theme', '?themeSystem' ], function(opts) {
 			var themeClass = ThemeRegistry.getThemeClass(opts.themeSystem || opts.theme);
-			var theme = new themeClass(_this.optionsModel);
+			var theme = new themeClass(_this.optionsManager);
 			var widgetClass = theme.getClass('widget');
 
 			_this.theme = theme;
@@ -69,7 +69,7 @@ Calendar.mixin({
 			}
 		});
 
-		this.optionsModel.watch('settingBusinessHourGenerator', [ '?businessHours' ], function(deps) {
+		this.optionsManager.watch('settingBusinessHourGenerator', [ '?businessHours' ], function(deps) {
 			_this.businessHourGenerator = new BusinessHourGenerator(deps.businessHours, _this);
 
 			if (_this.view) {
@@ -81,7 +81,7 @@ Calendar.mixin({
 
 		// called immediately, and upon option change.
 		// HACK: locale often affects isRTL, so we explicitly listen to that too.
-		this.optionsModel.watch('applyingDirClasses', [ '?isRTL', '?locale' ], function(opts) {
+		this.optionsManager.watch('applyingDirClasses', [ '?isRTL', '?locale' ], function(opts) {
 			el.toggleClass('fc-ltr', !opts.isRTL);
 			el.toggleClass('fc-rtl', opts.isRTL);
 		});
@@ -114,8 +114,8 @@ Calendar.mixin({
 		this.el.removeClass('fc fc-ltr fc-rtl');
 
 		// removes theme-related root className
-		this.optionsModel.unwatch('settingTheme');
-		this.optionsModel.unwatch('settingBusinessHourGenerator');
+		this.optionsManager.unwatch('settingTheme');
+		this.optionsManager.unwatch('settingBusinessHourGenerator');
 
 		this.el.off('.fc'); // unbind nav link handlers
 

+ 14 - 11
src/Calendar.view-spec.js

@@ -41,7 +41,7 @@ Calendar.mixin({
 
 	// Builds an object with information on how to create a given view
 	buildViewSpec: function(requestedViewType) {
-		var viewOverrides = this.overrides.views || {};
+		var viewOverrides = this.optionsManager.overrides.views || {};
 		var specChain = []; // for the view. lowest to highest priority
 		var defaultsChain = []; // for the view. lowest to highest priority
 		var overridesChain = []; // for the view. lowest to highest priority
@@ -84,8 +84,8 @@ Calendar.mixin({
 
 		// fall back to top-level `duration` option
 		durationInput = durationInput ||
-			this.dynamicOverrides.duration ||
-			this.overrides.duration;
+			this.optionsManager.dynamicOverrides.duration ||
+			this.optionsManager.overrides.duration;
 
 		if (durationInput) {
 			duration = moment.duration(durationInput);
@@ -118,14 +118,16 @@ Calendar.mixin({
 
 	// Builds and assigns a view spec's options object from its already-assigned defaults and overrides
 	buildViewSpecOptions: function(spec) {
+		var optionsManager = this.optionsManager;
+
 		spec.options = mergeOptions([ // lowest to highest priority
 			Calendar.defaults, // global defaults
 			spec.defaults, // view's defaults (from ViewSubclass.defaults)
-			this.dirDefaults,
-			this.localeDefaults, // locale and dir take precedence over view's defaults!
-			this.overrides, // calendar's overrides (options given to constructor)
+			optionsManager.dirDefaults,
+			optionsManager.localeDefaults, // locale and dir take precedence over view's defaults!
+			optionsManager.overrides, // calendar's overrides (options given to constructor)
 			spec.overrides, // view's overrides (view-specific options)
-			this.dynamicOverrides // dynamically set via setter. highest precedence
+			optionsManager.dynamicOverrides // dynamically set via setter. highest precedence
 		]);
 		populateInstanceComputableOptions(spec.options);
 	},
@@ -133,6 +135,7 @@ Calendar.mixin({
 
 	// Computes and assigns a view spec's buttonText-related options
 	buildViewSpecButtonText: function(spec, requestedViewType) {
+		var optionsManager = this.optionsManager;
 
 		// given an options object with a possible `buttonText` hash, lookup the buttonText for the
 		// requested view, falling back to a generic unit entry like "week" or "day"
@@ -147,14 +150,14 @@ Calendar.mixin({
 
 		// highest to lowest priority
 		spec.buttonTextOverride =
-			queryButtonText(this.dynamicOverrides) ||
-			queryButtonText(this.overrides) || // constructor-specified buttonText lookup hash takes precedence
+			queryButtonText(optionsManager.dynamicOverrides) ||
+			queryButtonText(optionsManager.overrides) || // constructor-specified buttonText lookup hash takes precedence
 			spec.overrides.buttonText; // `buttonText` for view-specific options is a string
 
 		// highest to lowest priority. mirrors buildViewSpecOptions
 		spec.buttonTextDefault =
-			queryButtonText(this.localeDefaults) ||
-			queryButtonText(this.dirDefaults) ||
+			queryButtonText(optionsManager.localeDefaults) ||
+			queryButtonText(optionsManager.dirDefaults) ||
 			spec.defaults.buttonText || // a single string. from ViewSubclass.defaults
 			queryButtonText(Calendar.defaults) ||
 			(spec.duration ? this.humanizeDuration(spec.duration) : null) || // like "3 days"

+ 4 - 3
src/Toolbar.js

@@ -58,11 +58,12 @@ function Toolbar(calendar, toolbarOptions) {
 
 	function renderSection(position) {
 		var theme = calendar.theme;
+		var optionsManager = calendar.optionsManager;
 		var sectionEl = $('<div class="fc-' + position + '"/>');
 		var buttonStr = toolbarOptions.layout[position];
-		var calendarCustomButtons = calendar.opt('customButtons') || {};
-		var calendarButtonTextOverrides = calendar.overrides.buttonText || {};
-		var calendarButtonText = calendar.opt('buttonText') || {};
+		var calendarCustomButtons = optionsManager.get('customButtons') || {};
+		var calendarButtonTextOverrides = optionsManager.overrides.buttonText || {};
+		var calendarButtonText = optionsManager.get('buttonText') || {};
 
 		if (buttonStr) {
 			$.each(buttonStr.split(' '), function(i) {

+ 1 - 1
src/locale.js

@@ -176,7 +176,7 @@ var instanceComputableOptions = {
 
 };
 
-// TODO: make these computable properties in optionsModel
+// TODO: make these computable properties in optionsManager
 function populateInstanceComputableOptions(options) {
 	$.each(instanceComputableOptions, function(name, func) {
 		if (options[name] == null) {

+ 4 - 3
src/theme/Theme.js

@@ -1,6 +1,7 @@
 
 var Theme = FC.Theme = Class.extend({
 
+	optionsManager: null,
 	classes: {},
 	iconClasses: {},
 	baseIconClass: '',
@@ -9,8 +10,8 @@ var Theme = FC.Theme = Class.extend({
 	iconOverridePrefix: '',
 
 
-	constructor: function(optionsModel) {
-		this.optionsModel = optionsModel;
+	constructor: function(optionsManager) {
+		this.optionsManager = optionsManager;
 		this.processIconOverride();
 	},
 
@@ -18,7 +19,7 @@ var Theme = FC.Theme = Class.extend({
 	processIconOverride: function() {
 		if (this.iconOverrideOption) {
 			this.setIconOverride(
-				this.optionsModel.get(this.iconOverrideOption)
+				this.optionsManager.get(this.iconOverrideOption)
 			);
 		}
 	},