diff --git a/README.md b/README.md
index 55f1c2f..548a057 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# adapt-pageNav
-**PageNav** is a *presentation component* that adds basic navigation controls to a page
+**PageNav** is a *presentation component* that adds basic navigation controls to a page.
@@ -13,21 +13,19 @@ The attributes listed below are used in *components.json* to configure **PageNav
Navigation bar component which can contain some or all of the following buttons:
-- _returnToPreviousLocation (takes you back to the previous location - not back in history, just the last routed location)
-- _root (takes you back to top level menu)
-- _up (takes you to the menu the next level up in the hierarchy)
-- _previous (navigates directly to the previous page, if exists, without having to navigate via the menu)
-- _next (navigates directly to the next page, if exists, without having to navigate via the menu)
-- _sibling (1,2,3,4 etc buttons representing each sibling page)
-- _close (closes the course window - only possible if the course was launched in a popup window)
+- `_root`: Navigates to the top level menu
+- `_up`: Navigates to the menu that is the next level up in the hierarchy. For instance, a sub menu.
+- `_previous`: Navigates to the previous page if it exists and is unlocked
+- `_next`: Navigates to the next page if it exists and is unlocked
+- `_close`: Closes the course window. Only possible if the course was launched in a popup window
-The pageNav buttons will respect any [locking](https://github.com/adaptlearning/adapt_framework/wiki/Locking-objects-with-'_isLocked'-and-'_lockType'#using-locking-with-menus) that has been configured in Adapt. In cases not covered by Adapt's locking system - such as a [start page](https://github.com/adaptlearning/adapt_framework/wiki/Content-starts-with-course.json#example-1) that appears immediately before the main menu - the setting `_lockUntilPageComplete` can be used to disable the button until the current page has been completed.
+The **PageNav** buttons will respect any [locking](https://github.com/adaptlearning/adapt_framework/wiki/Locking-objects-with-'_isLocked'-and-'_lockType'#using-locking-with-menus) that has been configured in Adapt. In cases not covered by Adapt's locking system - such as a [start page](https://github.com/adaptlearning/adapt_framework/wiki/Content-starts-with-course.json#example-1) that appears immediately before the main menu - the setting `_lockUntilPageComplete` can be used to disable the button until the current page has been completed.
### Attributes
-[**core model attributes**](https://github.com/adaptlearning/adapt_framework/wiki/Core-model-attributes): These are inherited by every Adapt component. [Read more](https://github.com/adaptlearning/adapt_framework/wiki/Core-model-attributes).
+[**core model attributes**](https://github.com/adaptlearning/adapt_framework/wiki/Core-model-attributes): These are inherited by every Adapt component. [Read more](https://github.com/adaptlearning/adapt_framework/wiki/Core-model-attributes)
-**\_component** (string): This value must be: `pageNav`. (One word.)
+**\_component** (string): This value must be `pageNav` (one word)
**\_classes** (string): CSS class name to be applied to **PageNav**’s containing `div`. The class must be predefined in one of the Less files. Separate multiple classes with a space.
@@ -35,43 +33,48 @@ The pageNav buttons will respect any [locking](https://github.com/adaptlearning/
**instruction** (string): This optional text appears above the component. It is frequently used to guide the learner’s interaction with the component.
-**\_loopStyle** (string): Acceptable values are `allPages`, `siblings`, and `none`. `allPages` = loop sequentially through all pages in course. `siblings` = loop sequentially through all pages in current parent object. `none` = disable previous and next buttons at start and end of the pages in the current parent object.
+**\_loopStyle** (string): Acceptable values are `allPages`, `siblings`, and `none`. Defaults to `none`.
+- `allPages`: Loop sequentially through all pages in course
+- `siblings`: Loop sequentially through all pages in current parent object
+- `none`: Disable previous and next buttons at start and end of the pages in the current parent object.
**\_shouldSkipOptionalPages** (boolean): Skip pages that are set to `"_isOptional": true`. Default is `false`.
-**\_buttons** (object): The following attributes configure the defaults for the **Quickanv** buttons. These attributes are available on all of the following buttons **\_returnToPreviousLocation**, **\_previous**, **\_root**, **\_up**, **\_next**, **\_sibling**, and **\_close**.
+**\_buttons** (object): The following attributes configure the defaults for the **Quickanv** buttons. These attributes are available on all of the following buttons **\_previous**, **\_root**, **\_up**, **\_next**, and **\_close**.
#### Global button configurations
>**\_isEnabled** (boolean): Turns the button on and off. Acceptable values are `true` and `false`.
->**\_lockUntilPageComplete** (boolean): For use when the standard Adapt locking system doesn't apply, such as in a start page before the main menu. Acceptable values are `true` and `false`.
+>**\_lockUntilPageComplete** (boolean): For use when the standard Adapt locking system doesn't apply, such as in a start page before the main menu. Locks a button until the current page is complete. Acceptable values are `true` and `false`. Defaults to `false`
>**\_order** (number): Defines the display order of the button. Numerical order with 0 rendering first.
>**\_classes** (string): CSS class name to be applied to the `button`. The class must be predefined in one of the Less files. Separate multiple classes with a space.
->**\_iconClass** (string): CSS class name to be applied to the `button` icon. The class must be predefined in one of the Less files with the corresponding icon be added as part of a font. Suggested icons for each button detailed in the [_example.json_](https://github.com/cgkineo/adapt-pageNav/blob/master/example.json). List of all available [_vanilla_ icons](https://github.com/adaptlearning/adapt-contrib-vanilla/wiki/Icons) to choose from.
+>**\_iconClass** (string): CSS class name to be applied to the `button` icon. The class must be predefined in one of the Less files with the corresponding icon included as part of a font. To have _no_ icon, leave this field blank. Suggested icons for each button are detailed in the [_example.json_](https://github.com/cgkineo/adapt-pageNav/blob/master/example.json). See the list of all available [_vanilla_ icons](https://github.com/adaptlearning/adapt-contrib-vanilla/wiki/Icons) to choose from.
->**\_alignIconright** (boolean): Defines whether the icon is aligned to the left or right of the text. Default is `false` which aligns the icon to the left of the text.
+>**\_iconAlignment** (string): Determines how the icon is aligned to the text. Options include `auto`, `left`, `right`, `top`, and `bottom`. When using `auto`, the position will automatically adjust based on whether the user is using an LTR or RTL lanaguage. The `_next` button will also be adjusted accordingly when using `auto` (i.e. the icon will be right-aligned for LTR and left-aligned for RTL). Defaults to `auto`.
>**text** (string): Defines the text that renders in the `button`.
>**ariaLabel** (string): This text is associated with the button. It renders as part of the aria label to give screen readers more information.
->**\_showTooltip** (boolean): Defines whether the tooltip renders on hover. Default is `false`.
+> **\_tooltip** (object): The tooltip object. Used when tooltips are enabled globally
->**tooltip** (string): Defines the text that renders in the tooltip.
+>> **\_isEnabled** (boolean): Enables tooltips on the button
-#### **\_previous** / **\_root** / **\_up** / **\_next** / **\_sibling**
+>> **text** (string): The text of the tooltip
+
+#### **\_previous**, **\_root**, **\_up**, and **\_next** properties
>**\_customRouteId** (string): Overrides the route ID. For use when non standard route navigation is required.
----------------------------
-**Framework versions:** 5.2+
+**Framework versions:** 5.30.2+
**Vanilla versions:** 5.1.1+
**Author / maintainer:** Kineo
**Accessibility support:** WAI AA
**RTL support:** Yes
-**Cross-platform coverage:** Chrome, Chrome for Android, Firefox (ESR + latest version), Edge, IE11, Safari 12+13 for macOS/iOS/iPadOS, Opera
+**Cross-platform coverage:** Chrome, Chrome for Android, Firefox (ESR + latest version), Edge, Safari for macOS/iOS/iPadOS, Opera
diff --git a/bower.json b/bower.json
index ebd165b..1e1b58f 100644
--- a/bower.json
+++ b/bower.json
@@ -5,7 +5,7 @@
"url": "git://github.com/cgkineo/adapt-pageNav.git"
},
"version": "2.4.0",
- "framework": ">=5.2",
+ "framework": ">=5.30.2",
"homepage": "https://github.com/cgkineo/adapt-pageNav",
"issues": "https://github.com/cgkineo/adapt-pageNav/issues/",
"component": "pageNav",
diff --git a/demo.fw.png b/demo.fw.png
deleted file mode 100644
index 942d901..0000000
Binary files a/demo.fw.png and /dev/null differ
diff --git a/example.json b/example.json
index b1ffe72..ed83f50 100644
--- a/example.json
+++ b/example.json
@@ -1,118 +1,97 @@
- // To go in the component.json file for each page
- // --------------------------------------------------
- {
- "_id": "c-05",
- "_parentId": "b-05",
- "_type": "component",
- "_component": "pageNav",
- "_classes": "",
- "_layout": "full",
- "title": "",
- "displayTitle": "",
- "body": "",
- "instruction": "",
- "_loopStyleComment": {
- "allPages": "loop sequentially through all pages in course",
- "siblings": "loop sequentially through all pages in current parent object",
- "none": "disable previous and next buttons at start and end of the pages in the current parent object"
- },
- "_loopStyle": "none",
- "_shouldSkipOptionalPages": false,
- "_buttons": {
- "_returnToPreviousLocation": {
- "_isEnabled": false,
- "_lockUntilPageComplete": false,
- "_order": 1,
- "_classes": "",
- "_iconClassComment": "Suggested icon = 'icon-controls-left'",
- "_iconClass": "",
- "_alignIconRight": false,
- "text": "Return",
- "ariaLabel": "Return to previous location",
- "_showTooltip": false,
- "tooltip": "{{displayTitle}}"
- },
- "_previous": {
+// To go in the component.json file for each page
+// --------------------------------------------------
+{
+ "_id": "c-05",
+ "_parentId": "b-05",
+ "_type": "component",
+ "_component": "pageNav",
+ "_classes": "",
+ "_layout": "full",
+ "title": "",
+ "displayTitle": "",
+ "body": "",
+ "instruction": "",
+ "_loopStyleComment": {
+ "allPages": "loop sequentially through all pages in course",
+ "siblings": "loop sequentially through all pages in current parent object",
+ "none": "disable previous and next buttons at start and end of the pages in the current parent object"
+ },
+ "_loopStyle": "none",
+ "_shouldSkipOptionalPages": false,
+ "_buttons": {
+ "_root": {
+ "_isEnabled": true,
+ "_lockUntilPageComplete": false,
+ "_order": 1,
+ "_classes": "",
+ "_iconClass": "icon-home",
+ "_iconAlignment": "auto",
+ "text": "Go to main menu",
+ "ariaLabel": "Go to main menu",
+ "_tooltip": {
"_isEnabled": true,
- "_lockUntilPageComplete": false,
- "_order": 1,
- "_classes": "",
- "_iconClassComment": "Suggested icon = 'icon-controls-left'",
- "_iconClass": "",
- "_alignIconRight": false,
- "text": "Previous",
- "ariaLabel": "Previous Page",
- "_showTooltip": false,
- "tooltip": "{{displayTitle}}",
- "_customRouteId": ""
+ "text": "{{displayTitle}}"
},
- "_root": {
+ "_customRouteId": ""
+ },
+ "_up": {
+ "_isEnabled": false,
+ "_lockUntilPageComplete": false,
+ "_order": 1,
+ "_classes": "",
+ "_iconClass": "icon-controls-up",
+ "_iconAlignment": "auto",
+ "text": "Back to menu",
+ "ariaLabel": "Back to menu",
+ "_tooltip": {
"_isEnabled": true,
- "_lockUntilPageComplete": false,
- "_order": 1,
- "_classes": "",
- "_iconClassComment": "Suggested icon = 'icon-home'",
- "_iconClass": "",
- "_alignIconRight": false,
- "text": "Go to main menu",
- "ariaLabel": "Go to main menu",
- "_showTooltip": false,
- "tooltip": "{{displayTitle}}",
- "_customRouteId": ""
+ "text": "{{displayTitle}}"
},
- "_up": {
- "_isEnabled": false,
- "_lockUntilPageComplete": false,
- "_order": 1,
- "_classes": "",
- "_iconClassComment": "Suggested icon = 'icon-controls-up'",
- "_iconClass": "",
- "_alignIconRight": false,
- "text": "Back to menu",
- "ariaLabel": "Back to menu",
- "_showTooltip": false,
- "tooltip": "{{displayTitle}}",
- "_customRouteId": ""
- },
- "_next": {
+ "_customRouteId": ""
+ },
+ "_previous": {
+ "_isEnabled": true,
+ "_lockUntilPageComplete": false,
+ "_order": 1,
+ "_classes": "",
+ "_iconClass": "icon-controls-left",
+ "_iconAlignment": "auto",
+ "text": "Previous",
+ "ariaLabel": "Previous Page",
+ "_tooltip": {
"_isEnabled": true,
- "_lockUntilPageComplete": false,
- "_order": 1,
- "_classes": "",
- "_iconClassComment": "Suggested icon = 'icon-controls-right'",
- "_iconClass": "",
- "_alignIconRight": true,
- "text": "Next",
- "ariaLabel": "Next Page",
- "_showTooltip": false,
- "tooltip": "{{displayTitle}}",
- "_customRouteId": ""
+ "text": "{{displayTitle}}"
},
- "_sibling": {
- "_isEnabled": false,
- "_lockUntilPageComplete": false,
- "_order": 1,
- "_classes": "",
- "_iconClass": "",
- "_alignIconRight": false,
- "text": "{{inc index}}",
- "ariaLabel": "Page {{inc index}}",
- "_showTooltip": false,
- "tooltip": "{{displayTitle}}",
- "_customRouteId": ""
+ "_customRouteId": ""
+ },
+ "_next": {
+ "_isEnabled": true,
+ "_lockUntilPageComplete": false,
+ "_order": 1,
+ "_classes": "",
+ "_iconClass": "icon-controls-right",
+ "_iconAlignment": "auto",
+ "text": "Next",
+ "ariaLabel": "Next Page",
+ "_tooltip": {
+ "_isEnabled": true,
+ "text": "{{displayTitle}}"
},
- "_close": {
- "_isEnabled": false,
- "_lockUntilPageComplete": false,
- "_order": 1,
- "_classes": "",
- "_iconClassComment": "Suggested icon = 'icon-cross'",
- "_iconClass": "",
- "_alignIconRight": false,
- "text": "Close",
- "ariaLabel": "Close window",
- "_showTooltip": false,
- "tooltip": "Close window"
+ "_customRouteId": ""
+ },
+ "_close": {
+ "_isEnabled": false,
+ "_lockUntilPageComplete": false,
+ "_order": 1,
+ "_classes": "",
+ "_iconClass": "icon-cross",
+ "_iconAlignment": "auto",
+ "text": "Close",
+ "ariaLabel": "Close window",
+ "_tooltip": {
+ "_isEnabled": true,
+ "text": "Close window"
}
}
}
+}
diff --git a/js/PageNavModel.js b/js/PageNavModel.js
new file mode 100644
index 0000000..fac2b1e
--- /dev/null
+++ b/js/PageNavModel.js
@@ -0,0 +1,164 @@
+import Adapt from 'core/js/adapt';
+import location from 'core/js/location';
+import data from 'core/js/data';
+import ComponentModel from 'core/js/models/componentModel';
+
+class PageNavModel extends ComponentModel {
+ init() {
+ this.listenTo(Adapt, 'router:location', this.setupItemsModel);
+
+ super.init();
+ };
+
+ setupItemsModel() {
+ this.set('_items', this.getNavigationData());
+ }
+
+ /**
+ * Combines the config, model, order, index and type for each _buttons item
+ *
+ * @returns {array} An array of combined button items
+ */
+ getNavigationData() {
+ const buttons = this.get('_buttons');
+ if (!buttons) return [];
+
+ const buttonTypeModels = this.getButtonTypeModels();
+ const currentPageComplete = buttonTypeModels._page.get('_isComplete');
+ const unsortedItems = [];
+ let order = 0;
+ let item;
+
+ for (const type in buttons) {
+ const buttonConfig = buttons[type];
+
+ // Skip the button if not enabled
+ if (!buttonConfig._isEnabled) continue;
+
+ // Get models, skipping any undefined types (ex. deprecated button types)
+ let buttonModel = buttonTypeModels[type];
+ if (!buttonModel) continue;
+
+ // Find buttonModel from config._customRouteId if not found in defined type
+ if (buttonConfig._customRouteId) {
+ buttonModel = data.findById(buttonConfig._customRouteId);
+ }
+
+ // Convert found buttonModel to json if exists or create an 'undefined' json
+ item = buttonModel ? buttonModel.toJSON() : { _isHidden: true };
+
+ Object.assign(item, buttonConfig, {
+ type,
+ index: 0,
+ order: order++,
+ _tooltipId: `pagenav_btn${type}`,
+ locked: item._isLocked || (buttonConfig._lockUntilPageComplete && !currentPageComplete)
+ });
+ unsortedItems.push(item);
+ }
+
+ // requires a stable sorting algorithm - native sorting in Chrome is unstable (should be stable from Chrome 70)
+ const sortedItems = _.sortBy(unsortedItems, '_order');
+
+ sortedItems.forEach((item, index) => {
+ item._index = index;
+ });
+
+ return sortedItems;
+ };
+
+ getButtonTypeModels() {
+ return {
+ _page: this.getCurrentPage(),
+ _up: this.getCurrentMenu(),
+ _root: Adapt.course,
+ _next: this.getNextPage(),
+ _previous: this.getPrevPage(),
+ _close: this.getClose()
+ };
+ }
+
+ getCurrentPage() {
+ return location._currentModel;
+ };
+
+ getCurrentMenu() {
+ return this.findAncestor('menu');
+ };
+
+ getPrevPage() {
+ const currentPage = this.getCurrentPage();
+ const currentPageId = currentPage.get('_id');
+ const pages = this.getPages();
+ let hasFoundCurrentPage = false;
+
+ for (const page of pages.reverse()) {
+ const isNotAvailable = !page.get('_isAvailable');
+ if (isNotAvailable) continue;
+
+ if (!hasFoundCurrentPage) {
+ hasFoundCurrentPage = page.get('_id') === currentPageId;
+ continue;
+ }
+
+ if (!this.get('_shouldSkipOptionalPages') || !page.get('_isOptional')) {
+ return page;
+ }
+ }
+ };
+
+ getNextPage() {
+ const currentPage = this.getCurrentPage();
+ const currentPageId = currentPage.get('_id');
+ const pages = this.getPages();
+ let hasFoundCurrentPage = false;
+
+ for (const page of pages) {
+ const isNotAvailable = !page.get('_isAvailable');
+ if (isNotAvailable) continue;
+
+ if (!hasFoundCurrentPage) {
+ hasFoundCurrentPage = page.get('_id') === currentPageId;
+ continue;
+ }
+
+ if (!this.get('_shouldSkipOptionalPages') || !page.get('_isOptional')) {
+ return page;
+ }
+ }
+ };
+
+ getPages() {
+ const loopStyle = this.get('_loopStyle');
+ if (!loopStyle) return [];
+
+ let loop = false;
+ let descendants;
+ let currentMenu;
+
+ switch (loopStyle) {
+ case 'allPages':
+ loop = true;
+ descendants = Adapt.course.getAllDescendantModels(true);
+ break;
+ default:
+ currentMenu = this.getCurrentMenu();
+ descendants = currentMenu.getAllDescendantModels(true);
+ }
+
+ if (loop) {
+ // Create a double copy to allow loop searching
+ descendants = descendants.concat(descendants);
+ }
+
+ return descendants.filter(model => {
+ return model.get('_type') === 'page';
+ });
+ };
+
+ getClose() {
+ return new Backbone.Model({ _id: '' });
+ };
+}
+
+export default PageNavModel;
diff --git a/js/PageNavView.js b/js/PageNavView.js
new file mode 100644
index 0000000..32d6574
--- /dev/null
+++ b/js/PageNavView.js
@@ -0,0 +1,88 @@
+import Adapt from 'core/js/adapt';
+import router from 'core/js/router';
+import ComponentView from 'core/js/views/componentView';
+import tooltips from 'core/js/tooltips';
+import logging from 'core/js/logging';
+
+class PageNavView extends ComponentView {
+ initialize() {
+ _.bindAll(this, 'postRender', 'onButtonClick');
+
+ super.initialize();
+ }
+
+ preRender() {
+ this.listenTo(Adapt, 'remove', this.remove);
+ this.listenTo(Adapt.contentObjects, {
+ 'change:_isComplete change:_isLocked': this.onContentObjectComplete
+ });
+ };
+
+ postRender() {
+ this.setReadyStatus();
+ this.setupInviewCompletion();
+ this.setupTooltips();
+ };
+
+ onContentObjectComplete() {
+ // Update model so that _lockUntilPageComplete works properly
+ this.model.setupItemsModel();
+ };
+
+ onButtonClick(event) {
+ const $target = $(event.currentTarget);
+ const index = $target.data('item-index');
+ const item = this.model.get('_items')[index];
+ const type = item.type;
+
+ // Close button
+ if (type === '_close') {
+ this.closeWindow();
+ return;
+ }
+
+ // Check if locked
+ const isLocked = item._isHidden || item._isLocked;
+ if (isLocked) return;
+
+ this.navigateTo(item._id);
+ };
+
+ closeWindow() {
+ try {
+ const scormWrapper = require('extensions/adapt-contrib-spoor/js/scorm/wrapper');
+ if (scormWrapper) {
+ const scormWrapperInstance = scormWrapper.getInstance();
+ if (scormWrapperInstance.lmsConnected && !scormWrapperInstance.finishCalled) {
+ scormWrapperInstance.finish();
+ }
+ }
+ } catch (err) {
+ logging.warn(`Could not close window. Error: ${err}`);
+ }
+ top.window.close();
+ };
+
+ setupTooltips() {
+ const items = this.model.get('_items');
+ items.forEach(item => {
+ if (!item._tooltip || item._isHidden) return;
+
+ tooltips.register({
+ _id: item._tooltipId,
+ _isEnabled: item._tooltip._isEnabled,
+ text: Handlebars.compile(item._tooltip.text)(item)
+ });
+ });
+ };
+
+ navigateTo(id) {
+ router.navigateToElement(id);
+ };
+
+ static get template() {
+ return 'pageNav.jsx';
+ }
+}
+
+export default PageNavView;
diff --git a/js/adapt-pageNav.js b/js/adapt-pageNav.js
index c29dbf7..7ec018e 100644
--- a/js/adapt-pageNav.js
+++ b/js/adapt-pageNav.js
@@ -1,12 +1,8 @@
-define([
- 'core/js/adapt',
- './model',
- './view'
-], function(Adapt, Model, View) {
-
- return Adapt.register('pageNav', {
- model: Model,
- view: View
- });
+import components from 'core/js/components';
+import PageNavView from './PageNavView';
+import PageNavModel from './PageNavModel';
+export default components.register('pageNav', {
+ view: PageNavView,
+ model: PageNavModel
});
diff --git a/js/model.js b/js/model.js
deleted file mode 100644
index 86b2b05..0000000
--- a/js/model.js
+++ /dev/null
@@ -1,253 +0,0 @@
-define([
- 'core/js/adapt',
- 'core/js/location',
- 'core/js/models/componentModel'
-], function(Adapt, Location, ComponentModel) {
-
- var Model = ComponentModel.extend({
-
- getNavigationData: function() {
-
- /*
- * Combine the config, model, order, index and type for each _buttons
- * Add each combined item to an array
- */
-
- var buttonTypeModels = {
- _returnToPreviousLocation: this.getReturnToPreviousLocation(),
- _page: this.getCurrentPage(),
- _up: this.getCurrentMenu(),
- _root: Adapt.course,
- _next: this.getNextPage(),
- _previous: this.getPrevPage(),
- _sibling: this.getSiblingPages(),
- _close: new Backbone.Model({
- _id: '',
- _onClick: `
-try {
- var scormWrapper = require('extensions/adapt-contrib-spoor/js/scorm/wrapper');
- if (scormWrapper) {
- var scormWrapperInstance = scormWrapper.getInstance();
- if (scormWrapperInstance.lmsConnected && !scormWrapperInstance.finishCalled) {
- scormWrapperInstance.finish();
- }
- }
-} catch (err) {}
-top.window.close();
-`
- })
- };
-
- var data = [];
- var buttons = this.get('_buttons');
-
- if (!buttons) {
- return data;
- }
-
- var order = 0;
- var item;
- var currentPageComplete = buttonTypeModels._page.get('_isComplete');
-
- for (var attrName in buttons) {
-
- var buttonConfig = buttons[attrName];
- var buttonModel = buttonTypeModels[attrName];
-
- if (attrName === '_sibling') {
-
- // Skip if only one sibling
- if (buttonModel.length <= 1) continue;
-
- // Generate sibling entries
- _.each(buttonModel, function(model, index) {
-
- item = model.toJSON();
- _.extend(item, buttonConfig, {
- type: attrName,
- index: index,
- _isCurrent: item._id === Location._currentId,
- order: order++,
- locked: item._isLocked || (buttonConfig._lockUntilPageComplete && !currentPageComplete)
- });
- data.push(item);
-
- });
-
- continue;
-
- }
-
- // Find buttonModel from config._customRouteId if not found in defined type
- if (buttonConfig._customRouteId) buttonModel = Adapt.findById(buttonConfig._customRouteId);
-
- // Convert found buttonModel to json if exists or create an 'undefined' json
- item = buttonModel ? buttonModel.toJSON() : { '_isHidden': true };
-
- _.extend(item, buttonConfig, {
- type: attrName,
- index: 0,
- order: order++,
- locked: item._isLocked || (buttonConfig._lockUntilPageComplete && !currentPageComplete)
- });
- data.push(item);
-
- }
-
- // requires a stable sorting algorithm - native sorting in Chrome is unstable (should be stable from Chrome 70)
- var orderedData = _.sortBy(data, '_order');
-
- orderedData.forEach(function(item, index) {
- item._index = index;
- });
-
- return orderedData;
-
- },
-
- getReturnToPreviousLocation: function() {
-
- return Adapt.location._previousId ? Adapt.findById(Adapt.location._previousId) : null;
-
- },
-
- getCurrentPage: function() {
-
- var parents = this.getAncestorModels ? this.getAncestorModels() : this.getParents().models;
- for (var i = 0, l = parents.length; i < l; i++) {
-
- var model = parents[i];
- switch (model.get('_type')) {
- case 'page':
- return model;
- }
-
- }
-
- },
-
- getCurrentMenu: function() {
-
- var parents = this.getAncestorModels ? this.getAncestorModels() : this.getParents().models;
- for (var i = 0, l = parents.length; i < l; i++) {
-
- var model = parents[i];
- switch (model.get('_type')) {
- case 'menu':
- case 'course':
- return model;
- }
-
- }
-
- },
-
- getSiblingPages: function() {
-
- var currentMenu = this.getCurrentMenu();
- var siblingModels = currentMenu.getAllDescendantModels(true);
-
- siblingModels = _.filter(siblingModels, function(model) {
- return model.get('_type') === 'page' && model.get('_isAvailable') &&
- (!this.get('_shouldSkipOptionalPages') || !model.get('_isOptional'));
- }, this);
-
- return siblingModels;
-
- },
-
- getPrevPage: function() {
-
- var currentPage = this.getCurrentPage();
- var currentPageId = currentPage.get('_id');
-
- var pages = this.getPages();
-
- var hasFoundCurrentPage = false;
- for (var i = pages.length-1; i > -1; i--) {
-
- var page = pages[i];
- var isNotAvailable = !page.get('_isAvailable');
- if (isNotAvailable) continue;
-
- if (!hasFoundCurrentPage) {
- hasFoundCurrentPage = page.get('_id') === currentPageId;
- continue;
- }
-
- if (!this.get('_shouldSkipOptionalPages') || !page.get('_isOptional')) {
- return page;
- }
-
- }
-
- return;
-
- },
-
- getNextPage: function() {
-
- var currentPage = this.getCurrentPage();
- var currentPageId = currentPage.get('_id');
-
- var pages = this.getPages();
-
- var hasFoundCurrentPage = false;
- for (var i = 0, l = pages.length; i < l; i++) {
-
- var page = pages[i];
- var isNotAvailable = !page.get('_isAvailable');
- if (isNotAvailable) continue;
-
- if (!hasFoundCurrentPage) {
- hasFoundCurrentPage = page.get('_id') === currentPageId;
- continue;
- }
-
- if (!this.get('_shouldSkipOptionalPages') || !page.get('_isOptional')) {
- return page;
- }
-
- }
-
- return;
-
- },
-
- getPages: function() {
-
- var loopStyle = this.get('_loopStyle');
-
- if (!loopStyle) return [];
-
- var loop = false;
- var descendants;
- switch (loopStyle) {
- case 'allPages':
- loop = true;
- descendants = Adapt.course.getAllDescendantModels(true);
- break;
- case 'siblings':
- loop = true;
- /* falls through */
- default:
- var currentMenu = this.getCurrentMenu();
- descendants = currentMenu.getAllDescendantModels(true);
- }
-
- if (loop) {
- // Create a double copy to allow loop searching
- descendants = descendants.concat(descendants);
- }
-
- return _.filter(descendants, function(model) {
- return model.get('_type') === 'page';
- });
-
- }
-
- });
-
- return Model;
-
-});
diff --git a/js/tooltip.js b/js/tooltip.js
deleted file mode 100644
index 5af7cf4..0000000
--- a/js/tooltip.js
+++ /dev/null
@@ -1,114 +0,0 @@
-/* eslint-disable no-var */
-define(["core/js/adapt"], function (Adapt) {
- var Tooltip = Backbone.View.extend({
- className: "collab__tooltip",
-
- initialize: function (options) {
- this.removeOtherTooltips();
- this.setupEventListeners();
- this.setupData(options);
-
- this.render();
- },
-
- removeOtherTooltips: function () {
- Adapt.trigger("tooltip:remove");
- Adapt.tooltip = this;
- },
-
- setupEventListeners: function () {
- _.bindAll(this, "remove", "postRender", "show");
- this.show = _.debounce(this.show, 17);
-
- $(document).on("mouseover", this.remove);
-
- this.listenTo(Adapt, {
- "device:resize": this.checkPosition,
- "tooltip:remove": this.remove,
- remove: this.remove
- });
- },
-
- setupData: function (options) {
- this.$target = options.$target;
- this.id = this.$target.attr("data-id");
- this.type = this.$target.attr("data-type");
- this.index = this.$target.attr("data-index");
-
- this.model.set("tooltip", this.$target.attr("data-tooltip"));
- },
-
- render: function () {
- var template = Handlebars.templates["pageNav-tooltip"];
-
- this.$el.html(template(this.model.toJSON()));
- _.defer(this.postRender);
- },
-
- postRender: function () {
- if (this.isRemoved) return;
-
- this.checkPosition();
- this.show();
- },
-
- checkPosition: function () {
- if (this.isRemoved) return;
-
- var buttonPosition = this.$target.position();
- var buttonWidth = this.$target.outerWidth(true);
- var buttonHalfWidth = buttonWidth / 2;
- var buttonCenterLeft = buttonPosition.left + buttonHalfWidth;
-
- var tooltipWidth = this.$el.outerWidth(true);
- var tooltipHalfWidth = tooltipWidth / 2;
-
- var tooltipCenter = {
- top: buttonPosition.top,
- left: buttonCenterLeft
- };
-
- var $offsetParent = this.$el.offsetParent();
- var parentWidth = $offsetParent.innerWidth();
-
- var overflowRight = parentWidth - (tooltipCenter.left + tooltipHalfWidth);
- var overflowLeft = tooltipCenter.left - tooltipHalfWidth;
-
- var isOverflowingRight = overflowRight < 0;
- var isOverflowingLeft = overflowLeft < 0;
-
- var leftOffset = isOverflowingRight
- ? overflowRight
- : isOverflowingLeft
- ? -overflowLeft
- : 0;
-
- this.$el.css({
- top: tooltipCenter.top,
- left: tooltipCenter.left + leftOffset
- });
-
- this.$el.find(".pagenav__triangle").css({
- left: tooltipHalfWidth - leftOffset
- });
- },
-
- show: function () {
- if (this.isRemoved) return;
-
- this.$el.addClass("show");
- },
-
- remove: function () {
- this.isRemoved = true;
-
- delete this.$target;
- delete Adapt.tooltip;
-
- $(document).off("mouseover", this.onBodyMouseOver);
- Backbone.View.prototype.remove.call(this);
- }
- });
-
- return Tooltip;
-});
diff --git a/js/view.js b/js/view.js
deleted file mode 100644
index e641927..0000000
--- a/js/view.js
+++ /dev/null
@@ -1,194 +0,0 @@
-
-define([
- 'core/js/adapt',
- 'core/js/views/componentView',
- './tooltip'
-], function(Adapt, ComponentView, Tooltip) {
-
- function getAttributes($node){
- var attrs = {};
- _.each($node[0].attributes, function (attribute) {
- attrs[attribute.name] = attribute.value;
- });
- return attrs;
- }
-
- var View = ComponentView.extend({
-
- events: {
- 'click .js-pagenav-btn': 'onButtonClick',
- 'mouseover .js-pagenav-btn': 'onButtonTooltip'
- },
-
- preRender: function() {
- this.model.set('_items', this.model.getNavigationData());
-
- this.$el.addClass('pagenav ' + this.model.get('_id'));
-
- _.bindAll(this, 'postRender', 'checkButtonStates');
-
- this.listenTo(Adapt, 'remove', this.remove);
- this.listenTo(Adapt.contentObjects, {
- 'change:_isComplete change:_isLocked': this.onContentObjectComplete
- });
-
- },
-
- postRender: function() {
- this.checkButtonStates();
- this.setReadyStatus();
- this.setupInview();
- },
-
- setupInview: function() {
- const selector = this.getInviewElementSelector();
- if (!selector) return this.setCompletionStatus();
- this.setupInviewCompletion(selector);
- },
-
- /**
- * determines which element should be used for inview logic - body, instruction, title or widget - and returns the selector for that element
- */
- getInviewElementSelector: function() {
- if (this.model.get('body')) return '.component__body';
- if (this.model.get('instruction')) return '.component__instruction';
- if (this.model.get('displayTitle')) return '.component__title';
- if (this.model.get('_buttons')) return '.component__widget';
- return null;
- },
-
- onContentObjectComplete: function() {
-
- _.defer(this.checkButtonStates);
-
- },
-
- checkButtonStates: function() {
-
- this.$('button').each(function(index, item) {
- this.checkButtonState(item);
- }.bind(this));
-
- },
-
- checkButtonState: function(button) {
-
- var $button = $(button);
- var id = $button.attr('data-id');
- var index = $button.attr('data-item-index');
-
- if (!id) return;
-
- // get the button data
- var items = this.model.getNavigationData();
- var data = items[index];
-
- // rerender the button
- var $buttonRendered = $(Handlebars.partials['pageNav-item'](data));
- if ($buttonRendered.length === 0) {
- $button.remove();
- return;
- }
-
- // get button attribute names from current and rerendered
- var renderedAttrs = getAttributes($buttonRendered);
- var attrs = getAttributes($button);
- var renderedAttrNames = _.keys(renderedAttrs);
- var attrNames = _.keys(attrs);
-
- // remove redundant attributes
- var removeAttrNames = _.difference(attrNames, renderedAttrNames);
- removeAttrNames.forEach(function(name) {
- $button.removeAttr(name);
- });
-
- // update remaining attributes
- $button.attr(renderedAttrs);
-
- // update button text
- $button.html($buttonRendered.html());
-
- },
-
- onButtonClick: function(event) {
-
- var $target = $(event.currentTarget);
- var isLocked = $target.hasClass('is-locked');
- var isSelected = $target.hasClass('is-selected');
-
- if (isLocked || isSelected) return;
-
- var id = $target.attr('data-id');
- var index = $target.attr('data-item-index');
-
- switch (id) {
- case '':
- var items = this.model.getNavigationData();
- try {
- var execute = new Function(items[index]._onClick||'');
- execute();
- } catch (err) {
- Adapt.log.error(err);
- }
- break;
- default:
- this.navigateTo(id);
- break;
- }
- },
-
- onButtonTooltip: function(event) {
-
- var $target = $(event.currentTarget);
-
- var id = $target.attr('data-id') || this.model.getCurrentPage().get('_id');
-
- if (!id) {
- return;
- }
-
- // If tooltip isn't defined allow the event to propogate down to the document
- if (!$target.attr('data-tooltip')) {
- return;
- }
-
- // Don't allow event to propogate, to stop the document over events
- event.stopPropagation();
-
-
- // If this tooltip is already rendered then skip
- if (Adapt.tooltip) {
-
- var type = $target.attr('data-type');
- var index = $target.attr('data-index');
- var isCurrentTooltip = (Adapt.tooltip.type === type) && (Adapt.tooltip.index === index);
-
- if (isCurrentTooltip) {
- return;
- }
-
- }
-
- var tooltip = new Tooltip({
- $target: $target,
- model: Adapt.findById(id)
- });
-
- this.$('.pagenav__tooltip-container').append(tooltip.$el);
-
- },
-
- navigateTo: function(id) {
-
- var isCourse = (id === Adapt.course.get('_id'));
- var hash = '#' + (isCourse ? '/' : '/id/' + id);
-
- Backbone.history.navigate(hash, { trigger: true, replace: false });
-
- }
-
- });
-
- return View;
-
-});
diff --git a/less/pageNav.less b/less/pageNav.less
index 67260e8..d4c719c 100644
--- a/less/pageNav.less
+++ b/less/pageNav.less
@@ -1,10 +1,3 @@
-html {
- // Prevents pagenav tooltip from triggering a horizontal scroll bar
- // Only affects IE11 but applied globally to weed out bugs
- // --------------------------------------------------
- overflow-x: hidden;
-}
-
.pagenav {
&__widget {
position: relative;
@@ -25,49 +18,103 @@ html {
// --------------------------------------------------
// THEME
// --------------------------------------------------
-.pagenav {
- &__btn {
- margin: @item-margin;
+.pagenav__btn {
+ margin: @item-margin;
- &[aria-current="page"] {
- background-color: darken(@btn-color, 20%);
- }
- }
-
- &__btn-icon .icon {
+ &-icon .icon {
display: block;
}
+}
- // buttons with text and icon (left aligned icon as default)
+// Buttons with text and icon
+// --------------------------------------------------
+.pagenav__btn.btn-icon.btn-text {
+
+ // Left aligned icon (icon before the text)
// --------------------------------------------------
- &__btn.btn-icon:not(.icon-is-right).btn-text .icon {
- padding-inline-end: (@icon-padding / 2);
+ &.has-icon-left,
+ .dir-ltr &.has-icon-auto,
+ .dir-rtl &.has-icon-auto[data-type="_next"] {
+ .icon {
+ padding-left: 0;
+ padding-right: (@icon-padding / 2);
+ }
+ }
+ .dir-rtl &.has-icon-left {
+ .icon {
+ padding-right: 0;
+ padding-left: (@icon-padding / 2);
+ }
+ }
+ .dir-rtl &.has-icon-auto[data-type="_next"] {
+ .pagenav__btn-inner {
+ flex-direction: row-reverse;
+ }
}
- // buttons with text and icon (right aligned icon)
+ // Right aligned icon (icon after the text)
// --------------------------------------------------
- &__btn.btn-icon.icon-is-right.btn-text .icon {
- padding-inline-start: (@icon-padding / 2);
+ &.has-icon-right,
+ .dir-rtl &.has-icon-auto,
+ .dir-ltr &.has-icon-auto[data-type="_next"] {
+ .icon {
+ padding-right: 0;
+ padding-left: (@icon-padding / 2);
+ }
+ }
+ .dir-rtl &.has-icon-right {
+ .icon {
+ padding-left: 0;
+ padding-right: (@icon-padding / 2);
+ }
+ }
+ &.has-icon-right,
+ .dir-ltr &.has-icon-auto[data-type="_next"] {
+ .pagenav__btn-inner {
+ flex-direction: row-reverse;
+ }
}
- // consistent with nav icon button styling
+ // Top aligned icon
// --------------------------------------------------
- &__btn.btn-icon:not(.btn-text) {
- padding: @icon-padding;
- background-color: @btn-icon-color;
- color: @btn-icon-color-inverted;
- border-radius: @btn-border-radius;
-
- .no-touch &:not(.is-disabled):not(.is-locked):hover {
- background-color: @btn-icon-color-hover;
- color: @btn-icon-color-inverted-hover;
- .transition(background-color @duration ease-in, color @duration ease-in;);
+ &.has-icon-top {
+ .pagenav__btn-inner {
+ flex-direction: column;
+ }
+ .icon {
+ padding-bottom: (@icon-padding / 4);
}
+ }
- &.is-locked,
- &.is-disabled {
- background-color: @disabled;
- color: @disabled-inverted;
+ // Bottom aligned icon
+ // --------------------------------------------------
+ &.has-icon-bottom {
+ .pagenav__btn-inner {
+ flex-direction: column-reverse;
}
+ .icon {
+ padding-top: (@icon-padding / 4);
+ }
+ }
+}
+
+// Consistent with nav icon button styling
+// --------------------------------------------------
+.pagenav__btn.btn-icon:not(.btn-text) {
+ padding: @icon-padding;
+ background-color: @btn-icon-color;
+ color: @btn-icon-color-inverted;
+ border-radius: @btn-border-radius;
+
+ .no-touch &:not(.is-disabled):not(.is-locked):hover {
+ background-color: @btn-icon-color-hover;
+ color: @btn-icon-color-inverted-hover;
+ .transition(background-color @duration ease-in, color @duration ease-in;);
+ }
+
+ &.is-locked,
+ &.is-disabled {
+ background-color: @disabled;
+ color: @disabled-inverted;
}
}
diff --git a/less/tooltip.less b/less/tooltip.less
deleted file mode 100644
index 83aad9d..0000000
--- a/less/tooltip.less
+++ /dev/null
@@ -1,43 +0,0 @@
-.pagenav {
- &__tooltip {
- position: absolute;
- .transform(translate(-50%, -100%));
- visibility: hidden;
- white-space: nowrap;
- }
-
- &__tooltip.show {
- visibility: visible;
- }
-
- &__triangle {
- position: relative;
- .transform(translateX(-50%));
- width: @item-padding;
- height: @item-padding;
- }
-
- &__triangle:after {
- content: "";
- position: absolute;
- border-width: @item-padding (@item-padding / 2) 0 (@item-padding / 2); /* vary these values to change the angle of the vertex */
- border-style: solid;
- border-color: red transparent transparent transparent;
- }
-}
-
-// --------------------------------------------------
-// THEME
-// --------------------------------------------------
-.pagenav {
- &__tooltip-text {
- padding: @item-padding / 2;
- background-color: @item-color;
- color: @item-color-inverted;
- border-radius: @item-border-radius;
- }
-
- &__triangle:after {
- border-color: @item-color transparent transparent transparent;
- }
-}
diff --git a/package.json b/package.json
index ebd165b..1e1b58f 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,7 @@
"url": "git://github.com/cgkineo/adapt-pageNav.git"
},
"version": "2.4.0",
- "framework": ">=5.2",
+ "framework": ">=5.30.2",
"homepage": "https://github.com/cgkineo/adapt-pageNav",
"issues": "https://github.com/cgkineo/adapt-pageNav/issues/",
"component": "pageNav",
diff --git a/properties.schema b/properties.schema
index 28f886d..70933c1 100644
--- a/properties.schema
+++ b/properties.schema
@@ -57,97 +57,6 @@
"required": true,
"title": "Buttons settings",
"properties": {
- "_returnToPreviousLocation": {
- "type": "object",
- "required": true,
- "legend": "Return to previous location button",
- "properties": {
- "_isEnabled": {
- "type": "boolean",
- "required": true,
- "title": "Show",
- "default": false,
- "inputType": "Checkbox",
- "validators": []
- },
- "_lockUntilPageComplete": {
- "type": "boolean",
- "required": true,
- "title": "Lock until page complete",
- "default": false,
- "inputType": "Checkbox",
- "validators": [],
- "help": "For use when the standard Adapt locking system doesn't apply, such as in a start page before the main menu"
- },
- "_order": {
- "type": "number",
- "required": true,
- "default": 0,
- "title": "Order",
- "inputType": "Number",
- "validators": ["required", "number"],
- "help": "Button display order"
- },
- "_classes": {
- "type": "string",
- "required": false,
- "title": "Classes",
- "default": "",
- "inputType": "Text",
- "validators": []
- },
- "_iconClass": {
- "type": "string",
- "required": false,
- "title": "Icon class",
- "default": "",
- "inputType": "Text",
- "validators": []
- },
- "_alignIconRight": {
- "type": "boolean",
- "required": true,
- "title": "Align icon right",
- "default": false,
- "inputType": "Checkbox",
- "validators": []
- },
- "text": {
- "type": "string",
- "required": true,
- "default": "Return",
- "inputType": "Text",
- "validators": [],
- "translatable": true
- },
- "ariaLabel": {
- "type": "string",
- "required": true,
- "title": "ARIA label",
- "default": "Return to previous location",
- "inputType": "Text",
- "validators": [],
- "translatable": true
- },
- "_showTooltip": {
- "type": "boolean",
- "required": true,
- "title": "Show tool tip",
- "default": false,
- "inputType": "Checkbox",
- "validators": []
- },
- "tooltip": {
- "type": "string",
- "required": false,
- "title": "Tool tip",
- "default": "{{displayTitle}}",
- "inputType": "Text",
- "validators": [],
- "translatable": true
- }
- }
- },
"_previous": {
"type": "object",
"required": true,
@@ -191,17 +100,18 @@
"type": "string",
"required": false,
"title": "Icon class",
- "default": "",
+ "default": "icon-controls-left",
+ "help": "CSS class name to be applied to the button icon. Suggested: icon-controls-left",
"inputType": "Text",
"validators": []
},
- "_alignIconRight": {
- "type": "boolean",
- "required": true,
- "title": "Align icon right",
- "default": false,
- "inputType": "Checkbox",
- "validators": []
+ "_iconAlignment": {
+ "type": "string",
+ "required": false,
+ "default": "auto",
+ "inputType": {"type":"Select", "options":["auto","left","right","top","bottom"]},
+ "title": "Icon alignment",
+ "help": "Determines how the icon is aligned to the text."
},
"text": {
"type": "string",
@@ -220,22 +130,27 @@
"validators": [],
"translatable": true
},
- "_showTooltip": {
- "type": "boolean",
- "required": true,
- "title": "Show tool tip",
- "default": false,
- "inputType": "Checkbox",
- "validators": []
- },
- "tooltip": {
- "type": "string",
- "required": false,
- "title": "Tool tip",
- "default": "{{displayTitle}}",
- "inputType": "Text",
- "validators": [],
- "translatable": true
+ "_navTooltip": {
+ "type": "object",
+ "title": "Navigation tooltip",
+ "properties": {
+ "_isEnabled": {
+ "type": "boolean",
+ "default": true,
+ "title": "Enable tooltip for navigation button",
+ "inputType": "Checkbox",
+ "validators": []
+ },
+ "text": {
+ "type": "string",
+ "title": "",
+ "default": "Home",
+ "help": "The tooltip text to display on hover over this item",
+ "inputType": "Text",
+ "validators": [],
+ "translatable": true
+ }
+ }
},
"_customRouteId": {
"type": "string",
@@ -290,17 +205,18 @@
"type": "string",
"required": false,
"title": "Icon class",
- "default": "",
+ "default": "icon-home",
+ "help": "CSS class name to be applied to the button icon. Suggested: icon-home",
"inputType": "Text",
"validators": []
},
- "_alignIconRight": {
- "type": "boolean",
- "required": true,
- "title": "Align icon right",
- "default": false,
- "inputType": "Checkbox",
- "validators": []
+ "_iconAlignment": {
+ "type": "string",
+ "required": false,
+ "default": "auto",
+ "inputType": {"type":"Select", "options":["auto","left","right","top","bottom"]},
+ "title": "Icon alignment",
+ "help": "Determines how the icon is aligned to the text."
},
"text": {
"type": "string",
@@ -319,22 +235,27 @@
"validators": [],
"translatable": true
},
- "_showTooltip": {
- "type": "boolean",
- "required": true,
- "title": "Show tool tip",
- "default": false,
- "inputType": "Checkbox",
- "validators": []
- },
- "tooltip": {
- "type": "string",
- "required": false,
- "title": "Tool tip",
- "default": "{{displayTitle}}",
- "inputType": "Text",
- "validators": [],
- "translatable": true
+ "_navTooltip": {
+ "type": "object",
+ "title": "Navigation tooltip",
+ "properties": {
+ "_isEnabled": {
+ "type": "boolean",
+ "default": true,
+ "title": "Enable tooltip for navigation button",
+ "inputType": "Checkbox",
+ "validators": []
+ },
+ "text": {
+ "type": "string",
+ "title": "",
+ "default": "Home",
+ "help": "The tooltip text to display on hover over this item",
+ "inputType": "Text",
+ "validators": [],
+ "translatable": true
+ }
+ }
},
"_customRouteId": {
"type": "string",
@@ -389,17 +310,18 @@
"type": "string",
"required": false,
"title": "Icon class",
- "default": "",
+ "default": "icon-controls-up",
+ "help": "CSS class name to be applied to the button icon. Suggested: icon-controls-up",
"inputType": "Text",
"validators": []
},
- "_alignIconRight": {
- "type": "boolean",
- "required": true,
- "title": "Align icon right",
- "default": false,
- "inputType": "Checkbox",
- "validators": []
+ "_iconAlignment": {
+ "type": "string",
+ "required": false,
+ "default": "auto",
+ "inputType": {"type":"Select", "options":["auto","left","right","top","bottom"]},
+ "title": "Icon alignment",
+ "help": "Determines how the icon is aligned to the text."
},
"text": {
"type": "string",
@@ -418,22 +340,27 @@
"validators": [],
"translatable": true
},
- "_showTooltip": {
- "type": "boolean",
- "required": true,
- "title": "Show tool tip",
- "default": false,
- "inputType": "Checkbox",
- "validators": []
- },
- "tooltip": {
- "type": "string",
- "required": false,
- "title": "Tool tip",
- "default": "{{displayTitle}}",
- "inputType": "Text",
- "validators": [],
- "translatable": true
+ "_navTooltip": {
+ "type": "object",
+ "title": "Navigation tooltip",
+ "properties": {
+ "_isEnabled": {
+ "type": "boolean",
+ "default": true,
+ "title": "Enable tooltip for navigation button",
+ "inputType": "Checkbox",
+ "validators": []
+ },
+ "text": {
+ "type": "string",
+ "title": "",
+ "default": "Home",
+ "help": "The tooltip text to display on hover over this item",
+ "inputType": "Text",
+ "validators": [],
+ "translatable": true
+ }
+ }
},
"_customRouteId": {
"type": "string",
@@ -488,121 +415,23 @@
"type": "string",
"required": false,
"title": "Icon class",
- "default": "",
+ "default": "icon-controls-right",
+ "help": "CSS class name to be applied to the button icon. Suggested: icon-controls-right",
"inputType": "Text",
"validators": []
},
- "_alignIconRight": {
- "type": "boolean",
- "required": true,
- "title": "Align icon right",
- "default": true,
- "inputType": "Checkbox",
- "validators": []
- },
- "text": {
- "type": "string",
- "required": true,
- "default": "Next",
- "inputType": "Text",
- "validators": [],
- "translatable": true
- },
- "ariaLabel": {
- "type": "string",
- "required": true,
- "title": "ARIA label",
- "default": "Next Page",
- "inputType": "Text",
- "validators": [],
- "translatable": true
- },
- "_showTooltip": {
- "type": "boolean",
- "required": true,
- "title": "Show tool tip",
- "default": false,
- "inputType": "Checkbox",
- "validators": []
- },
- "tooltip": {
+ "_iconAlignment": {
"type": "string",
"required": false,
- "title": "Tool tip",
- "default": "{{displayTitle}}",
- "inputType": "Text",
- "validators": [],
- "translatable": true
- },
- "_customRouteId": {
- "type": "string",
- "required": true,
- "title": "Override the route id",
- "default": "",
- "inputType": "Text",
- "validators": []
- }
- }
- },
- "_sibling": {
- "type": "object",
- "required": true,
- "legend": "Sibling buttons",
- "properties": {
- "_isEnabled": {
- "type": "boolean",
- "required": true,
- "title": "Show",
- "default": false,
- "inputType": "Checkbox",
- "validators": []
- },
- "_lockUntilPageComplete": {
- "type": "boolean",
- "required": true,
- "title": "Lock until page complete",
- "default": false,
- "inputType": "Checkbox",
- "validators": [],
- "help": "For use when the standard Adapt locking system doesn't apply, such as in a start page before the main menu"
- },
- "_order": {
- "type": "number",
- "required": true,
- "default": 0,
- "title": "Order",
- "inputType": "Number",
- "validators": ["required", "number"],
- "help": "Button display order"
- },
- "_classes": {
- "type": "string",
- "required": false,
- "title": "Classes",
- "default": "",
- "inputType": "Text",
- "validators": []
- },
- "_iconClass": {
- "type": "string",
- "required": false,
- "title": "Icon class",
- "default": "",
- "inputType": "Text",
- "validators": []
- },
- "_alignIconRight": {
- "type": "boolean",
- "required": true,
- "title": "Align icon right",
- "default": false,
- "inputType": "Checkbox",
- "validators": []
+ "default": "auto",
+ "inputType": {"type":"Select", "options":["auto","left","right","top","bottom"]},
+ "title": "Icon alignment",
+ "help": "Determines how the icon is aligned to the text."
},
"text": {
"type": "string",
"required": true,
- "default": "{{inc index}}",
+ "default": "Next",
"inputType": "Text",
"validators": [],
"translatable": true
@@ -611,27 +440,32 @@
"type": "string",
"required": true,
"title": "ARIA label",
- "default": "Page {{inc index}}",
+ "default": "Next Page",
"inputType": "Text",
"validators": [],
"translatable": true
},
- "_showTooltip": {
- "type": "boolean",
- "required": true,
- "title": "Show tool tip",
- "default": false,
- "inputType": "Checkbox",
- "validators": []
- },
- "tooltip": {
- "type": "string",
- "required": false,
- "title": "Tool tip",
- "default": "{{displayTitle}}",
- "inputType": "Text",
- "validators": [],
- "translatable": true
+ "_navTooltip": {
+ "type": "object",
+ "title": "Navigation tooltip",
+ "properties": {
+ "_isEnabled": {
+ "type": "boolean",
+ "default": true,
+ "title": "Enable tooltip for navigation button",
+ "inputType": "Checkbox",
+ "validators": []
+ },
+ "text": {
+ "type": "string",
+ "title": "",
+ "default": "Home",
+ "help": "The tooltip text to display on hover over this item",
+ "inputType": "Text",
+ "validators": [],
+ "translatable": true
+ }
+ }
},
"_customRouteId": {
"type": "string",
@@ -686,17 +520,18 @@
"type": "string",
"required": false,
"title": "Icon class",
- "default": "",
+ "default": "icon-cross",
+ "help": "CSS class name to be applied to the button icon. Suggested: icon-cross",
"inputType": "Text",
"validators": []
},
- "_alignIconRight": {
- "type": "boolean",
- "required": true,
- "title": "Align icon right",
- "default": false,
- "inputType": "Checkbox",
- "validators": []
+ "_iconAlignment": {
+ "type": "string",
+ "required": false,
+ "default": "auto",
+ "inputType": {"type":"Select", "options":["auto","left","right","top","bottom"]},
+ "title": "Icon alignment",
+ "help": "Determines how the icon is aligned to the text."
},
"text": {
"type": "string",
@@ -715,22 +550,27 @@
"validators": [],
"translatable": true
},
- "_showTooltip": {
- "type": "boolean",
- "required": true,
- "title": "Show tool tip",
- "default": false,
- "inputType": "Checkbox",
- "validators": []
- },
- "tooltip": {
- "type": "string",
- "required": false,
- "title": "Tool tip",
- "default": "Close window",
- "inputType": "Text",
- "validators": [],
- "translatable": true
+ "_navTooltip": {
+ "type": "object",
+ "title": "Navigation tooltip",
+ "properties": {
+ "_isEnabled": {
+ "type": "boolean",
+ "default": true,
+ "title": "Enable tooltip for navigation button",
+ "inputType": "Checkbox",
+ "validators": []
+ },
+ "text": {
+ "type": "string",
+ "title": "",
+ "default": "Home",
+ "help": "The tooltip text to display on hover over this item",
+ "inputType": "Text",
+ "validators": [],
+ "translatable": true
+ }
+ }
}
}
}
diff --git a/schema/component.schema.json b/schema/component.schema.json
index 28d7d04..e7df35d 100644
--- a/schema/component.schema.json
+++ b/schema/component.schema.json
@@ -49,86 +49,13 @@
"type": "object",
"title": "Buttons settings",
"required": [
- "_returnToPreviousLocation",
"_previous",
"_root",
"_up",
"_next",
- "_sibling",
"_close"
],
"properties": {
- "_returnToPreviousLocation": {
- "type": "object",
- "title": "Return to previous location button",
- "properties": {
- "_isEnabled": {
- "type": "boolean",
- "title": "Show",
- "default": false
- },
- "_lockUntilPageComplete": {
- "type": "boolean",
- "title": "Lock until page complete",
- "description": "For use when the standard Adapt locking system doesn't apply, such as in a start page before the main menu",
- "default": false
- },
- "_order": {
- "type": "number",
- "title": "Order",
- "description": "Button display order",
- "default": 0
- },
- "_classes": {
- "type": "string",
- "title": "Classes",
- "default": ""
- },
- "_iconClass": {
- "type": "string",
- "title": "Icon class",
- "description": "CSS class name to be applied to the button icon. Suggested: icon-controls-left",
- "default": ""
- },
- "_alignIconRight": {
- "type": "boolean",
- "title": "Align icon right",
- "description": "Defines whether the icon is aligned to the left or right of the text.",
- "default": false
- },
- "text": {
- "type": "string",
- "title": "Button text",
- "description": "Text that appears on the button. Optional since you can only use an icon.",
- "default": "Return",
- "_adapt": {
- "translatable": true
- }
- },
- "ariaLabel": {
- "type": "string",
- "title": "ARIA label",
- "default": "Return to previous location",
- "_adapt": {
- "translatable": true
- }
- },
- "_showTooltip": {
- "type": "boolean",
- "title": "Show tool tip",
- "description": "Defines whether the tooltip renders on hover.",
- "default": false
- },
- "tooltip": {
- "type": "string",
- "title": "Tool tip",
- "default": "{{displayTitle}}",
- "_adapt": {
- "translatable": true
- }
- }
- }
- },
"_previous": {
"type": "object",
"title": "Previous button",
@@ -159,13 +86,21 @@
"type": "string",
"title": "Icon class",
"description": "CSS class name to be applied to the button icon. Suggested: icon-controls-left",
- "default": ""
- },
- "_alignIconRight": {
- "type": "boolean",
- "title": "Align icon right",
- "description": "Defines whether the icon is aligned to the left or right of the text.",
- "default": false
+ "default": "icon-controls-left"
+ },
+ "_iconAlignment": {
+ "type": "string",
+ "title": "Icon alignment",
+ "description": "Determines how the icon is aligned to the text.",
+ "default": "auto",
+ "enum": [
+ "auto",
+ "left",
+ "right",
+ "top",
+ "bottom"
+ ],
+ "_backboneForms": "Select"
},
"text": {
"type": "string",
@@ -184,18 +119,24 @@
"translatable": true
}
},
- "_showTooltip": {
- "type": "boolean",
- "title": "Show tool tip",
- "description": "Defines whether the tooltip renders on hover.",
- "default": false
- },
- "tooltip": {
- "type": "string",
- "title": "Tool tip",
- "default": "{{displayTitle}}",
- "_adapt": {
- "translatable": true
+ "_navTooltip": {
+ "type": "object",
+ "title": "Button tooltip",
+ "default": {},
+ "properties": {
+ "_isEnabled": {
+ "type": "boolean",
+ "title": "Enable tooltip for this button",
+ "default": true
+ },
+ "text": {
+ "type": "string",
+ "title": "",
+ "default": "Home",
+ "_adapt": {
+ "translatable": true
+ }
+ }
}
},
"_customRouteId": {
@@ -237,13 +178,21 @@
"type": "string",
"title": "Icon class",
"description": "CSS class name to be applied to the button icon. Suggested: icon-home",
- "default": ""
- },
- "_alignIconRight": {
- "type": "boolean",
- "title": "Align icon right",
- "description": "Defines whether the icon is aligned to the left or right of the text.",
- "default": false
+ "default": "icon-home"
+ },
+ "_iconAlignment": {
+ "type": "string",
+ "title": "Icon alignment",
+ "description": "Determines how the icon is aligned to the text.",
+ "default": "auto",
+ "enum": [
+ "auto",
+ "left",
+ "right",
+ "top",
+ "bottom"
+ ],
+ "_backboneForms": "Select"
},
"text": {
"type": "string",
@@ -262,18 +211,24 @@
"translatable": true
}
},
- "_showTooltip": {
- "type": "boolean",
- "title": "Show tool tip",
- "description": "Defines whether the tooltip renders on hover.",
- "default": false
- },
- "tooltip": {
- "type": "string",
- "title": "Tool tip",
- "default": "{{displayTitle}}",
- "_adapt": {
- "translatable": true
+ "_navTooltip": {
+ "type": "object",
+ "title": "Button tooltip",
+ "default": {},
+ "properties": {
+ "_isEnabled": {
+ "type": "boolean",
+ "title": "Enable tooltip for this button",
+ "default": true
+ },
+ "text": {
+ "type": "string",
+ "title": "",
+ "default": "Home",
+ "_adapt": {
+ "translatable": true
+ }
+ }
}
},
"_customRouteId": {
@@ -315,13 +270,21 @@
"type": "string",
"title": "Icon class",
"description": "CSS class name to be applied to the button icon. Suggested: icon-controls-up",
- "default": ""
- },
- "_alignIconRight": {
- "type": "boolean",
- "title": "Align icon right",
- "description": "Defines whether the icon is aligned to the left or right of the text.",
- "default": false
+ "default": "icon-controls-up"
+ },
+ "_iconAlignment": {
+ "type": "string",
+ "title": "Icon alignment",
+ "description": "Determines how the icon is aligned to the text.",
+ "default": "auto",
+ "enum": [
+ "auto",
+ "left",
+ "right",
+ "top",
+ "bottom"
+ ],
+ "_backboneForms": "Select"
},
"text": {
"type": "string",
@@ -340,18 +303,24 @@
"translatable": true
}
},
- "_showTooltip": {
- "type": "boolean",
- "title": "Show tool tip",
- "description": "Defines whether the tooltip renders on hover.",
- "default": false
- },
- "tooltip": {
- "type": "string",
- "title": "Tool tip",
- "default": "{{displayTitle}}",
- "_adapt": {
- "translatable": true
+ "_navTooltip": {
+ "type": "object",
+ "title": "Button tooltip",
+ "default": {},
+ "properties": {
+ "_isEnabled": {
+ "type": "boolean",
+ "title": "Enable tooltip for this button",
+ "default": true
+ },
+ "text": {
+ "type": "string",
+ "title": "",
+ "default": "Home",
+ "_adapt": {
+ "translatable": true
+ }
+ }
}
},
"_customRouteId": {
@@ -392,13 +361,21 @@
"type": "string",
"title": "Icon class",
"description": "CSS class name to be applied to the button icon. Suggested: icon-controls-right",
- "default": ""
- },
- "_alignIconRight": {
- "type": "boolean",
- "title": "Align icon right",
- "description": "Defines whether the icon is aligned to the left or right of the text.",
- "default": true
+ "default": "icon-controls-right"
+ },
+ "_iconAlignment": {
+ "type": "string",
+ "title": "Icon alignment",
+ "description": "Determines how the icon is aligned to the text.",
+ "default": "auto",
+ "enum": [
+ "auto",
+ "left",
+ "right",
+ "top",
+ "bottom"
+ ],
+ "_backboneForms": "Select"
},
"text": {
"type": "string",
@@ -417,96 +394,24 @@
"translatable": true
}
},
- "_showTooltip": {
- "type": "boolean",
- "title": "Show tool tip",
- "description": "Defines whether the tooltip renders on hover.",
- "default": false
- },
- "tooltip": {
- "type": "string",
- "title": "Tool tip",
- "default": "{{displayTitle}}",
- "_adapt": {
- "translatable": true
- }
- },
- "_customRouteId": {
- "type": "string",
- "title": "Override the route id",
- "description": "Enter the Friendly id of the page that the button should direct the user to. For use when non-standard navigation is required.",
- "default": ""
- }
- }
- },
- "_sibling": {
- "type": "object",
- "title": "Sibling buttons",
- "description": "Numbered buttons representing each sibling page",
- "properties": {
- "_isEnabled": {
- "type": "boolean",
- "title": "Show",
- "default": false
- },
- "_lockUntilPageComplete": {
- "type": "boolean",
- "title": "Lock until page complete",
- "description": "For use when the standard Adapt locking system doesn't apply, such as in a start page before the main menu",
- "default": false
- },
- "_order": {
- "type": "number",
- "title": "Order",
- "description": "Button display order",
- "default": 0
- },
- "_classes": {
- "type": "string",
- "title": "Classes",
- "default": ""
- },
- "_iconClass": {
- "type": "string",
- "title": "Icon class",
- "description": "CSS class name to be applied to the button icon. No icon is recommended.",
- "default": ""
- },
- "_alignIconRight": {
- "type": "boolean",
- "title": "Align icon right",
- "description": "Defines whether the icon is aligned to the left or right of the text.",
- "default": false
- },
- "text": {
- "type": "string",
- "title": "Button text",
- "description": "Text that appears on the button. Suggest using the default.",
- "default": "{{inc index}}",
- "_adapt": {
- "translatable": true
- }
- },
- "ariaLabel": {
- "type": "string",
- "title": "ARIA label",
- "default": "Page {{inc index}}",
- "_adapt": {
- "translatable": true
- }
- },
- "_showTooltip": {
- "type": "boolean",
- "title": "Show tool tip",
- "description": "Defines whether the tooltip renders on hover.",
- "default": false
- },
- "tooltip": {
- "type": "string",
- "title": "Tool tip",
- "default": "{{displayTitle}}",
- "_adapt": {
- "translatable": true
+ "_navTooltip": {
+ "type": "object",
+ "title": "Button tooltip",
+ "default": {},
+ "properties": {
+ "_isEnabled": {
+ "type": "boolean",
+ "title": "Enable tooltip for this button",
+ "default": true
+ },
+ "text": {
+ "type": "string",
+ "title": "",
+ "default": "Home",
+ "_adapt": {
+ "translatable": true
+ }
+ }
}
},
"_customRouteId": {
@@ -548,13 +453,21 @@
"type": "string",
"title": "Icon class",
"description": "CSS class name to be applied to the button icon. Suggested: icon-cross",
- "default": ""
- },
- "_alignIconRight": {
- "type": "boolean",
- "title": "Align icon right",
- "description": "Defines whether the icon is aligned to the left or right of the text.",
- "default": false
+ "default": "icon-cross"
+ },
+ "_iconAlignment": {
+ "type": "string",
+ "title": "Icon alignment",
+ "description": "Determines how the icon is aligned to the text.",
+ "default": "auto",
+ "enum": [
+ "auto",
+ "left",
+ "right",
+ "top",
+ "bottom"
+ ],
+ "_backboneForms": "Select"
},
"text": {
"type": "string",
@@ -573,18 +486,24 @@
"translatable": true
}
},
- "_showTooltip": {
- "type": "boolean",
- "title": "Show tool tip",
- "description": "Defines whether the tooltip renders on hover.",
- "default": false
- },
- "tooltip": {
- "type": "string",
- "title": "Tool tip",
- "default": "Close window",
- "_adapt": {
- "translatable": true
+ "_navTooltip": {
+ "type": "object",
+ "title": "Button tooltip",
+ "default": {},
+ "properties": {
+ "_isEnabled": {
+ "type": "boolean",
+ "title": "Enable tooltip for this button",
+ "default": true
+ },
+ "text": {
+ "type": "string",
+ "title": "",
+ "default": "Home",
+ "_adapt": {
+ "translatable": true
+ }
+ }
}
}
}
diff --git a/templates/pageNav-tooltip.hbs b/templates/pageNav-tooltip.hbs
deleted file mode 100644
index 8f9bedc..0000000
--- a/templates/pageNav-tooltip.hbs
+++ /dev/null
@@ -1,7 +0,0 @@
-