Template loader wrapper

/**
 * The templates tool loads a template with view data. It caches template scripts.
 *
 * Example: loader.load('/path/to/template.html', 'selector', container, data);
 */
(function ($, M) {
	'use strict';
	var templates = {},
		data = {};

	/**
	 * Render a template
	 * @param {Object} template {id: id, html: template}
	 */
	function renderTemplate(template) {
		var viewData = data[template.id].viewData,
			$container = data[template.id].$templateContainer,
			output = M.render(template.html, viewData);
		// clear and fill the container
		$container.html('').html(output);

	}

	/**
	 * get template by url
	 * @param {String} templateUrl Location of the template
	 * @param {String} templateId  ID of template
	 */
	function getTemplate(templateUrl, templateId) {
		var templateDefer = new $.Deferred();

		// get template
		$.get(templateUrl, function (file) {
			var html = $(file).filter('#' + templateId).html();
			templates[templateId] = templateDefer.promise();
			templateDefer.resolve({id: templateId, html: html});
		});
		return templateDefer.promise();
	}

	/**
	 * Load a template and put it in a container.
	 * @param {String} templateUrl        The absolute path to the template
	 * @param {String} templateId         The id of the chosen template
	 * @param {jQuery} $templateContainer Empty container where the template will be placed in
	 * @param {Object} viewData           The data that is loaded in the template
	 */
	function load(templateUrl, templateId, $templateContainer, viewData) {
		var templateRendered = $.Deferred();
		data[templateId] = {
			$templateContainer: $templateContainer,
			viewData: viewData
		};
		function resolveLoad() {
			templateRendered.resolve($templateContainer);
		}
		if (templates[templateId]) {
			// template already in cache
			templates[templateId].done(renderTemplate, resolveLoad);
		} else {
			getTemplate(templateUrl, templateId).done(renderTemplate, resolveLoad);
		}
		return templateRendered.promise();
	}

	loader = {
		load: load
	};
}(jQuery, Mustache));