Răsfoiți Sursa

more formal model parsing system for EventSource

Adam Shaw 8 ani în urmă
părinte
comite
787d78a1fb

+ 41 - 22
src/gcal/GcalEventSource.js

@@ -157,6 +157,29 @@ var GcalEventSource = EventSource.extend({
 
 	getPrimitive: function() {
 		return this.googleCalendarId;
+	},
+
+
+	applyManualRawProps: function(rawProps) {
+		var superSuccess = EventSource.prototype.applyManualRawProps.apply(this, arguments);
+		var googleCalendarId = rawProps.googleCalendarId;
+
+		if (googleCalendarId == null && rawProps.url) {
+			googleCalendarId = parseGoogleCalendarId(rawProps.url);
+		}
+
+		if (googleCalendarId != null) {
+			this.googleCalendarId = googleCalendarId;
+
+			return superSuccess;
+		}
+
+		return false;
+	},
+
+
+	applyOtherRawProps: function(rawProps) {
+		this.ajaxSettings = rawProps;
 	}
 
 });
@@ -165,36 +188,32 @@ var GcalEventSource = EventSource.extend({
 GcalEventSource.API_BASE = 'https://www.googleapis.com/calendar/v3/calendars';
 
 
+GcalEventSource.allowRawProps({
+	// manually process...
+	url: false,
+	googleCalendarId: false,
+
+	// automatically transfer...
+	googleCalendarApiKey: true,
+	googleCalendarError: true
+});
+
+
 GcalEventSource.parse = function(rawInput, calendar) {
 	var rawProps;
-	var url;
-	var googleCalendarId;
-	var source;
 
-	if (typeof rawInput === 'string') {
-		url = rawInput;
-		rawProps = {};
+	if (typeof rawInput === 'object') { // long form. might fail in applyManualRawProps
+		rawProps = rawInput;
 	}
-	else if (typeof rawInput === 'object') {
-		rawProps = $.extend({}, rawInput); // clone
-		url = pluckProp(rawProps, 'url');
-		googleCalendarId = pluckProp(rawProps, 'googleCalendarId');
+	else if (typeof rawInput === 'string') { // short form
+		rawProps = { url: rawInput }; // url will be parsed with parseGoogleCalendarId
 	}
 
-	if (!googleCalendarId && url) {
-		googleCalendarId = parseGoogleCalendarId(url);
+	if (rawProps) {
+		return EventSource.parse.call(this, rawProps, calendar);
 	}
 
-	if (googleCalendarId) {
-		source = EventSource.parseAndPluck.call(this, rawProps, calendar);
-
-		source.googleCalendarId = googleCalendarId;
-		source.googleCalendarApiKey = pluckProp(rawProps, 'googleCalendarApiKey');
-		source.googleCalendarError = pluckProp(rawProps, 'googleCalendarError');
-		source.ajaxSettings = rawProps; // remainder
-
-		return source;
-	}
+	return false;
 };
 
 

+ 24 - 14
src/models/event-source/ArrayEventSource.js

@@ -56,31 +56,41 @@ var ArrayEventSource = EventSource.extend({
 
 	getPrimitive: function() {
 		return this.rawEventDefs;
+	},
+
+
+	applyManualRawProps: function(rawProps) {
+		var superSuccess = EventSource.prototype.applyManualRawProps.apply(this, arguments);
+
+		this.setRawEventDefs(rawProps.events);
+
+		return superSuccess;
 	}
 
 });
 
 
+ArrayEventSource.allowRawProps({
+	events: false // don't automatically transfer
+});
+
+
 ArrayEventSource.parse = function(rawInput, calendar) {
-	var rawEventDefs;
-	var rawOtherProps;
-	var source;
+	var rawProps;
 
-	if ($.isArray(rawInput)) {
-		rawEventDefs = rawInput;
-		rawOtherProps = {};
+	// normalize raw input
+	if ($.isArray(rawInput.events)) { // extended form
+		rawProps = rawInput;
 	}
-	else if ($.isArray(rawInput.events)) {
-		rawOtherProps = $.extend({}, rawInput); // copy
-		rawEventDefs = pluckProp(rawOtherProps, 'events');
+	else if ($.isArray(rawInput)) { // short form
+		rawProps = { events: rawInput };
 	}
 
-	if (rawEventDefs) {
-		source = EventSource.parseAndPluck.call(this, rawOtherProps, calendar);
-		source.setRawEventDefs(rawEventDefs);
-
-		return source;
+	if (rawProps) {
+		return EventSource.parse.call(this, rawProps, calendar);
 	}
+
+	return false;
 };
 
 

+ 89 - 35
src/models/event-source/EventSource.js

@@ -63,6 +63,58 @@ var EventSource = Class.extend({
 		}
 
 		return eventDefs;
+	},
+
+
+	standardPropMap: {}, // will be cloned by allowRawProps
+
+
+	/*
+	Returns true/false for success
+	*/
+	applyRawProps: function(rawProps) {
+		var standardPropMap = this.standardPropMap;
+		var manualProps = {};
+		var otherProps = {};
+		var propName;
+
+		for (propName in rawProps) {
+			if (standardPropMap[propName] === true) { // copy automatically
+				this[propName] = rawProps[propName];
+			}
+			else if (standardPropMap[propName] === false) {
+				manualProps[propName] = rawProps[propName];
+			}
+			else {
+				otherProps[propName] = rawProps[propName];
+			}
+		}
+
+		this.applyOtherRawProps(otherProps);
+
+		return this.applyManualRawProps(manualProps);
+	},
+
+
+	/*
+	If subclasses override, they must call this supermethod and return the boolean response.
+	*/
+	applyManualRawProps: function(rawProps) {
+		this.id = EventSource.normalizeId(rawProps.id);
+
+		if ($.isArray(rawProps.className)) {
+			this.className = rawProps.className;
+		}
+		if (typeof rawProps.className === 'string') {
+			this.className = rawProps.className.split(/\s+/);
+		}
+
+		return true;
+	},
+
+
+	applyOtherRawProps: function(rawProps) {
+		// subclasses can implement
 	}
 
 });
@@ -84,47 +136,49 @@ EventSource.normalizeId = function(id) {
 // ---------------------------------------------------------------------------------------------------------------------
 
 
-EventSource.parse = function(rawInput, calendar) {
-	// subclasses must implement
+EventSource.allowRawProps = function(propDefs) {
+	var proto = this.prototype;
+
+	proto.standardPropMap = Object.create(proto.standardPropMap);
+
+	copyOwnProps(propDefs, proto.standardPropMap);
 };
 
 
-EventSource.parseAndPluck = function(rawProps, calendar) {
+EventSource.allowRawProps({
+	// manually process...
+	id: false,
+	className: false,
+
+	// automatically transfer...
+	color: true,
+	backgroundColor: true,
+	borderColor: true,
+	textColor: true,
+	editable: true,
+	startEditable: true,
+	durationEditable: true,
+	rendering: true,
+	overlap: true,
+	constraint: true,
+	allDayDefault: true,
+	eventDataTransform: true
+});
+
+
+/*
+rawInput can be any data type!
+*/
+EventSource.parse = function(rawInput, calendar) {
 	var source = new this(calendar);
-	var members = pluckProps(rawProps, [
-		'id',
-		'color',
-		'backgroundColor',
-		'borderColor',
-		'textColor',
-		'className',
-		'editable',
-		'startEditable',
-		'durationEditable',
-		'resourceEditable',
-		'rendering',
-		'overlap',
-		'constraint',
-		'allDayDefault',
-		'eventDataTransform'
-	]);
-
-	// post-process some soon-to-be member variables...
-
-	members.id = EventSource.normalizeId(members.id);
-
-	// can make DRY with EventDef
-	if (typeof members.className === 'string') {
-		members.className = members.className.split(/\s+/);
-	}
-	else if (!$.isArray(members.className)) {
-		delete members.className; // don't overwrite the empty array
-	}
 
-	// apply the member variables
-	$.extend(source, members);
+	if (typeof rawInput === 'object') {
+		if (source.applyRawProps(rawInput)) {
+			return source;
+		}
+	}
 
-	return source;
+	return false;
 };
 
 

+ 24 - 14
src/models/event-source/FuncEventSource.js

@@ -23,31 +23,41 @@ var FuncEventSource = EventSource.extend({
 
 	getPrimitive: function() {
 		return this.func;
+	},
+
+
+	applyManualRawProps: function(rawProps) {
+		var superSuccess = EventSource.prototype.applyManualRawProps.apply(this, arguments);
+
+		this.func = rawProps.events;
+
+		return superSuccess;
 	}
 
 });
 
 
+FuncEventSource.allowRawProps({
+	events: false // don't automatically transfer
+});
+
+
 FuncEventSource.parse = function(rawInput, calendar) {
-	var func;
-	var rawOtherProps;
-	var source;
+	var rawProps;
 
-	if ($.isFunction(rawInput)) {
-		func = rawInput;
-		rawOtherProps = {};
+	// normalize raw input
+	if ($.isFunction(rawInput.events)) { // extended form
+		rawProps = rawInput;
 	}
-	else if ($.isFunction(rawInput.events)) {
-		rawOtherProps = $.extend({}, rawInput); // copy
-		func = pluckProp(rawOtherProps, 'events');
+	else if ($.isFunction(rawInput)) { // short form
+		rawProps = { events: rawInput };
 	}
 
-	if (func) {
-		source = EventSource.parseAndPluck.call(this, rawOtherProps, calendar);
-		source.func = func;
-
-		return source;
+	if (rawProps) {
+		return EventSource.parse.call(this, rawProps, calendar);
 	}
+
+	return false;
 };
 
 

+ 23 - 13
src/models/event-source/JsonFeedEventSource.js

@@ -99,6 +99,13 @@ var JsonFeedEventSource = EventSource.extend({
 
 	getPrimitive: function() {
 		return this.ajaxSettings.url;
+	},
+
+
+	applyOtherRawProps: function(rawProps) {
+		EventSource.prototype.applyOtherRawProps.apply(this, arguments);
+
+		this.ajaxSettings = rawProps;
 	}
 
 });
@@ -110,27 +117,30 @@ JsonFeedEventSource.AJAX_DEFAULTS = {
 };
 
 
+JsonFeedEventSource.allowRawProps({
+	// automatically transfer (true)...
+	startParam: true,
+	endParam: true,
+	timezoneParam: true
+});
+
+
 JsonFeedEventSource.parse = function(rawInput, calendar) {
 	var rawProps;
-	var source;
 
-	if (typeof rawInput === 'string') {
-		rawProps =  { url: rawInput };
+	// normalize raw input
+	if (typeof rawInput.url === 'string') { // extended form
+		rawProps = rawInput;
 	}
-	else if (typeof rawInput.url === 'string') {
-		rawProps = $.extend({}, rawInput); // copy
+	else if (typeof rawInput === 'string') { // short form
+		rawProps = { url: rawInput }; // will end up in ajaxSettings
 	}
 
 	if (rawProps) {
-		source = EventSource.parseAndPluck.call(this, rawProps, calendar);
-
-		source.startParam = pluckProp(rawProps, 'startParam');
-		source.endParam = pluckProp(rawProps, 'endParam');
-		source.timezoneParam = pluckProp(rawProps, 'timezoneParam');
-		source.ajaxSettings = rawProps; // remainder
-
-		return source;
+		return EventSource.parse.call(this, rawProps, calendar);
 	}
+
+	return false;
 };