/*!
* UI development toolkit for HTML5 (OpenUI5)
* (c) Copyright 2009-2018 SAP SE or an SAP affiliate company.
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
*/
// Provides control sap.m.ColorPalette
sap.ui.define([
'sap/ui/core/Control',
'sap/ui/Device',
'sap/ui/base/DataType',
'sap/ui/core/library',
'sap/ui/core/delegate/ItemNavigation',
'./Button',
'./Dialog',
'./library',
'./ColorPaletteRenderer',
"sap/ui/dom/containsOrEquals",
"sap/ui/events/KeyCodes",
"sap/ui/thirdparty/jquery"
], function(
Control,
Device,
DataType,
coreLibrary,
ItemNavigation,
Button,
Dialog,
library,
ColorPaletteRenderer,
containsOrEquals,
KeyCodes,
jQuery
) {
"use strict";
// shortcut to CSSColor of the core library
var CSSColor = coreLibrary.CSSColor;
// shortcut to ColorPicker (lazy initialized)
var ColorPicker;
// shortcut to ColorPickerMode (lazy initialized)
var ColorPickerMode;
// shortcut to the ButtonType enumeration
var ButtonType = library.ButtonType;
// reference to the boolean data type in the core
var BooleanType = DataType.getType("boolean");
// The name of the class, corresponding to a single color item
var CSS_CLASS_SWATCH = "sapMColorPaletteSquare";
// Defines the exact count of swatches per row
var SWATCHES_PER_ROW = 5;
// Min amount of swatches when app.developer sets colors
var MIN_COLORS = 2;
// Max amount of swatches when app.developer sets colors
var MAX_COLORS = 15;
// get resource translation bundle;
var oLibraryResourceBundle = sap.ui.getCore().getLibraryResourceBundle("sap.m");
/**
* Constructor for a new ColorPalette
.
*
* @param {string} [sId] ID for the new control, generated automatically if no ID is given
* @param {object} [mSettings] Initial settings for the new control
*
* @class
* Represents a predefined range of colors for easier selection.
*
*
ColorPalette
provides the users with a range of predefined colors.
*
* You can customize them with the use of the colors
property.
* You can specify a defaultColor
and display a "Default color" button
* for the user to choose directly. You can display a "More colors..." button
* that opens an additional color picker for the user to choose specific colors
* that are not present in the predefined range.
*
* sap.m.ColorPalettePopover).
* @see {@link sap.m.ColorPalettePopover}
*
* Note: The {@link sap.ui.unified.ColorPicker} is used internally only if the ColorPicker
* is opened (not used for the initial rendering). If the sap.ui.unified
library is not loaded
* before the ColorPicker
is opened, it will be loaded upon opening. This could lead to a waiting
* time when the ColorPicker
is opened for the first time. To prevent this, apps using the
* ColorPalette
should also load the sap.ui.unified
library.
*
* @extends sap.ui.core.Control
* @version 1.60.23
*
* @constructor
* @public
* @since 1.54
* @alias sap.m.ColorPalette
* @ui5-metamodel This control/element also will be described in the UI5 (legacy) designtime metamodel
*/
var ColorPalette = Control.extend("sap.m.ColorPalette", /** @lends sap.m.ColorPalette.prototype */ {
metadata: {
library: "sap.m",
properties: {
/**
* Defines the List of colors displayed in the palette. Minimum is 2 colors, maximum is 15 colors.
*/
colors: {
type: "sap.ui.core.CSSColor[]", group: "Appearance",
defaultValue: [
"gold",
"darkorange",
"indianred",
"darkmagenta",
"cornflowerblue",
"deepskyblue",
"darkcyan",
"olivedrab",
"darkslategray",
"azure",
"white",
"lightgray",
"darkgray",
"dimgray",
"black"
]
}
},
aggregations: {
/* Reference to an optional button for activating default color. For private use. */
_defaultColorButton: {type: "sap.m.Button", multiple: false, visibility: "hidden"},
/* Reference to an optional button for activating more color selection. For private use. */
_moreColorsButton: {type: "sap.m.Button", multiple: false, visibility: "hidden"}
},
events: {
/**
* Fired when the user selects a color.
*/
colorSelect: {
parameters: {
/**
* The color that is returned when user chooses the "Default color" button.
*/
"value": {type: "sap.ui.core.CSSColor"},
/**
* Denotes if the color has been chosen by selecting the "Default Color" button (true or false)
*/
"defaultAction": {type: "boolean"}
}
}
}
}
});
ColorPalette.prototype.init = function () {
// The default color. Private API. Allowed consumer is ColorPaletteAPI.
this._oDefaultColor = null;
// If the "Default color" button should be shown. Private API. Allowed consumer is ColorPaletteAPI.
this._bShowDefaultColorButton = false;
// If the "More colors" button should be shown. Private API. Allowed consumer is ColorPaletteAPI.
this._bShowMoreColorsButton = false;
// Reference to the dialog containing the internal "Color Picker". For private use.
this._oMoreColorsDialog = null;
// Reference to the item navigation
this._oItemNavigation = null;
};
ColorPalette.prototype.exit = function () {
if (this._oMoreColorsDialog) {
this._oMoreColorsDialog.destroy();
delete this._oMoreColorsDialog;
}
if (this._oItemNavigation) {
this.removeDelegate(this._oItemNavigation);
this._oItemNavigation.destroy();
delete this._oItemNavigation;
}
};
ColorPalette.prototype.setColors = function (aColors) {
aColors = this.validateProperty("colors", aColors);
if (aColors.length < MIN_COLORS || aColors.length > MAX_COLORS) {
throw new Error("Cannot set property 'colors' - array must has minimum 2 and maximum 15 elements");
}
return this.setProperty("colors", aColors);
};
ColorPalette.prototype.ontap = function (oEvent) {
var $Target = jQuery(oEvent.target),
sColor,
$Swatch;
$Swatch = $Target.closest("." + CSS_CLASS_SWATCH);
if (!$Swatch.length) {
return;
}
sColor = $Swatch.attr("data-sap-ui-color");
this._fireColorSelect(sColor, false, oEvent);
};
ColorPalette.prototype.onsaptabnext = ColorPalette.prototype.onsaptabprevious = function (oEvent) {
var oElementInfo = this._getElementInfo(oEvent.target);
if (oElementInfo.bIsMoreColorsButton) {
this.fireEvent("_colorNotSelected", {_originalEvent: oEvent});
return;
}
if (oElementInfo.bIsDefaultColorButton) {
this._fireColorSelect(this._getDefaultColor(), true, oEvent);
return;
}
ColorPalette.prototype.ontap.apply(this, arguments);
};
ColorPalette.prototype.onsapenter = ColorPalette.prototype.ontap;
ColorPalette.prototype.onkeyup = function (oEvent) {
if (oEvent.which === KeyCodes.SPACE) {
oEvent.preventDefault();
ColorPalette.prototype.ontap.apply(this, arguments);
}
};
ColorPalette.prototype.onsaphome = ColorPalette.prototype.onsapend = function(oEvent) {
// Home and End keys on ColorPalette buttons should do nothing. If event occurs on the swatch, see ItemNavigationHomeEnd).
var oElemInfo = this._getElementInfo(oEvent.target);
if (oElemInfo.bIsDefaultColorButton || oElemInfo.bIsMoreColorsButton) {
oEvent.preventDefault();
oEvent.stopImmediatePropagation(true); // does not allow the ItemNavigationHomeEnd delegate to receive it
}
};
ColorPalette.prototype.onAfterRendering = function () {
this._ensureItemNavigation();
};
// Private methods -------------------------------------------------------------------------------------------
ColorPalette.prototype._createDefaultColorButton = function () {
return new Button(this.getId() + "-btnDefaultColor", {
width: "100%",
type: ButtonType.Transparent,
text: oLibraryResourceBundle.getText("COLOR_PALETTE_DEFAULT_COLOR"),
visible: this._getShowDefaultColorButton(),
press: function (oEvent) {
this._fireColorSelect(this._getDefaultColor(), true, oEvent);
}.bind(this)
});
};
// Default color
ColorPalette.prototype._getDefaultColor = function () {
return this._oDefaultColor;
};
/**
* Sets a default color.
* @param {sap.ui.core.CSSColor} color the color
* @private
* @return {sap.m.ColorPalette} this
for method chaining
*/
ColorPalette.prototype._setDefaultColor = function (color) {
if (!CSSColor.isValid(color)) {
throw new Error("Cannot set internal property '_defaultColor' - invalid value: " + color);
}
this._oDefaultColor = color;
return this;
};
ColorPalette.prototype._getShowDefaultColorButton = function () {
return this._bShowDefaultColorButton;
};
ColorPalette.prototype._setShowDefaultColorButton = function (bValue) {
if (!BooleanType.isValid(bValue)) {
throw new Error("Cannot set internal property 'showDefaultColorButton' - invalid value: " + bValue);
}
this._bShowDefaultColorButton = bValue;
//lazy loading check
if (bValue && !this._getDefaultColorButton()) {
this.setAggregation("_defaultColorButton", this._createDefaultColorButton());
}
if (this._getDefaultColorButton()) { /* still button may not be there */
this._getDefaultColorButton().setVisible(bValue);
}
return this;
};
ColorPalette.prototype._getDefaultColorButton = function () {
return this.getAggregation("_defaultColorButton");
};
// More Colors...
ColorPalette.prototype._createMoreColorsButton = function () {
return new Button(this.getId() + "-btnMoreColors", {
width: "100%",
type: ButtonType.Transparent,
text: oLibraryResourceBundle.getText("COLOR_PALETTE_MORE_COLORS"),
visible: this._getShowMoreColorsButton(),
press: this._openColorPicker.bind(this)
});
};
ColorPalette.prototype._getShowMoreColorsButton = function () {
return this._bShowMoreColorsButton;
};
ColorPalette.prototype._setShowMoreColorsButton = function (bValue) {
if (!BooleanType.isValid(bValue)) {
throw new Error("Cannot set internal property 'showMoreColorsButton' - invalid value: " + bValue);
}
this._bShowMoreColorsButton = bValue;
//lazy loading check
if (bValue && !this._getMoreColorsButton()) {
this.setAggregation("_moreColorsButton", this._createMoreColorsButton());
}
if (this._getMoreColorsButton()) { /* still button may not be there */
this._getMoreColorsButton().setVisible(bValue);
}
return this;
};
ColorPalette.prototype._getMoreColorsButton = function () {
return this.getAggregation("_moreColorsButton");
};
/**
* Opens a color picker in a Dialog.
* The function assumes that there is a "more colors.." button visible.
* @return void
* @private
*/
ColorPalette.prototype._openColorPicker = function () {
this.fireEvent("_beforeOpenColorPicker"); //hook for program consumers (i.e. ColorPalettePopover)
this._ensureMoreColorsDialog().open();
};
/**
* Ensure a dialog wrapping the ColorPicker exists (creates new if is not created yet).
* @return {sap.m.Dialog} the dialog.
* @private
*/
ColorPalette.prototype._ensureMoreColorsDialog = function () {
if (!this._oMoreColorsDialog) {
this._oMoreColorsDialog = this._createMoreColorsDialog();
}
return this._oMoreColorsDialog;
};
/**
* Creates a dialog that wraps the ColorPicker
* @return {sap.m.Dialog} the dialog containing the ColorPicker
* @private
*/
ColorPalette.prototype._createMoreColorsDialog = function () {
var oDialog = new Dialog(this.getId() + "-moreColorsDialog", {
stretch: !!Device.system.phone,
title: oLibraryResourceBundle.getText("COLOR_PALETTE_MORE_COLORS_TITLE")
}).addStyleClass("CPDialog");
this._ensureUnifiedLibrary();
// keep explicit reference to the picker attached to the parent dialog
oDialog.addContent(oDialog._oColorPicker = new ColorPicker({
mode: ColorPickerMode.HSL
}));
// OK button
oDialog.setBeginButton(new Button({
text: oLibraryResourceBundle.getText("COLOR_PALETTE_MORE_COLORS_CONFIRM"),
press: function (oEvent) {
oDialog.close();
if (oDialog._oColorPicker.getColorString()) {
this._fireColorSelect(oDialog._oColorPicker.getColorString(), false, oEvent);
}
}.bind(this)
}));
// Cancel button
oDialog.setEndButton(new Button({
text: oLibraryResourceBundle.getText("COLOR_PALETTE_MORE_COLORS_CANCEL"),
press: function () {
oDialog.close();
}
}));
return oDialog;
};
// Other
// Ensure that the sap.ui.unified library and sap.ui.unified.ColorPicker are both loaded
ColorPalette.prototype._ensureUnifiedLibrary = function () {
var oUnifiedLib;
if (!ColorPicker) {
sap.ui.getCore().loadLibrary("sap.ui.unified");
oUnifiedLib = sap.ui.require("sap/ui/unified/library");
ColorPicker = sap.ui.requireSync("sap/ui/unified/ColorPicker");
ColorPickerMode = oUnifiedLib.ColorPickerMode;
}
};
/**
* Focuses the first available element in the palette.
* @private
*/
ColorPalette.prototype._focusFirstElement = function () {
var oFirstSwatchElement = this._getShowDefaultColorButton() ? this._getDefaultColorButton().getDomRef() : this._getAllSwatches()[0];
oFirstSwatchElement.focus();
};
/**
* Helper function to fire the event "colorSelect"
* @param {sap.ui.core.CSSColor} color the color
* @param {boolean} [defaultAction=false] if the selection is performed via "Default color" button
* @param {jQuery.Event} oOriginalEvent original event
* @private
*/
ColorPalette.prototype._fireColorSelect = function (color, defaultAction, oOriginalEvent) {
this.fireColorSelect({value: color, defaultAction: defaultAction, _originalEvent: oOriginalEvent});
};
/**
* Handles creation or update of the ItemNavigation.
* @private
*/
ColorPalette.prototype._ensureItemNavigation = function () {
var aDomRefs = [];
if (!this._oItemNavigation) {
this._oItemNavigation = new ItemNavigationHomeEnd(this);
this._oItemNavigation.setColumns(SWATCHES_PER_ROW);
this._oItemNavigation.setCycling(false);
this.addDelegate(this._oItemNavigation);
this._oItemNavigation.attachEvent(ItemNavigation.Events.BorderReached, this._onSwatchContainerBorderReached, this);
}
// all currently available swatches
aDomRefs = aDomRefs.concat(this._getAllSwatches());
this._oItemNavigation.setRootDomRef(this.getDomRef("swatchCont"));
this._oItemNavigation.setItemDomRefs(aDomRefs);
};
/**
* Handles navigation from within the swatch container to the outside where the end-user navigates through the
* swatch container and reaches its border (ItemNavigationHomeEnd.BorderReachedDirectionBackward
or
* ItemNavigationHomeEnd.BorderReachedDirectionForward
).
*
* The buttons Default Color and More colors are handled as color palette items, these are also part of the
* arrow key navigation.
*
* If the user is on the last swatch item and presses [Down] or [Right] keyboard key
* (ItemNavigationHomeEnd.BorderReachedDirectionForward
), the focus should go into one of the
* following elements (in the provided order):
*
* - More Colors button if such is available. If not, the focus should go to
* - Default color button if such is available. If not, the focus should go to
* - The first swatch item in the swatch container (there is always such)
*
*
* If the user is on the first swatch item inside the swatch container and presses [Up] or [Down] keyboard keys
* (ItemNavigationHomeEnd.BorderReachedDirectionBackward
) the focus should go into one of the
* following elements (in the provided order):
*
* - Default color button if such is available. If not, the focus should go to
* - More Colors button if such is available. If not, the focus should go to
* - The first swatch item in the last row of the swatch container (there is always such)
*
*
* @param {jQuery.Event} oEvent the keyboard event
* @return {Element|sap.m.Button} the element that the focus has been moved on.
* @private
*/
ColorPalette.prototype._onSwatchContainerBorderReached = function(oEvent) {
var vNextElement,
aSwatches,
bHomeOrEnd = ["saphome","sapend"].indexOf(oEvent.getParameter("event").type) > -1;
if (oEvent.getParameter(ItemNavigationHomeEnd.BorderReachedDirection) === ItemNavigationHomeEnd.BorderReachedDirectionForward) {
if (this._getShowMoreColorsButton()) {
vNextElement = this._getMoreColorsButton();
} else if (!bHomeOrEnd && this._getShowDefaultColorButton()) {// Default Color, but excluding "home" and "end"
vNextElement = this._getDefaultColorButton();
} else if (!bHomeOrEnd) { // swatch, but not due to "home" and "end" keys
vNextElement = this._getAllSwatches()[0];
}
} else { // Backward
if (this._getShowDefaultColorButton()) {
vNextElement = this._getDefaultColorButton();
} else if (!bHomeOrEnd && this._getShowMoreColorsButton()) {// More Colors, but excluding "home" and "end"
vNextElement = this._getMoreColorsButton();
} else if (!bHomeOrEnd) { // swatch, but not due to "home" and "end" keys
aSwatches = this._getAllSwatches();
vNextElement = aSwatches[this._oItemNavigation._getIndexOfTheFirstItemInLastRow()];
}
}
if (vNextElement) {
vNextElement.focus();
}
return vNextElement;
};
/**
* Handles forward navigation when the user is either on Default Color or More Colors buttons.
*
* If the user is on Default Color, focus should go to the first item in the swatch container.
* If the user is on More Colors, focus should go on the Default Color button if such exists, otherwise on the
* the first item in the swatch container.
*
* @param {jQuery.Event} oEvent the keyboard event
*/
ColorPalette.prototype.onsapnext = function (oEvent) {
var vNextElement,
oElementInfo = this._getElementInfo(oEvent.target);
if (!(oElementInfo.bIsDefaultColorButton || oElementInfo.bIsMoreColorsButton)) {
return;
}
oEvent.preventDefault();
oEvent.stopImmediatePropagation(true); //also prevents ItemNavigation handler
if (oElementInfo.bIsDefaultColorButton) {
vNextElement = this._getAllSwatches()[0];
} else { // More Colors...
vNextElement = this._getShowDefaultColorButton() ? this._getDefaultColorButton() : this._getAllSwatches()[0];
}
vNextElement.focus();
};
/**
* Handles backward navigation when user is either on Default Color or More Colors buttons.
*
* If the user is on Default Color, focus should go to the More Colors button if such exists, otherwise,
* on the first item in the last row of the swatch container.
* If user is on More Colors, focus should go on:
* - the first item in the last row of the swatch container if sapprevious
is fired due to
* [Up] key, otherwise
* - the last item in the swatch container (the possible keycodes is: [Left] (in ltr) or [Right] (rtl).
*
* @param {jQuery.Event} oEvent the keyboard event
*/
ColorPalette.prototype.onsapprevious = function (oEvent) {
var vNextElement,
oFocusInfo = this._getElementInfo(oEvent.target),
aAllSwatches;
if (!(oFocusInfo.bIsDefaultColorButton || oFocusInfo.bIsMoreColorsButton)) {
return;
}
oEvent.preventDefault();
oEvent.stopImmediatePropagation(true);//also prevents ItemNavigation handler
aAllSwatches = this._getAllSwatches();
if (oFocusInfo.bIsMoreColorsButton) {
vNextElement = oEvent.keyCode === KeyCodes.ARROW_UP ?
aAllSwatches[this._oItemNavigation._getIndexOfTheFirstItemInLastRow()] : aAllSwatches[aAllSwatches.length - 1];
} else { // Default Color Button
vNextElement = this._getShowMoreColorsButton() ? this._getMoreColorsButton() :
aAllSwatches[this._oItemNavigation._getIndexOfTheFirstItemInLastRow()];
}
vNextElement.focus();
};
// DOM related private helpers
/**
* Returns all swatches/squares
* @return {Element[]} returns all swatch container items in an array of DOM elements.
* @private
*/
ColorPalette.prototype._getAllSwatches = function () {
return this.$().find("." + CSS_CLASS_SWATCH).get();
};
/**
* Analyzes if given DOM element is one of the ColorPalette
artifacts (Default Color, More Colors,
* swatch color).
* @param {Element} oElement DOM Element
* @return {{bIsDefaultColorButton: *, bIsMoreColorsButton: boolean|*, bIsASwatch: boolean|*}} result
* @private
*/
ColorPalette.prototype._getElementInfo = function (oElement) {
var bIsDefaultColorButton = this._getShowDefaultColorButton() && containsOrEquals(oElement,
this._getDefaultColorButton().getDomRef()),
bIsMoreColorsButton = !bIsDefaultColorButton && this._getShowMoreColorsButton() && containsOrEquals(oElement,
this._getMoreColorsButton().getDomRef()),
bIsASwatch = !bIsMoreColorsButton && !bIsDefaultColorButton && jQuery(oElement).hasClass(CSS_CLASS_SWATCH);
return {
bIsDefaultColorButton: bIsDefaultColorButton,
bIsMoreColorsButton: bIsMoreColorsButton,
bIsASwatch: bIsASwatch
};
};
/**
* Extension of sap.ui.core.delegate.ItemNavigation
to support custom keyboard handling for:
* - [Home] (overrides onsaphome
,
* - [End] (overrides onsapend
),
* - [Up] (overrides onsapprevious
),
* - [Down] (overrides onsapnext
).
*
* When using [Up] or [Down] keys, the focus moves up one row or down one row.
* If the next row has less items than the currently focused row, and the focus is above whitespace, the use of
* the [Down] arrow key moves the focus to the last item of the next row (-> also changes column). When using [Up] now,
* the focus moves one row up, onto the same column.
*
* ItemNavigation
's event BorderReached
is enhanced. It used to be fired by [Right]
* (respectively [Left]) key on the last (respectively the first) item. Now, the same event is fired also when
* [Down] (respectively [Up]) key is used.
*
* If the [Home] key is pressed, it moves the focus according to the following order:
* - to the first item in the current row. If already on it
* - to the first item in the whole container. If already on it
* - fires a BorderReached
event
*
* Respectively, if the [End] key is pressed, it moves the focus according to the following order:
* - to the last item in the current row. If already on it
* - to the last item in the whole container. If already on it
* - fires a BorderReached
event
*
* @private
*/
var ItemNavigationHomeEnd = ItemNavigation.extend("sap.m.ItemNavigationHomeEnd", {
constructor: function () {
ItemNavigation.apply(this, arguments);
this.setHomeEndColumnMode(true);
// overrides fireEvent in order to enhance it with the parameter 'direction'
this.fireEvent = function(sName, oEventParams) {
var sDirection;
if (sName === ItemNavigation.Events.BorderReached) {
sDirection = ItemNavigationHomeEnd.BorderReachedDirectionBackward;
if (["sapnext", "sapend"].indexOf(oEventParams.event.type) > -1) { // last item
sDirection = ItemNavigationHomeEnd.BorderReachedDirectionForward;
}
oEventParams[ItemNavigationHomeEnd.BorderReachedDirection] = sDirection;
}
ItemNavigation.prototype.fireEvent.apply(this, arguments);
};
}
});
// Custom Event Parameter to enhance ItemNavigation.BorderReached event with the direction of reach.
ItemNavigationHomeEnd.BorderReachedDirection = "direction";
ItemNavigationHomeEnd.BorderReachedDirectionForward = "BorderReachedDirectionForward";
ItemNavigationHomeEnd.BorderReachedDirectionBackward = "BorderReachedDirectionBackward";
/**
* Returns the number of columns defined.
* @return {*}
*/
ItemNavigationHomeEnd.prototype.getColumns = function() {
return this.iColumns;
};
/**
* Handles the backward navigation in case the [Up] key is used on the first swatch item.
* Otherwise, delegates the event to the ItemNavigation
.
* @param {jQuery.Event} oEvent the keyboard event
*/
ItemNavigationHomeEnd.prototype.onsapprevious = function (oEvent) {
var bIsOnItem = containsOrEquals(this.getRootDomRef(), oEvent.target),
bArrowUpOnFirstItem = oEvent.keyCode === KeyCodes.ARROW_UP && this.getFocusedIndex() === 0;
if (!bIsOnItem) {
return;
}
if (!bArrowUpOnFirstItem) {
ItemNavigation.prototype.onsapprevious.apply(this, arguments);
return;
}
oEvent.preventDefault(); // browser's scrolling should be prevented
this.fireEvent(ItemNavigation.Events.BorderReached, {
index: 0,
event: oEvent
});
};
/**
* Handles the forward navigation when the [Down] key is used in the following cases:
* - on the last swatch item
* - on an upper row item when moving on the same column of the next row will hit an empty/whitespace swatch item.
* Otherwise delegates the event to the ItemNavigation
.
*
* @param {jQuery.Event} oEvent the keyboard event
*/
ItemNavigationHomeEnd.prototype.onsapnext = function (oEvent) {
var bIsOnItem = containsOrEquals(this.getRootDomRef(), oEvent.target),
aItemDomRefs,
iCurrentIndex,
oItemInfo;
if (!bIsOnItem) {
return;
}
if (oEvent.keyCode !== KeyCodes.ARROW_DOWN) {
ItemNavigation.prototype.onsapnext.apply(this, arguments);
return;
}
iCurrentIndex = this.getFocusedIndex();
oItemInfo = this._getItemInfo(iCurrentIndex);
if (oItemInfo.bIsLastItem && oItemInfo.bIsInTheLastColumn) {
oEvent.preventDefault(); //browser's scrolling should be prevented
this.fireEvent(ItemNavigation.Events.BorderReached, {// Arrow down on last item should fire the event "BorderRŠµached"
index: iCurrentIndex,
event: oEvent
});
return;
}
// Whitespace handler
if (oItemInfo.bNextRowExists && !oItemInfo.bItemSameColumnNextRowExists) {
oEvent.preventDefault(); //browser's scrolling should be prevented
aItemDomRefs = this.getItemDomRefs();
aItemDomRefs[aItemDomRefs.length - 1].focus();
return;
}
ItemNavigation.prototype.onsapnext.apply(this, arguments);
};
ItemNavigationHomeEnd.prototype.onsaphome = function(oEvent) {
var bIsOnItem = containsOrEquals(this.getRootDomRef(), oEvent.target),
oItemInfo;
if (!bIsOnItem) {
return;
}
oItemInfo = this._getItemInfo(this.getFocusedIndex());
if (!oItemInfo.bIsInTheFirstColumn) {
// delegate to the parent, which should move the focus to the first item in the row
ItemNavigation.prototype.onsaphome.apply(this, arguments);
return;
}
oEvent.preventDefault(); // browser's scrolling should be prevented
if (oItemInfo.bIsFirstItem) {
this.fireEvent(ItemNavigation.Events.BorderReached, {
index: 0,
event: oEvent
});
} else { //first item in the row, move the focus to the first item in the whole container
this.getItemDomRefs()[0].focus();
}
};
ItemNavigationHomeEnd.prototype.onsapend = function(oEvent) {
var bIsOnItem = containsOrEquals(this.getRootDomRef(), oEvent.target),
oItemInfo;
if (!bIsOnItem) {
return;
}
oItemInfo = this._getItemInfo(this.getFocusedIndex());
if (!(oItemInfo.bIsLastItem || oItemInfo.bIsInTheLastColumn)) {
// delegate to the parent, which should move the focus to the last item in the row
ItemNavigation.prototype.onsapend.apply(this, arguments);
return;
}
oEvent.preventDefault(); // browser's scrolling should be prevented
if (oItemInfo.bIsLastItem) {
this.fireEvent(ItemNavigation.Events.BorderReached, {
index: this.getItemDomRefs().length - 1,
event: oEvent
});
} else { // last item in the row, move the focus to the last item in the whole container
this.getItemDomRefs()[this.getItemDomRefs().length - 1].focus();
}
};
/**
* Analyzes the given item and produces information about its position.
* @param {number} iIndex the item given by its position
* @return {{bIsLastItem: boolean, bIsInTheLastColumn: boolean, bNextRowExists: boolean|*, bItemSameColumnNextRowExists: boolean|*}}
* @private
*/
ItemNavigationHomeEnd.prototype._getItemInfo = function(iIndex) {
var iItemsCount = this.getItemDomRefs().length,
bItemIsLast = iIndex === (iItemsCount - 1),
iLastVisibleColumn = iItemsCount > this.getColumns() ? this.getColumns() : iItemsCount,
bItemIsInTheFirstColumn = iIndex % this.getColumns() === 0,
bItemIsInTheLastColumn = (iIndex + 1) % iLastVisibleColumn === 0,
iCurrentRow = Math.floor(iIndex / this.getColumns()) + 1, //1 based
bNextRowExists,
bItemSameColumnNextRowExists;
bNextRowExists = iCurrentRow * this.getColumns() < iItemsCount;
bItemSameColumnNextRowExists = bNextRowExists && (iIndex + this.getColumns()) < iItemsCount;
return {
bIsFirstItem: iIndex === 0,
bIsLastItem: bItemIsLast,
bIsInTheLastColumn: bItemIsInTheLastColumn,
bIsInTheFirstColumn: bItemIsInTheFirstColumn,
bNextRowExists: bNextRowExists,
bItemSameColumnNextRowExists: bItemSameColumnNextRowExists
};
};
/**
* Calculates the index of the first item in the last row.
* @return {int} the index(zero based) of the first/last item in the row.
* @private
*/
ItemNavigationHomeEnd.prototype._getIndexOfTheFirstItemInLastRow = function () {
return Math.floor((this.getItemDomRefs().length - 1) / this.getColumns()) * this.getColumns();
};
/**
* @private
*/
ColorPalette.prototype._ItemNavigation = ItemNavigationHomeEnd;
/**
* Private Color map helper
* @private
*/
ColorPalette.prototype._ColorsHelper = {
RGB_TO_NAMED_COLORS_MAP: {
"#FFB200": "gold",
"#FF8C00": "darkorange",
"#CD5C5C": "indianred",
"#8B008B": "darkmagenta",
"#6495ED": "cornflowerblue",
"#00BFFF": "deepskyblue",
"#008B8B": "darkcyan",
"#6B8E23": "olivedrab",
"#2F4F4F": "darkslategray",
"#F0FFFF": "azure",
"#FFFFFF": "white",
"#D3D3D3": "lightgray",
"#A9A9A9": "darkgray",
"#696969": "dimgray",
"#000000": "black"
},
NAME_COLORS_TO_RGB_MAP: {
"gold": "#FFB200",
"darkorange": "#FF8C00",
"indianred": "#CD5C5C",
"darkmagenta": "#8B008B",
"cornflowerblue": "#6495ED",
"deepskyblue": "#00BFFF",
"darkcyan": "#008B8B",
"olivedrab": "#6B8E23",
"darkslategray": "#2F4F4F",
"azure": "#F0FFFF",
"white": "#FFFFFF",
"lightgray": "#D3D3D3",
"darkgray": "#A9A9A9",
"dimgray": "#696969",
"black": "#000000"
},
/**
* Returns a named color for given color. For example - "gold" for input "#FFB200".
* @param {string} sColor the given color
* @return {string|undefined} The named color, if such can really corresponds to the input color, or undefined otherwise.
*/
getNamedColor: function (sColor) {
var sHexColor = "";
if (!sColor || sColor.toLowerCase().indexOf("hsl") !== -1) {
return undefined;
}
// named color
if (sColor.indexOf("#") === -1) {
return this.NAME_COLORS_TO_RGB_MAP[sColor.toLowerCase()] ? sColor.toLowerCase() : undefined;
}
//HEX value
if (sColor.length === 4) {
sHexColor = ["#", sColor[1], sColor[1], sColor[2], sColor[2], sColor[3], sColor[3]].join("");
} else {
sHexColor = sColor;
}
sHexColor = sHexColor.toUpperCase();
return this.RGB_TO_NAMED_COLORS_MAP[sHexColor];
}
};
return ColorPalette;
}
);