76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav GlassYUI.add('view', function(Y) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass/**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav GlassRepresents a logical piece of an application's user interface, and provides a
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glasslightweight, overridable API for rendering content and handling delegated DOM
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glassevents on a container element.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
f50179c7ad363c27b2d90fbb8aa37b714bc9a51eEric Ferraiuolo@module app
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove@submodule view
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove@since 3.4.0
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove**/
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove/**
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan GroveRepresents a logical piece of an application's user interface, and provides a
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grovelightweight, overridable API for rendering content and handling delegated DOM
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Groveevents on a container element.
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav GlassThe View class imposes little structure and provides only minimal functionality
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glassof its own: it's basically just an overridable API interface that helps you
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glassimplement custom views.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
db664634abff07e378add55f2ef12fcd2f37f62dRyan GroveAs of YUI 3.5.0, View allows ad-hoc attributes to be specified at instantiation
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grovetime, so you don't need to subclass `Y.View` to add custom attributes. Just pass
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grovethem to the constructor:
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove var view = new Y.View({foo: 'bar'});
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove view.get('foo'); // => "bar"
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass@class View
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass@constructor
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove@extends Base
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove@since 3.4.0
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass**/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glassfunction View() {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass View.superclass.constructor.apply(this, arguments);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass}
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav GlassY.View = Y.extend(View, Y.Base, {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // -- Public Properties ----------------------------------------------------
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove /**
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove Template for this view's container.
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove @property containerTemplate
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove @type String
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove @default "<div/>"
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove @since 3.5.0
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove **/
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove containerTemplate: '<div/>',
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Hash of CSS selectors mapped to events to delegate to elements matching
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass those selectors.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass CSS selectors are relative to the `container` element. Events are attached
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass to the container, and delegation is used so that subscribers are only
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass notified of events that occur on elements inside the container that match
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove the specified selectors. This allows the container's contents to be re-
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove rendered as needed without losing event subscriptions.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Event handlers can be specified either as functions or as strings that map
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass to function names on this view instance or its prototype.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass The `this` object in event handlers will refer to this view instance. If
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass you'd prefer `this` to be something else, use `Y.bind()` to bind a custom
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass `this` object.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @example
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var view = new Y.View({
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass events: {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // Call `this.toggle()` whenever the element with the id
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // "toggle-button" is clicked.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass '#toggle-button': {click: 'toggle'},
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // Call `this.hoverOn()` when the mouse moves over any element
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // with the "hoverable" class, and `this.hoverOff()` when the
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // mouse moves out of any element with the "hoverable" class.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass '.hoverable': {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass mouseover: 'hoverOn',
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass mouseout : 'hoverOff'
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass });
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @property events
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @type Object
c1463e30f48fb36d028c3ca3d1e7c9b96848a9c1Ryan Grove @default {}
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass events: {},
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
95766e1d0380c92a2b078520644ed1d388b4e9d0Ryan Grove /**
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove Template for this view's contents.
95766e1d0380c92a2b078520644ed1d388b4e9d0Ryan Grove
95766e1d0380c92a2b078520644ed1d388b4e9d0Ryan Grove This is a convenience property that has no default behavior of its own.
95766e1d0380c92a2b078520644ed1d388b4e9d0Ryan Grove It's only provided as a convention to allow you to store whatever you
95766e1d0380c92a2b078520644ed1d388b4e9d0Ryan Grove consider to be a template, whether that's an HTML string, a `Y.Node`
95766e1d0380c92a2b078520644ed1d388b4e9d0Ryan Grove instance, a Mustache template, or anything else your little heart
95766e1d0380c92a2b078520644ed1d388b4e9d0Ryan Grove desires.
95766e1d0380c92a2b078520644ed1d388b4e9d0Ryan Grove
95766e1d0380c92a2b078520644ed1d388b4e9d0Ryan Grove How this template gets used is entirely up to you and your custom
95766e1d0380c92a2b078520644ed1d388b4e9d0Ryan Grove `render()` method.
95766e1d0380c92a2b078520644ed1d388b4e9d0Ryan Grove
95766e1d0380c92a2b078520644ed1d388b4e9d0Ryan Grove @property template
95766e1d0380c92a2b078520644ed1d388b4e9d0Ryan Grove @type mixed
95766e1d0380c92a2b078520644ed1d388b4e9d0Ryan Grove @default ''
95766e1d0380c92a2b078520644ed1d388b4e9d0Ryan Grove **/
95766e1d0380c92a2b078520644ed1d388b4e9d0Ryan Grove template: '',
95766e1d0380c92a2b078520644ed1d388b4e9d0Ryan Grove
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove // -- Protected Properties -------------------------------------------------
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove /**
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove This tells `Y.Base` that it should create ad-hoc attributes for config
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove properties passed to View's constructor. This makes it possible to
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove instantiate a view and set a bunch of attributes without having to subclass
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove `Y.View` and declare all those attributes first.
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove @property _allowAdHocAttrs
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove @type Boolean
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove @default true
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove @protected
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove @since 3.5.0
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove **/
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove _allowAdHocAttrs: true,
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // -- Lifecycle Methods ----------------------------------------------------
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass initializer: function (config) {
95766e1d0380c92a2b078520644ed1d388b4e9d0Ryan Grove config || (config = {});
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove // Set instance properties specified in the config.
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove config.containerTemplate &&
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove (this.containerTemplate = config.containerTemplate);
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove
95766e1d0380c92a2b078520644ed1d388b4e9d0Ryan Grove config.template && (this.template = config.template);
95766e1d0380c92a2b078520644ed1d388b4e9d0Ryan Grove
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove // Merge events from the config into events in `this.events`.
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove this.events = config.events ? Y.merge(this.events, config.events) :
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove this.events;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove // When the container node changes (or when it's set for the first
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove // time), we'll attach events to it, but not until then. This allows the
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove // container to be created lazily the first time it's accessed rather
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove // than always on init.
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove this.after('containerChange', this._afterContainerChange);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove /**
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove Destroys this View, detaching any DOM events and optionally also destroying
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove its container node.
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove By default, the container node will not be destroyed. Pass an _options_
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove object with a truthy `remove` property to destroy the container as well.
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove @method destroy
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove @param {Object} [options] Options.
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove @param {Boolean} [options.remove=false] If `true`, this View's container
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove will be removed from the DOM and destroyed as well.
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove @chainable
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove */
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove destroy: function (options) {
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove // We also accept `delete` as a synonym for `remove`.
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove if (options && (options.remove || options['delete'])) {
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove // Attaching an event handler here because the `destroy` event is
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove // preventable. If we destroyed the container before calling the
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove // superclass's `destroy()` method and the event was prevented, the
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove // class would end up in a broken state.
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove this.onceAfter('destroy', function () {
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove this._destroyContainer();
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove });
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove }
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove return View.superclass.destroy.call(this);
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove },
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass destructor: function () {
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove this.detachEvents();
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove delete this._container;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // -- Public Methods -------------------------------------------------------
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove Attaches delegated event handlers to this view's container element. This
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass method is called internally to subscribe to events configured in the
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove `events` attribute when the view is initialized.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass You may override this method to customize the event attaching logic.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method attachEvents
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove @param {Object} [events] Hash of events to attach. See the docs for the
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove `events` attribute for details on the format. If not specified, this
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove view's `events` property will be used.
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove @chainable
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove @see detachEvents
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass attachEvents: function (events) {
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove var container = this.get('container'),
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass owns = Y.Object.owns,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass handler, handlers, name, selector;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove this.detachEvents();
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove events || (events = this.events);
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass for (selector in events) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (!owns(events, selector)) { continue; }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass handlers = events[selector];
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass for (name in handlers) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (!owns(handlers, name)) { continue; }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass handler = handlers[name];
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (typeof handler === 'string') {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass handler = this[handler];
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove this._attachedViewEvents.push(
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove container.delegate(name, handler, selector, this));
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove return this;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove Creates and returns a container node for this view.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove By default, the container is created from the HTML template specified in the
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove `containerTemplate` property, and is _not_ added to the DOM automatically.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass You may override this method to customize how the container node is created
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove (such as by rendering it from a custom template format). Your method must
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove return a `Y.Node` instance.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method create
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove @param {HTMLElement|Node|String} [container] Selector string, `Y.Node`
ce92a3aa2a2a508df3cc14d422868f601240b0b7Eric Ferraiuolo instance, or DOM element to use at the container node.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @return {Node} Node instance of the created container node.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass create: function (container) {
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove return container ? Y.one(container) :
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove Y.Node.create(this.containerTemplate);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove Detaches DOM events that have previously been attached to the container by
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove `attachEvents()`.
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove @method detachEvents
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove @chainable
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove @see attachEvents
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove **/
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove detachEvents: function () {
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove Y.Array.each(this._attachedViewEvents, function (handle) {
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove handle.detach();
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove });
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove this._attachedViewEvents = [];
e003df9c0cca758e53e27d267b48075e33502427Ryan Grove return this;
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove },
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove /**
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove Removes this view's container element from the DOM (if it's in the DOM),
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass but doesn't destroy it or any event listeners attached to it.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method remove
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @chainable
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass remove: function () {
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove var container = this.get('container');
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove container && container.remove();
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return this;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove Renders this view.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove This method is a noop by default. Override it to provide a custom
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove implementation that renders this view's content and appends it to the
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove container element. Ideally your `render` method should also return `this` as
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove the end to allow chaining, but that's up to you.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Since there's no default renderer, you're free to render your view however
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass you see fit, whether that means manipulating the DOM directly, dumping
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass strings into `innerHTML`, or using a template language of some kind.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass For basic templating needs, `Y.Node.create()` and `Y.Lang.sub()` may
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass suffice, but there are no restrictions on what tools or techniques you can
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass use to render your view. All you need to do is append something to the
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove container element at some point, and optionally append the container
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass to the DOM if it's not there already.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method render
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @chainable
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass render: function () {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return this;
5971b14cabff91a9860ef266b0d282d2ad083153Eric Ferraiuolo },
5971b14cabff91a9860ef266b0d282d2ad083153Eric Ferraiuolo
5971b14cabff91a9860ef266b0d282d2ad083153Eric Ferraiuolo // -- Protected Methods ----------------------------------------------------
5971b14cabff91a9860ef266b0d282d2ad083153Eric Ferraiuolo
5971b14cabff91a9860ef266b0d282d2ad083153Eric Ferraiuolo /**
5971b14cabff91a9860ef266b0d282d2ad083153Eric Ferraiuolo Removes the `container` from the DOM and purges all its event listeners.
5971b14cabff91a9860ef266b0d282d2ad083153Eric Ferraiuolo
5971b14cabff91a9860ef266b0d282d2ad083153Eric Ferraiuolo @method _destroyContainer
5971b14cabff91a9860ef266b0d282d2ad083153Eric Ferraiuolo @protected
5971b14cabff91a9860ef266b0d282d2ad083153Eric Ferraiuolo **/
5971b14cabff91a9860ef266b0d282d2ad083153Eric Ferraiuolo _destroyContainer: function () {
5971b14cabff91a9860ef266b0d282d2ad083153Eric Ferraiuolo var container = this.get('container');
5971b14cabff91a9860ef266b0d282d2ad083153Eric Ferraiuolo container && container.remove(true);
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove },
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove /**
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove Getter for the `container` attribute.
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove @method _getContainer
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove @param {Node|null} value Current attribute value.
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove @return {Node} Container node.
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove @protected
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove @since 3.5.0
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove **/
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove _getContainer: function (value) {
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove // This wackiness is necessary to enable fully lazy creation of the
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove // container node both when no container is specified and when one is
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove // specified via a valueFn.
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove if (!this._container) {
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove if (value) {
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove // Attach events to the container when it's specified via a
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove // valueFn, which won't fire the containerChange event.
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove this._container = value;
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove this.attachEvents();
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove } else {
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove // Create a default container and set that as the new attribute
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove // value. The `this._container` property prevents infinite
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove // recursion.
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove value = this._container = this.create();
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove this._set('container', value);
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove }
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove }
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove return value;
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove },
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove // -- Protected Event Handlers ---------------------------------------------
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove /**
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove Handles `containerChange` events. Detaches event handlers from the old
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove container (if any) and attaches them to the new container.
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove Right now the `container` attr is initOnly so this event should only ever
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove fire the first time the container is created, but in the future (once Y.App
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove can handle it) we may allow runtime container changes.
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove @method _afterContainerChange
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove @protected
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove @since 3.5.0
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove **/
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove _afterContainerChange: function () {
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove this.attachEvents(this.events);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass}, {
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove NAME: 'view',
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove ATTRS: {
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove /**
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove Container node into which this view's content will be rendered.
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove The container node serves as the host for all DOM events attached by the
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove view. Delegation is used to handle events on children of the container,
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove allowing the container's contents to be re-rendered at any time without
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove losing event subscriptions.
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove
b3c0000ee2acad3759af025d5cece6468634da07Ryan Grove The default container is a `<div>` Node, but you can override this in
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove a subclass, or by passing in a custom `container` config value at
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove instantiation time.
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove When `container` is overridden by a subclass or passed as a config
b3c0000ee2acad3759af025d5cece6468634da07Ryan Grove option at instantiation time, it may be provided as a selector string, a
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove DOM element, or a `Y.Node` instance. The value will be converted into a
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove `Y.Node` instance if it isn't one already.
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove The container is not added to the page automatically. This allows you to
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove have full control over how and when your view is actually rendered to
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove the page.
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove @attribute container
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove @type HTMLElement|Node|String
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove @default Y.Node.create(this.containerTemplate)
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove @writeOnce
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove **/
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove container: {
8e24f50e31a85305f4a1eaadbd5216229c8f1f8bRyan Grove getter : '_getContainer',
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove setter : Y.one,
d332ce1cf07c89a8b9f2ccb04ff7204940866fecRyan Grove writeOnce: true
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove }
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove },
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove /**
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove Properties that shouldn't be turned into ad-hoc attributes when passed to
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove View's constructor.
3d972ae925dd55609d50660e1479c256bce1840cRyan Grove
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove @property _NON_ATTRS_CFG
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove @type Array
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove @static
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove @protected
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove @since 3.5.0
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove **/
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove _NON_ATTRS_CFG: [
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove 'containerTemplate',
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove 'events',
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove 'template'
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove ]
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass});
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
db664634abff07e378add55f2ef12fcd2f37f62dRyan Grove
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass}, '@VERSION@' ,{requires:['base-build', 'node-event-delegate']});