app-base.js revision 94440da5e5a52f2d96a9e177aca3719e3d3abe02
/**
Provides a top-level application component which manages navigation and views.
@submodule app-base
@since 3.5.0
**/
App;
/**
Provides a top-level application component which manages navigation and views.
* TODO: Add more description.
* TODO: Should this extend `Y.Base` and mix in `Y.Router` along with
`Y.PjaxBase` and `Y.View`? Also need to make sure the `Y.Base`-based
extensions are doing the proper thing w.r.t. multiple inheritance.
@class App
@constructor
@extends Base
@uses View
@uses Router
@uses PjaxBase
@since 3.5.0
**/
// -- Public Properties ----------------------------------------------------
/**
Hash of view-name to metadata used to declaratively describe an
application's views and their relationship with the app and other views.
The view info in `views` is an Object keyed to a view name and can have any
or all of the following properties:
* `type`: Function or a string representing the view constructor to use to
create view instances. If a string is used, the constructor function is
assumed to be on the `Y` object; e.g. `"SomeView"` -> `Y.SomeView`.
* `preserve`: Boolean for whether the view instance should be retained. By
default, the view instance will be destroyed when it is no longer the
active view. If `true` the view instance will simply be `removed()` from
the DOM when it is no longer active. This is useful when the view is
frequently used and may be expensive to re-create.
* `parent`: String to another named view in this hash that represents
parent view within the application's view hierarchy; e.g. a `"photo"`
relationship is used a queue for which transition to use.
* `instance`: Used internally to manage the current instance of this named
view. This can be used if your view instance is created up-front, or if
you would rather manage the View lifecyle, but you probably should just
let this be handled for you.
If `views` are passed at instantiation time, they will override any views
set on the prototype.
@property views
@type Object
@default {}
**/
views: {},
// -- Protected Properties -------------------------------------------------
/**
Map of view instance id (via `Y.stamp()`) to view-info object in `views`.
This mapping is used to tie a specific view instance back to its metadata by
adding a reference to the the related view info on the `views` object.
@property _viewInfoMap
@type Object
@default {}
@protected
**/
// -- Lifecycle Methods ----------------------------------------------------
initializer: function (config) {
this._viewInfoMap = {};
},
// -- Public Methods -------------------------------------------------------
/**
Creates and returns this app's `container` node from the specified HTML
string, DOM element, or existing `Y.Node` instance. This method is called
internally when the view is initialized.
This node is also stamped with the CSS class specified by `Y.App.CSS_CLASS`.
By default, the created node is _not_ added to the DOM automatically.
@method create
@param {HTMLElement|Node|String} container HTML string, DOM element, or
`Y.Node` instance to use as the container node.
@return {Node} Node instance of the created container node.
**/
create: function () {
},
/**
Renders this application by appending the `viewContainer` node to the
`container` node, and showing the `activeView`.
You should call this method at least once, usually after the initialization
of your `Y.App` instance.
@method render
@chainable
**/
render: function () {
return this;
},
/**
Returns the metadata associated with a view instance or view name defined on
the `views` object.
@method getViewInfo
@param {View|String} view View instance, or name of a view defined on the
`views` object.
@return {Object} The metadata for the view, or `undefined` if the view is
not registered.
**/
getViewInfo: function (view) {
}
},
/**
Creates and returns a new view instance using the provided `name` to look up
the view info metadata defined in the `views` object. The passed-in `config`
object is passed to the view constructor function.
This function also maps a view instance back to its view info metadata.
@method createView
@param {String} name The name of a view defined on the `views` object.
@param {Object} [config] The configuration object passed to the view
constructor function when creating the new view instance.
@return {View} The new view instance.
**/
view;
// Create the view instance and map it with its metadata.
return view;
},
/**
This will set the application's `activeView` attribute to the view instance
passed-in, or when a view name is provided, the `activeView` attribute will
be set to either the preserved instance, or a new view instance will be
created using the passed in `config`.
A callback function can be specified as either the third or fourth argument,
and this function will be called after the new `view` is the `activeView`
and ready to use.
@method showView
@param {String|View} view The name of a view defined in the `views` object,
or a view instance.
@param {Object} [config] Optional configuration to use when creating a new
view instance.
@param {Object} [options] Optional object containing any of the following
properties:
@param {Boolean} [options.prepend] Whether the new view should be
prepended instead of appended to the `viewContainer`.
@param {Object} [options.transitions] An object that contains transition
configuration overrides for the following properties:
@param {Object} [options.transitions.viewIn] Transition overrides for
the view being transitioned-in.
@param {Object} [options.transitions.viewOut] Transition overrides for
the view being transitioned-out.
@param {Function} [callback] Optional callback Function to call after the
new `activeView` is ready to use, the function will be passed:
@param {View} view
@chainable
**/
var viewInfo;
// Use the preserved view instance, or create a new view.
} else {
}
}
// TODO: Add options.update to update to view with the `config`, if
// needed. Would this be too much overloading of the API?
if (callback) {
}
},
// -- Protected Methods ----------------------------------------------------
/**
Determines if the `view` passed in is configured as a child of the `parent`
view passed in. This requires both views to be either named-views, or view
instanced created using configuration data that exists in the `views`
object.
@method _isChildView
@param {View|String} view The name of a view defined in the `views` object,
or a view instance.
@param {View|String} parent The name of a view defined in the `views`
object, or a view instance.
@return {Boolean} Whether the view is configured as a child of the parent.
@protected
**/
if (viewInfo && parentInfo) {
}
return false;
},
/**
Determines if the `view` passed in is configured as a parent of the `child`
view passed in. This requires both views to be either named-views, or view
instanced created using configuration data that exists in the `views`
object.
@method _isParentView
@param {View|String} view The name of a view defined in the `views` object,
or a view instance.
@param {View|String} parent The name of a view defined in the `views`
object, or a view instance.
@return {Boolean} Whether the view is configured as a parent of the child.
@protected
**/
}
return false;
},
/**
Adds the `Y.App.VIEWS_CSS_CLASS` to the `viewContainer`.
@method _setViewContainer
@param {HTMLElement|Node|String} container HTML string, DOM element, or
`Y.Node` instance to use as the container node.
@return {Node} Node instance of the created container node.
@protected
**/
_setViewContainer: function (viewContainer) {
},
/**
Helper method to attach the view instance to the application by making the
application a bubble target of the view, and assigning the view instance to
the `instance` property of the associated view info metadata.
@method _attachView
@param {View} view View to attach.
@param {Boolean} prepend Whether the view should be prepended instead of
appended to the `viewContainer`.
@protected
**/
if (!view) {
return;
}
// TODO: Attach events?
// Insert view into the DOM.
},
/**
Helper method to detach the view instance from the application by removing
the application as a bubble target of the view, and either just removing the
view if it is intended to be preserved, or destroying the instance
completely.
@method _detachView
@param {View} view View to detach.
@protected
**/
_detachView: function (view) {
if (!view) {
return;
}
// TODO: detach events?
} else {
// Remove from view to view-info map.
// Remove from view-info instance property.
}
}
view.removeTarget(this);
},
// -- Protected Event Handlers ---------------------------------------------
/**
Handles the application's `activeViewChange` event (which is fired when the
`activeView` attribute changes) by detaching the old view, attaching the new
view.
The `activeView` attribute is read-only, so the public API to change its
value is through the `showView()` method.
@method _afterActiveViewChange
@param {EventFacade} e
@protected
**/
_afterActiveViewChange: function (e) {
// Prevent detaching (thus removing) the view we want to show.
// Also hard to animate out and in, the same view.
}
// TODO: Remove `viewContainer` before making DOM updates?
this._detachView(oldView);
}
}, {
ATTRS: {
/**
Container node which represents the application's bounding-box.
@attribute container
@type HTMLElement|Node|String
@default "body"
@initOnly
**/
container: {
value: 'body'
},
/**
Container node into which all application views will be rendered.
@attribute viewContainer
@type HTMLElement|Node|String
@default Y.Node.create('<div/>')
@initOnly
**/
valueFn: function () {
},
setter : '_setViewContainer',
writeOnce: 'initOnly'
},
/**
This attribute is provided by `PjaxBase`, but the default value is
overridden to match all links on the page.
@attribute linkSelector
@type String|Function
@default "a"
**/
linkSelector: {
value: 'a'
},
/**
This attribute is read-only, to set the `activeView`, use the
`showView()` method.
@attribute activeView
@type View
@readOnly
@see showView
**/
activeView: {
readOnly: true
}
},
});
// -- Namespace ----------------------------------------------------------------