549 lines
17 KiB
JavaScript
549 lines
17 KiB
JavaScript
//////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// This is a generated file. You can view the original //
|
|
// source in your browser if your browser supports source maps. //
|
|
// Source maps are supported by all recent versions of Chrome, Safari, //
|
|
// and Firefox, and by Internet Explorer 11. //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
(function () {
|
|
|
|
/* Imports */
|
|
var Meteor = Package.meteor.Meteor;
|
|
var global = Package.meteor.global;
|
|
var meteorEnv = Package.meteor.meteorEnv;
|
|
var Template = Package['templating-runtime'].Template;
|
|
var Blaze = Package.blaze.Blaze;
|
|
var UI = Package.blaze.UI;
|
|
var Handlebars = Package.blaze.Handlebars;
|
|
var _ = Package.underscore._;
|
|
var Tracker = Package.tracker.Tracker;
|
|
var Deps = Package.tracker.Deps;
|
|
var Iron = Package['iron:core'].Iron;
|
|
var HTML = Package.htmljs.HTML;
|
|
var Spacebars = Package.spacebars.Spacebars;
|
|
|
|
/* Package-scope variables */
|
|
var findFirstLayout, Layout, DEFAULT_REGION;
|
|
|
|
(function(){
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// packages/iron_layout/version_conflict_errors.js //
|
|
// //
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
var errors = [];
|
|
|
|
if (Package['cmather:iron-layout']) {
|
|
errors.push("\n\n\
|
|
The cmather:iron-{x} packages were migrated to the new package system with the wrong name, and you have duplicate copies.\n\
|
|
You can see which cmather:iron-{x} packages have been installed by using this command:\n\n\
|
|
> meteor list\n\n\
|
|
Can you remove any installed cmather:iron-{x} packages like this:\
|
|
\n\n\
|
|
> meteor remove cmather:iron-core\n\
|
|
> meteor remove cmather:iron-router\n\
|
|
> meteor remove cmather:iron-dynamic-template\n\
|
|
> meteor remove cmather:iron-dynamic-layout\n\
|
|
\n\
|
|
The new packages are named iron:{x}. For example:\n\n\
|
|
> meteor add iron:router\n\n\
|
|
Sorry for the hassle, but thank you!\
|
|
\n\n\
|
|
");
|
|
}
|
|
|
|
// If the user still has blaze-layout throw an error. Let's get rid of that
|
|
// package so it's not lingering around with all its nastiness.
|
|
if (Package['cmather:blaze-layout']) {
|
|
errors.push(
|
|
"The blaze-layout package has been replaced by iron-layout. Please remove the package like this:\n> meteor remove cmather:blaze-layout\n"
|
|
);
|
|
}
|
|
|
|
if (errors.length > 0) {
|
|
throw new Error("Sorry! Looks like there's a few errors related to iron:layout\n\n" + errors.join("\n\n"));
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}).call(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(function(){
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// packages/iron_layout/template.default_layout.js //
|
|
// //
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
|
|
Template.__checkName("__IronDefaultLayout__");
|
|
Template["__IronDefaultLayout__"] = new Template("Template.__IronDefaultLayout__", (function() {
|
|
var view = this;
|
|
return Spacebars.include(view.lookupTemplate("yield"));
|
|
}));
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}).call(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(function(){
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// packages/iron_layout/layout.js //
|
|
// //
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
/*****************************************************************************/
|
|
/* Imports */
|
|
/*****************************************************************************/
|
|
var DynamicTemplate = Iron.DynamicTemplate;
|
|
var inherits = Iron.utils.inherits;
|
|
|
|
/*****************************************************************************/
|
|
/* Helpers */
|
|
/*****************************************************************************/
|
|
/**
|
|
* Find the first Layout in the rendered parent hierarchy.
|
|
*/
|
|
findFirstLayout = function (view) {
|
|
while (view) {
|
|
if (view.name === 'Iron.Layout')
|
|
return view.__dynamicTemplate__;
|
|
else
|
|
view = view.parentView;
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
/*****************************************************************************/
|
|
/* Layout */
|
|
/*****************************************************************************/
|
|
|
|
/**
|
|
* Dynamically render templates into regions.
|
|
*
|
|
* Layout inherits from Iron.DynamicTemplate and provides the ability to create
|
|
* regions that a user can render templates or content blocks into. The layout
|
|
* and each region is an instance of DynamicTemplate so the template and data
|
|
* contexts are completely dynamic and programmable in javascript.
|
|
*/
|
|
Layout = function (options) {
|
|
var self = this;
|
|
|
|
Layout.__super__.constructor.apply(this, arguments);
|
|
|
|
options = options || {};
|
|
this.name = 'Iron.Layout';
|
|
this._regions = {};
|
|
this._regionHooks = {};
|
|
this.defaultTemplate('__IronDefaultLayout__');
|
|
|
|
// if there's block content then render that
|
|
// to the main region
|
|
if (options.content)
|
|
this.render(options.content);
|
|
};
|
|
|
|
/**
|
|
* The default region for a layout where the main content will go.
|
|
*/
|
|
DEFAULT_REGION = Layout.DEFAULT_REGION = 'main';
|
|
|
|
/**
|
|
* Inherits from Iron.DynamicTemplate which gives us the ability to set the
|
|
* template and data context dynamically.
|
|
*/
|
|
inherits(Layout, Iron.DynamicTemplate);
|
|
|
|
/**
|
|
* Return the DynamicTemplate instance for a given region. If the region doesn't
|
|
* exist it is created.
|
|
*
|
|
* The regions object looks like this:
|
|
*
|
|
* {
|
|
* "main": DynamicTemplate,
|
|
* "footer": DynamicTemplate,
|
|
* .
|
|
* .
|
|
* .
|
|
* }
|
|
*/
|
|
Layout.prototype.region = function (name, options) {
|
|
return this._ensureRegion(name, options);
|
|
};
|
|
|
|
/**
|
|
* Destroy all child regions and reset the regions map.
|
|
*/
|
|
Layout.prototype.destroyRegions = function () {
|
|
_.each(this._regions, function (dynamicTemplate) {
|
|
dynamicTemplate.destroy();
|
|
});
|
|
|
|
this._regions = {};
|
|
};
|
|
|
|
/**
|
|
* Set the template for a region.
|
|
*/
|
|
Layout.prototype.render = function (template, options) {
|
|
// having options is usually good
|
|
options = options || {};
|
|
|
|
// let the user specify the region to render the template into
|
|
var region = options.to || options.region || DEFAULT_REGION;
|
|
|
|
// get the DynamicTemplate for this region
|
|
var dynamicTemplate = this.region(region);
|
|
|
|
// if we're in a rendering transaction, track that we've rendered this
|
|
// particular region
|
|
this._trackRenderedRegion(region);
|
|
|
|
// set the template value for the dynamic template
|
|
dynamicTemplate.template(template);
|
|
|
|
// set the data for the region. If options.data is not defined, this will
|
|
// clear the data, which is what we want
|
|
dynamicTemplate.data(options.data);
|
|
};
|
|
|
|
/**
|
|
* Returns true if the given region is defined and false otherwise.
|
|
*/
|
|
Layout.prototype.has = function (region) {
|
|
region = region || Layout.DEFAULT_REGION;
|
|
return !!this._regions[region];
|
|
};
|
|
|
|
/**
|
|
* Returns an array of region keys.
|
|
*/
|
|
Layout.prototype.regionKeys = function () {
|
|
return _.keys(this._regions);
|
|
};
|
|
|
|
/**
|
|
* Clear a given region or the "main" region by default.
|
|
*/
|
|
Layout.prototype.clear = function (region) {
|
|
region = region || Layout.DEFAULT_REGION;
|
|
|
|
// we don't want to create a region if it didn't exist before
|
|
if (this.has(region))
|
|
this.region(region).template(null);
|
|
|
|
// chain it up
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Clear all regions.
|
|
*/
|
|
Layout.prototype.clearAll = function () {
|
|
_.each(this._regions, function (dynamicTemplate) {
|
|
dynamicTemplate.template(null);
|
|
});
|
|
|
|
// chain it up
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Start tracking rendered regions.
|
|
*/
|
|
Layout.prototype.beginRendering = function (onComplete) {
|
|
var self = this;
|
|
if (this._finishRenderingTransaction)
|
|
this._finishRenderingTransaction();
|
|
|
|
this._finishRenderingTransaction = _.once(function () {
|
|
var regions = self._endRendering({flush: false});
|
|
onComplete && onComplete(regions);
|
|
});
|
|
|
|
Deps.afterFlush(this._finishRenderingTransaction);
|
|
|
|
if (this._renderedRegions)
|
|
throw new Error("You called beginRendering again before calling endRendering");
|
|
this._renderedRegions = {};
|
|
};
|
|
|
|
/**
|
|
* Track a rendered region if we're in a transaction.
|
|
*/
|
|
Layout.prototype._trackRenderedRegion = function (region) {
|
|
if (!this._renderedRegions)
|
|
return;
|
|
this._renderedRegions[region] = true;
|
|
};
|
|
|
|
/**
|
|
* Stop a rendering transaction and retrieve the rendered regions. This
|
|
* shouldn't be called directly. Instead, pass an onComplete callback to the
|
|
* beginRendering method.
|
|
*/
|
|
Layout.prototype._endRendering = function (opts) {
|
|
// we flush here to ensure all of the {{#contentFor}} inclusions have had a
|
|
// chance to render from our templates, otherwise we'll never know about
|
|
// them.
|
|
opts = opts || {};
|
|
if (opts.flush !== false)
|
|
Deps.flush();
|
|
var renderedRegions = this._renderedRegions || {};
|
|
this._renderedRegions = null;
|
|
return _.keys(renderedRegions);
|
|
};
|
|
|
|
/**
|
|
* View lifecycle hooks for regions.
|
|
*/
|
|
_.each(
|
|
[
|
|
'onRegionCreated',
|
|
'onRegionRendered',
|
|
'onRegionDestroyed'
|
|
],
|
|
function (hook) {
|
|
Layout.prototype[hook] = function (cb) {
|
|
var hooks = this._regionHooks[hook] = this._regionHooks[hook] || [];
|
|
hooks.push(cb);
|
|
return this;
|
|
}
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Returns the DynamicTemplate for a given region or creates it if it doesn't
|
|
* exists yet.
|
|
*/
|
|
Layout.prototype._ensureRegion = function (name, options) {
|
|
return this._regions[name] = this._regions[name] || this._createDynamicTemplate(name, options);
|
|
};
|
|
|
|
/**
|
|
* Create a new DynamicTemplate instance.
|
|
*/
|
|
Layout.prototype._createDynamicTemplate = function (name, options) {
|
|
var self = this;
|
|
var tmpl = new Iron.DynamicTemplate(options);
|
|
var capitalize = Iron.utils.capitalize;
|
|
tmpl._region = name;
|
|
|
|
_.each(['viewCreated', 'viewReady', 'viewDestroyed'], function (hook) {
|
|
hook = capitalize(hook);
|
|
tmpl['on' + hook](function (dynamicTemplate) {
|
|
// "this" is the view instance
|
|
var view = this;
|
|
var regionHook = ({
|
|
viewCreated: "regionCreated",
|
|
viewReady: "regionRendered",
|
|
viewDestroyed: "regionDestroyed"
|
|
})[hook];
|
|
self._runRegionHooks('on' + regionHook, view, dynamicTemplate);
|
|
});
|
|
});
|
|
|
|
return tmpl;
|
|
};
|
|
|
|
Layout.prototype._runRegionHooks = function (name, regionView, regionDynamicTemplate) {
|
|
var layout = this;
|
|
var hooks = this._regionHooks[name] || [];
|
|
var hook;
|
|
|
|
for (var i = 0; i < hooks.length; i++) {
|
|
hook = hooks[i];
|
|
// keep the "thisArg" pointing to the view, but make the first parameter to
|
|
// the callback teh dynamic template instance.
|
|
hook.call(regionView, regionDynamicTemplate.region, regionDynamicTemplate, this);
|
|
}
|
|
};
|
|
|
|
/*****************************************************************************/
|
|
/* UI Helpers */
|
|
/*****************************************************************************/
|
|
if (typeof Template !== 'undefined') {
|
|
/**
|
|
* Create a region in the closest layout ancestor.
|
|
*
|
|
* Examples:
|
|
* <aside>
|
|
* {{> yield "aside"}}
|
|
* </aside>
|
|
*
|
|
* <article>
|
|
* {{> yield}}
|
|
* </article>
|
|
*
|
|
* <footer>
|
|
* {{> yield "footer"}}
|
|
* </footer>
|
|
*/
|
|
UI.registerHelper('yield', new Template('yield', function () {
|
|
var layout = findFirstLayout(this);
|
|
|
|
if (!layout)
|
|
throw new Error("No Iron.Layout found so you can't use yield!");
|
|
|
|
// Example options: {{> yield region="footer"}} or {{> yield "footer"}}
|
|
var options = DynamicTemplate.getInclusionArguments(this);
|
|
var region;
|
|
var dynamicTemplate;
|
|
|
|
if (_.isString(options)) {
|
|
region = options;
|
|
} else if (_.isObject(options)) {
|
|
region = options.region;
|
|
}
|
|
|
|
// if there's no region specified we'll assume you meant the main region
|
|
region = region || DEFAULT_REGION;
|
|
|
|
// get or create the region
|
|
dynamicTemplate = layout.region(region);
|
|
|
|
// if the dynamicTemplate had already been inserted, let's
|
|
// destroy it before creating a new one.
|
|
if (dynamicTemplate.isCreated)
|
|
dynamicTemplate.destroy();
|
|
|
|
// now return a newly created view
|
|
return dynamicTemplate.create();
|
|
}));
|
|
|
|
/**
|
|
* Render a template into a region in the closest layout ancestor from within
|
|
* your template markup.
|
|
*
|
|
* Examples:
|
|
*
|
|
* {{#contentFor "footer"}}
|
|
* Footer stuff
|
|
* {{/contentFor}}
|
|
*
|
|
* {{> contentFor region="footer" template="SomeTemplate" data=someData}}
|
|
*
|
|
* Note: The helper is a UI.Component object instead of a function so that
|
|
* Meteor UI does not create a Deps.Dependency.
|
|
*
|
|
* XXX what happens if the parent that calls contentFor gets destroyed?
|
|
* XXX the layout.region should be reset to be empty?
|
|
* XXX but how do we control order of setting the region? what if it gets destroyed but then something else sets it?
|
|
*
|
|
*/
|
|
UI.registerHelper('contentFor', new Template('contentFor', function () {
|
|
var layout = findFirstLayout(this);
|
|
|
|
if (!layout)
|
|
throw new Error("No Iron.Layout found so you can't use contentFor!");
|
|
|
|
var options = DynamicTemplate.getInclusionArguments(this) || {}
|
|
var content = this.templateContentBlock;
|
|
var template = options.template;
|
|
var data = options.data;
|
|
var region;
|
|
|
|
if (_.isString(options))
|
|
region = options;
|
|
else if (_.isObject(options))
|
|
region = options.region;
|
|
else
|
|
throw new Error("Which region is this contentFor block supposed to be for?");
|
|
|
|
// set the region to a provided template or the content directly.
|
|
layout.region(region).template(template || content);
|
|
|
|
// tell the layout to track this as a rendered region if we're in a
|
|
// rendering transaction.
|
|
layout._trackRenderedRegion(region);
|
|
|
|
// if we have some data then set the data context
|
|
if (data)
|
|
layout.region(region).data(data);
|
|
|
|
// just render nothing into this area of the page since the dynamic template
|
|
// will do the actual rendering into the right region.
|
|
return null;
|
|
}));
|
|
|
|
/**
|
|
* Check to see if a given region is currently rendered to.
|
|
*
|
|
* Example:
|
|
* {{#if hasRegion 'aside'}}
|
|
* <aside>
|
|
* {{> yield "aside"}}
|
|
* </aside>
|
|
* {{/if}}
|
|
*/
|
|
UI.registerHelper('hasRegion', function (region) {
|
|
var layout = findFirstLayout(Blaze.getView());
|
|
|
|
if (!layout)
|
|
throw new Error("No Iron.Layout found so you can't use hasRegion!");
|
|
|
|
if (!_.isString(region))
|
|
throw new Error("You need to provide an region argument to hasRegion");
|
|
|
|
return !! layout.region(region).template();
|
|
});
|
|
|
|
/**
|
|
* Let people use Layout directly from their templates!
|
|
*
|
|
* Example:
|
|
* {{#Layout template="MyTemplate"}}
|
|
* Main content goes here
|
|
*
|
|
* {{#contentFor "footer"}}
|
|
* footer goes here
|
|
* {{/contentFor}}
|
|
* {{/Layout}}
|
|
*/
|
|
UI.registerHelper('Layout', new Template('layout', function () {
|
|
var args = Iron.DynamicTemplate.args(this);
|
|
|
|
var layout = new Layout({
|
|
template: function () { return args('template'); },
|
|
data: function () { return args('data'); },
|
|
content: this.templateContentBlock
|
|
});
|
|
|
|
return layout.create();
|
|
}));
|
|
}
|
|
/*****************************************************************************/
|
|
/* Namespacing */
|
|
/*****************************************************************************/
|
|
Iron.Layout = Layout;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}).call(this);
|
|
|
|
|
|
/* Exports */
|
|
Package._define("iron:layout");
|
|
|
|
})();
|