Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions js/views/articleView.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
/**
* @file Article View - Renders an article within a page
* @module core/js/views/articleView
* @description Renders an article content object containing one or more blocks.
* Registered as the 'article' component type. Provides standard Adapt class
* composition including visibility, hidden, complete, and optional state flags.
*/
import components from 'core/js/components';
import AdaptView from 'core/js/views/adaptView';

/**
* @class ArticleView
* @classdesc View for article content objects. An article is a top-level grouping
* within a page and contains one or more blocks. Registered as the default 'article'
* component view. All rendering and child-view management is provided by
* {@link module:core/js/views/adaptView~AdaptView}.
* @extends AdaptView
*/
class ArticleView extends AdaptView {

className() {
Expand Down
15 changes: 15 additions & 0 deletions js/views/blockView.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
/**
* @file Block View - Renders a block within an article
* @module core/js/views/blockView
* @description Renders a block content object containing one or more components.
* Registered as the 'block' component type. Components inside the block are
* laid out according to each component's `_layout` attribute.
*/
import components from 'core/js/components';
import AdaptView from 'core/js/views/adaptView';

/**
* @class BlockView
* @classdesc View for block content objects. A block is a row-level grouping
* within an article and contains one or more components. Registered as the
* default 'block' component view. All rendering and child-view management is
* provided by {@link module:core/js/views/adaptView~AdaptView}.
* @extends AdaptView
*/
class BlockView extends AdaptView {

className() {
Expand Down
18 changes: 18 additions & 0 deletions js/views/componentView.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
/**
* @file Component View - Base view for all Adapt component types
* @module core/js/views/componentView
* @description Base class for all Adapt presentation and question component views.
* Provides optional ARIA region labelling, inview scroll-based completion tracking
* via {@link ComponentView#setupInviewCompletion}, and standard remove lifecycle
* cleanup. Registered as the 'component' type.
*/
import logging from 'core/js/logging';
import AdaptView from 'core/js/views/adaptView';

/**
* @class ComponentView
* @classdesc Base view for Adapt components. All presentation and question component
* views extend this class. Provides:
* - Optional ARIA `role="region"` and `aria-labelledby` when `_isA11yRegionEnabled` is set
* - Inview-based completion via {@link ComponentView#setupInviewCompletion}
* - Automatic inview listener cleanup on removal
* @extends AdaptView
*/
class ComponentView extends AdaptView {

attributes() {
Expand Down Expand Up @@ -38,6 +55,7 @@ class ComponentView extends AdaptView {
* @param {function} [callback] Allows you to specify what function is called when the component has been viewed, should
* you want to perform additional checks before setting the component to completed - see adapt-contrib-assessmentResults
* for an example. Defaults to `view.setCompletionStatus` if not specified.
* @returns {void}
*/
setupInviewCompletion(inviewElementSelector = '.component__inner', callback = this.setCompletionStatus) {
this.$inviewElement = this.$(inviewElementSelector);
Expand Down
52 changes: 50 additions & 2 deletions js/views/contentObjectView.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,37 @@
/**
* @file Content Object View - Base view for page and menu content objects
* @module core/js/views/contentObjectView
* @description Renders top-level Adapt content objects (pages and menus). Manages the
* async ready lifecycle, animated fade-in, scroll position reset on load, and the
* full hierarchy of child article/block/component views. Fires prefixed events for
* both the concrete type (e.g. `pageView:ready`) and the base type
* (`contentObjectView:ready`) so plugins can target either level.
*/
import Adapt from 'core/js/adapt';
import wait from 'core/js/wait';
import AdaptView from 'core/js/views/adaptView';
import ReactDOM from 'react-dom';
import data from 'core/js/data';
import router from 'core/js/router';

/**
* @class ContentObjectView
* @classdesc Base view for Adapt content objects. Handles the full render lifecycle:
* template or JSX rendering, async ready state (triggered by `model.change:_isReady`),
* scroll-to-top, velocity fade-in animation, and recursive child-view removal via
* ReactDOM or standard DOM cleanup. Subclassed by {@link module:core/js/views/pageView~PageView}
* and menu views.
* @extends AdaptView
* @fires contentObjectView:preRender
* @fires contentObjectView:render
* @fires contentObjectView:postRender
* @fires contentObjectView:preReady
* @fires contentObjectView:ready
* @fires contentObjectView:postReady
* @fires contentObjectView:preRemove
* @fires contentObjectView:remove
* @fires contentObjectView:postRemove
*/
export default class ContentObjectView extends AdaptView {

attributes() {
Expand Down Expand Up @@ -34,6 +61,13 @@ export default class ContentObjectView extends AdaptView {
this._loadingErrorTimeout = setTimeout(() => data.logReadyError(this), 10000);
}

/**
* Renders the view using either a JSX template (via `this.changed()`) or a
* Handlebars template, then defers a `postRender` call. Fires the
* `preRender`, `render`, and `postRender` lifecycle events for both the
* concrete type (e.g. `pageView:render`) and `contentObjectView:render`.
* @returns {ContentObjectView} This view instance
*/
render() {
const type = this.constructor.type;
Adapt.trigger(`${type}View:preRender contentObjectView:preRender view:preRender`, this);
Expand Down Expand Up @@ -97,8 +131,14 @@ export default class ContentObjectView extends AdaptView {
}

/**
* Force render up to specified id. Resolves when views are ready.
* @param {string} id
* Force-renders descendant views down to the specified model ID. All models
* between the content object root and `id` (inclusive) are forced to render
* even when lazy-rendering would normally skip them.
* @param {string} id - The `_id` of the target descendant model
* @returns {Promise<void>} Resolves once the target view is rendered and ready
* @throws {Error} If `id` is not a descendant of this content object
* @throws {Error} If any model up to `id` is locked
* @throws {Error} If the target view fails to reach a rendered and ready state
*/
async renderTo(id) {
const isRenderToSelf = (id === this.model.get('_id'));
Expand Down Expand Up @@ -141,6 +181,14 @@ export default class ContentObjectView extends AdaptView {
this.trigger('preRemove');
}

/**
* Removes the view and all descendant views from the DOM. Unmounts React
* components via `ReactDOM.unmountComponentAtNode` when JSX is in use,
* otherwise removes descendant views in reverse order. Fires the `remove`
* and deferred `postRemove` lifecycle events. Uses {@link module:core/js/wait}
* to ensure removal completes before the next queued operation.
* @returns {ContentObjectView} This view instance
*/
remove() {
const type = this.constructor.type;
this.preRemove();
Expand Down
15 changes: 15 additions & 0 deletions js/views/menuItemView.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
/**
* @file Menu Item View - Renders a single menu item within a parent menu
* @module core/js/views/menuItemView
* @description Renders a menu item card representing a child content object
* (page or nested menu) inside a parent menu. Checks completion and interaction
* completion status before rendering, and signals ready only after all images
* within the item have loaded.
*/
import AdaptView from 'core/js/views/adaptView';

/**
* @class MenuItemView
* @classdesc Renders a clickable menu item card for a child content object. Applies
* state CSS classes for visited, complete, locked, and optional states. Defers the
* ready signal until all embedded images have loaded via `imageready`.
* @extends AdaptView
*/
class MenuItemView extends AdaptView {

attributes() {
Expand Down
17 changes: 17 additions & 0 deletions js/views/menuView.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
/**
* @file Menu View - Renders a menu-type content object
* @module core/js/views/menuView
* @description Extends {@link module:core/js/views/contentObjectView~ContentObjectView}
* for menu content objects. Renders child content objects as
* {@link module:core/js/views/menuItemView~MenuItemView} instances inside
* `.js-children`. The child view class is currently fixed; making it configurable
* is a planned improvement.
*/
import ContentObjectView from 'core/js/views/contentObjectView';
import MenuItemView from 'core/js/views/menuItemView';

/**
* @class MenuView
* @classdesc View for menu-type content objects. Displays child content objects
* (pages or nested menus) as a list of {@link module:core/js/views/menuItemView~MenuItemView}
* cards inside `.js-children`. All ready-state and lifecycle handling is inherited
* from {@link module:core/js/views/contentObjectView~ContentObjectView}.
* @extends ContentObjectView
*/
class MenuView extends ContentObjectView {}

Object.assign(MenuView, {
Expand Down
22 changes: 22 additions & 0 deletions js/views/pageView.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,30 @@
/**
* @file Page View - Renders a page-type content object
* @module core/js/views/pageView
* @description Extends {@link module:core/js/views/contentObjectView~ContentObjectView}
* for page content objects. Registered as the 'page' component type. Cleans up
* any injected page-label element when the view is removed.
*/
import components from 'core/js/components';
import ContentObjectView from 'core/js/views/contentObjectView';

/**
* @class PageView
* @classdesc View for page-type content objects. A page is the primary learner-facing
* screen and contains one or more articles. This view adds cleanup of any page-label
* element on removal; all other lifecycle behaviour is inherited from
* {@link module:core/js/views/contentObjectView~ContentObjectView}.
* @extends ContentObjectView
*/
class PageView extends ContentObjectView {

/**
* Removes the page view from the DOM. Cleans up the injected
* `$pageLabel` element (added by the page heading plugin) before
* delegating full removal to
* {@link module:core/js/views/contentObjectView~ContentObjectView#remove}.
* @returns {PageView} This view instance
*/
remove() {
if (this.$pageLabel) {
this.$pageLabel.remove();
Expand Down
Loading
Loading