text: 
  fc.applyAll = applyAll;
  
  
  /* Event Date Math
  -----------------------------------------------------------------------------*/
  
  
  function exclEndDay(event) {
  	if (event.end) {
  		return _exclEndDay(event.end, event.allDay);
  	}else{
  		return addDays(cloneDate(event.start), 1);
  	}
  }
  
  
  function _exclEndDay(end, allDay) {
  	end = cloneDate(end);
  	return allDay || end.getHours() || end.getMinutes() ? addDays(end, 1) : clearTime(end);
  }
  
  
  function segCmp(a, b) {
  	return (b.msLength - a.msLength) * 100 + (a.event.start - b.event.start);
  }
  
  
  function segsCollide(seg1, seg2) {
  	return seg1.end > seg2.start && seg1.start < seg2.end;
  }
  
  
  
  /* Event Sorting
  -----------------------------------------------------------------------------*/
  
  
  // event rendering utilities
  function sliceSegs(events, visEventEnds, start, end) {
  	var segs = [],
  		i, len=events.length, event,
  		eventStart, eventEnd,
  		segStart, segEnd,
  		isStart, isEnd;
  	for (i=0; i<len; i++) {
  		event = events[i];
  		eventStart = event.start;
  		eventEnd = visEventEnds[i];
  		if (eventEnd > start && eventStart < end) {
  			if (eventStart < start) {
  				segStart = cloneDate(start);
  				isStart = false;
  			}else{
  				segStart = eventStart;
  				isStart = true;
  			}
  			if (eventEnd > end) {
  				segEnd = cloneDate(end);
  				isEnd = false;
  			}else{
  				segEnd = eventEnd;
  				isEnd = true;
  			}
  			segs.push({
  				event: event,
  				start: segStart,
  				end: segEnd,
  				isStart: isStart,
  				isEnd: isEnd,
  				msLength: segEnd - segStart
  			});
  		}
  	}
  	return segs;
  	//return segs.sort(segCmp);
  }
  
  
  // event rendering calculation utilities
  function stackSegs(segs) {
  	var levels = [],
  		i, len = segs.length, seg,
  		j, collide, k;
  	for (i=0; i<len; i++) {
  		seg = segs[i];
  		j = 0; // the level index where seg should belong
  		while (true) {
  			collide = false;
  			if (levels[j]) {
  				for (k=0; k<levels[j].length; k++) {
  					if (segsCollide(levels[j][k], seg)) {
  						collide = true;
  						break;
  					}
  				}
  			}
  			if (collide) {
  				j++;
  			}else{
  				break;
  			}
  		}
  		if (levels[j]) {
  			levels[j].push(seg);
  		}else{
  			levels[j] = [seg];
  		}
  	}
  	return levels;
  }
  
  
  
  /* Event Element Binding
  -----------------------------------------------------------------------------*/
  
  
  function lazySegBind(container, segs, bindHandlers) {
  	container.unbind('mouseover').mouseover(function(ev) {
  		var parent=ev.target, e,
  			i, seg;
  		while (parent != this) {
  			e = parent;
  			parent = parent.parentNode;
  		}
  		if ((i = e._fci) !== undefined) {
  			e._fci = undefined;
  			seg = segs[i];
  			bindHandlers(seg.event, seg.element, seg);
  			$(ev.target).trigger(ev);
  		}
  		ev.stopPropagation();
  	});
  }
  
  
  
  /* Element Dimensions
  -----------------------------------------------------------------------------*/
  
  
  function setOuterWidth(element, width, includeMargins) {
  	for (var i=0, e; i<element.length; i++) {
  		e = $(element[i]);
  		e.width(Math.max(0, width - hsides(e, includeMargins)));
  	}
  }
  
  
  function setOuterHeight(element, height, includeMargins) {
  	for (var i=0, e; i<element.length; i++) {
  		e = $(element[i]);
  		e.height(Math.max(0, height - vsides(e, includeMargins)));
  	}
  }
  
  
  function hsides(element, includeMargins) {
  	return hpadding(element) + hborders(element) + (includeMargins ? hmargins(element) : 0);
  }
  
  
  function hpadding(element) {
  	return (parseFloat($.css(element[0], 'paddingLeft', true)) || 0) +
  	       (parseFloat($.css(element[0], 'paddingRight', true)) || 0);
  }
  
  
  function hmargins(element) {
  	return (parseFloat($.css(element[0], 'marginLeft', true)) || 0) +
  	       (parseFloat($.css(element[0], 'marginRight', true)) || 0);
  }
  
  
  function hborders(element) {
  	return (parseFloat($.css(element[0], 'borderLeftWidth', true)) || 0) +
  	       (parseFloat($.css(element[0], 'borderRightWidth', true)) || 0);
  }
  
  
  function vsides(element, includeMargins) {
  	return vpadding(element) +  vborders(element) + (includeMargins ? vmargins(element) : 0);
  }
  
  
  function vpadding(element) {
  	return (parseFloat($.css(element[0], 'paddingTop', true)) || 0) +
  	       (parseFloat($.css(element[0], 'paddingBottom', true)) || 0);
  }
  
  
  function vmargins(element) {
  	return (parseFloat($.css(element[0], 'marginTop', true)) || 0) +
  	       (parseFloat($.css(element[0], 'marginBottom', true)) || 0);
  }
  
  
  function vborders(element) {
  	return (parseFloat($.css(element[0], 'borderTopWidth', true)) || 0) +
  	       (parseFloat($.css(element[0], 'borderBottomWidth', true)) || 0);
  }
  
  
  function setMinHeight(element, height) {
  	height = (typeof height == 'number' ? height + 'px' : height);
  	element.each(function(i, _element) {
  		_element.style.cssText += ';min-height:' + height + ';_height:' + height;
  		// why can't we just use .css() ? i forget
  	});
  }
  
  
  
  /* Misc Utils
  -----------------------------------------------------------------------------*/
  
  
  //TODO: arraySlice
  //TODO: isFunction, grep ?
  
  
  function noop() { }
  
  
  function cmp(a, b) {
  	return a - b;
  }
  
  
  function arrayMax(a) {
  	return Math.max.apply(Math, a);
  }
  
  
  function zeroPad(n) {
  	return (n < 10 ? '0' : '') + n;
  }
  
  
  function smartProperty(obj, name) { // get a camel-cased/namespaced property of an object
  	if (obj[name] !== undefined) {
  		return obj[name];
  	}
  	var parts = name.split(/(?=[A-Z])/),
  		i=parts.length-1, res;
  	for (; i>=0; i--) {
  		res = obj[parts[i].toLowerCase()];
  		if (res !== undefined) {
  			return res;
  		}
  	}
  	return obj[''];
  }
  
  
  function htmlEscape(s) {
  	return s.replace(/&/g, '&amp;')
  		.replace(/</g, '&lt;')
  		.replace(/>/g, '&gt;')
  		.replace(/'/g, '&#039;')
  		.replace(/"/g, '&quot;')
  		.replace(/\n/g, '<br />');
  }
  
  
  function cssKey(_element) {
  	return _element.id + '/' + _element.className + '/' + _element.style.cssText.replace(/(^|;)\s*(top|left|width|height)\s*:[^;]*/ig, '');
  }
  
  
  function disableTextSelection(element) {
  	element
  		.attr('unselectable', 'on')
  		.css('MozUserSelect', 'none')
  		.bind('selectstart.ui', function() { return false; });
  }
  
  
  /*
  function enableTextSelection(element) {
  	element
  		.attr('unselectable', 'off')
  		.css('MozUserSelect', '')
  		.unbind('selectstart.ui');
  }
  */
  
  
  function markFirstLast(e) {
  	e.children()
  		.removeClass('fc-first fc-last')
  		.filter(':first-child')
  			.addClass('fc-first')
  		.end()
  		.filter(':last-child')
  			.addClass('fc-last');
  }
  
  
  function setDayID(cell, date) {
  	cell.each(function(i, _cell) {
  		_cell.className = _cell.className.replace(/^fc-\w*/, 'fc-' + dayIDs[date.getDay()]);
  		// TODO: make a way that doesn't rely on order of classes
  	});
  }
  
  
  function getSkinCss(event, opt) {
  	var source = event.source || {};
  	var eventColor = event.color;
  	var sourceColor = source.color;
  	var optionColor = opt('eventColor');
  	var backgroundColor =
  		event.backgroundColor ||
  		eventColor ||
  		source.backgroundColor ||
  		sourceColor ||
  		opt('eventBackgroundColor') ||
  		optionColor;
  	var borderColor =
  		event.borderColor ||
  		eventColor ||
  		source.borderColor ||
  		sourceColor ||
  		opt('eventBorderColor') ||
  		optionColor;
  	var textColor =
  		event.textColor ||
  		source.textColor ||
  		opt('eventTextColor');
  	var statements = [];
  	if (backgroundColor) {
  		statements.push('background-color:' + backgroundColor);
  	}
  	if (borderColor) {
  		statements.push('border-color:' + borderColor);
  	}
  	if (textColor) {
  		statements.push('color:' + textColor);
  	}
  	return statements.join(';');
  }
  
  
  function applyAll(functions, thisObj, args) {
  	if ($.isFunction(functions)) {
  		functions = [ functions ];
  	}
  	if (functions) {
  		var i;
  		var ret;
  		for (i=0; i<functions.length; i++) {
  			ret = functions[i].apply(thisObj, args) || ret;
  		}
  		return ret;
  	}
  }
  
  
  function firstDefined() {
  	for (var i=0; i<arguments.length; i++) {
  		if (arguments[i] !== undefined) {
  			return arguments[i];
  		}
  	}
  }
  
  