diff --git a/apidoc/Titanium/UI/TabGroup.yml b/apidoc/Titanium/UI/TabGroup.yml index da052078eb1..fcaac2326b4 100644 --- a/apidoc/Titanium/UI/TabGroup.yml +++ b/apidoc/Titanium/UI/TabGroup.yml @@ -22,13 +22,13 @@ description: | On iOS, tabs can be removed, and the user may (optionally) be allowed to reorder tabs. - On iOS, it is - also possible to add tabs by updating the [tabs](Titanium.UI.TabGroup.tabs) property, - and to switch active tabs by setting the [active](Titanium.UI.Tab.active) - property on one of the tabs to `true`. Since these mechanisms are platform-specific, - it is recommended that you use `addTab` and `setActiveTab` instead. + On iOS and Mobile Web, it is also possible to add tabs by updating the + [tabs](Titanium.UI.TabGroup.tabs) property, and to switch active tabs by setting + the [active](Titanium.UI.Tab.active) property on one of the tabs to `true`. Since + these mechanisms are platform-specific, it is recommended that you use `addTab` + and `setActiveTab` instead. - If you use the iOS-specific mechanisms, it is possible to add multiple active tabs + If you use the iOS/Mobile Web-specific mechanisms, it is possible to add multiple active tabs to a tab group. In this case, the result of which tab is initially selected is undefined. extends: Titanium.UI.View @@ -123,3 +123,103 @@ properties: type: Number platforms: [android] availabilty: creation + - name: tabsBackgroundColor + summary: The default background color for tabs. If [backgroundColor](Titanium.UI.Tab.backgroundColor) is explicitly set on an individual tab, that value takes precidence. + type: String + platforms: [android, mobileweb] + - name: tabsBackgroundImage + summary: The default background image for tabs. If [backgroundImage](Titanium.UI.Tab.backgroundImage) is explicitly set on an individual tab, that value takes precidence. + type: String + since: "1.9.0" + platforms: [android, mobileweb] + - name: tabsBackgroundDisabledColor + summary: The default background disabled color for tabs. If [backgroundDisabledColor](Titanium.UI.Tab.backgroundDisabledColor) is explicitly set on an individual tab, that value takes precidence. + type: String + since: "1.9.0" + platforms: [android, mobileweb] + - name: tabsBackgroundDisabledImage + summary: The default background disabled image for tabs. If [backgroundDisabledImage](Titanium.UI.Tab.backgroundDisabledImage) is explicitly set on an individual tab, that value takes precidence. + type: String + since: "1.9.0" + platforms: [android, mobileweb] + - name: tabsBackgroundFocusedColor + summary: The default background focused color for tabs. If [backgroundFocusedColor](Titanium.UI.Tab.backgroundFocusedColor) is explicitly set on an individual tab, that value takes precidence. + type: String + since: "1.9.0" + platforms: [android, mobileweb] + - name: tabsBackgroundFocusedImage + summary: The default background focused image for tabs. If [backgroundFocusedImage](Titanium.UI.Tab.backgroundFocusedImage) is explicitly set on an individual tab, that value takes precidence. + type: String + since: "1.9.0" + platforms: [android, mobileweb] + - name: tabsBackgroundSelectedColor + summary: The default background selected color for tabs. If [backgroundSelectedColor](Titanium.UI.Tab.backgroundSelectedColor) is explicitly set on an individual tab, that value takes precidence. + type: String + since: "1.9.0" + platforms: [android, mobileweb] + - name: tabsBackgroundSelectedImage + summary: The default background selected image for tabs. If [backgroundSelectedImage](Titanium.UI.Tab.backgroundSelectedImage) is explicitly set on an individual tab, that value takes precidence. + type: String + since: "1.9.0" + platforms: [android, mobileweb] + - name: activeTabBackgroundColor + summary: The default background color for the active tab. If [backgroundColor](Titanium.UI.Tab.backgroundColor) is explicitly set on an individual tab, that value takes precidence. + type: String + since: "1.9.0" + platforms: [android, mobileweb] + - name: activeTabBackgroundImage + summary: The default background image for the active tab. If [backgroundImage](Titanium.UI.Tab.backgroundImage) is explicitly set on an individual tab, that value takes precidence. + type: String + since: "1.9.0" + platforms: [android, mobileweb] + - name: activeTabBackgroundDisabledColor + summary: The default background disabled color for the active tab. If [backgroundDisabledColor](Titanium.UI.Tab.backgroundDisabledColor) is explicitly set on an individual tab, that value takes precidence. + type: String + since: "1.9.0" + platforms: [android, mobileweb] + - name: activeTabBackgroundDisabledImage + summary: The default background disabled image for the active tab. If [backgroundDisabledImage](Titanium.UI.Tab.backgroundDisabledImage) is explicitly set on an individual tab, that value takes precidence. + type: String + since: "1.9.0" + platforms: [android, mobileweb] + - name: activeTabBackgroundFocusedColor + summary: The default background focused color for the active tab. If [backgroundFocusedColor](Titanium.UI.Tab.backgroundFocusedColor) is explicitly set on an individual tab, that value takes precidence. + type: String + since: "1.9.0" + platforms: [android, mobileweb] + - name: activeTabBackgroundFocusedImage + summary: The default background focused image for the active tab. If [backgroundFocusedImage](Titanium.UI.Tab.backgroundFocusedImage) is explicitly set on an individual tab, that value takes precidence. + type: String + since: "1.9.0" + platforms: [android, mobileweb] + - name: activeTabBackgroundSelectedColor + summary: The default background selected color for the active tab. If [backgroundSelectedColor](Titanium.UI.Tab.backgroundSelectedColor) is explicitly set on an individual tab, that value takes precidence. + type: String + since: "1.9.0" + platforms: [android, mobileweb] + - name: activeTabBackgroundSelectedImage + summary: The default background selected image for the active tab. If [backgroundSelectedImage](Titanium.UI.Tab.backgroundSelectedImage) is explicitly set on an individual tab, that value takes precidence. + type: String + since: "1.9.0" + platforms: [android, mobileweb] + - name: tabDividerColor + summary: The color of the divider between tabs + type: String + since: "1.9.0" + platforms: [android, mobileweb] + - name: tabDividerWidth + summary: The width of the divider between tabs. + description: | + This width is relative to the tabgroup's parent. Can be either a float value or + a dimension string (for example, '50%' or 'auto'). + type: [Number,String] + since: "1.9.0" + platforms: [android, mobileweb] + - name: tabHeight + summary: The height of the tabs. + description: | + This height is relative to the tabgroup's parent. Can be either a float value or + a dimension string (for example, '50%' or 'auto'). + type: [Number,String] + since: "1.9.0" + platforms: [mobileweb] diff --git a/mobileweb/themes/common.css b/mobileweb/themes/common.css index 1b9f4f21448..599d157e63d 100644 --- a/mobileweb/themes/common.css +++ b/mobileweb/themes/common.css @@ -231,20 +231,6 @@ textarea { to(#666)); } -.TiUITab { - background-color: silver; - border: solid 1px black; -} -.TiUITab:active { - background-color: gray; -} -.TiUITab.TiActiveTab { - background-color: white; -} -.TiUITab.TiActiveTab:active { - background-color: gray; -} - .TiMediaVideoPlayer video { left: 0; position: absolute; diff --git a/mobileweb/titanium/Ti/UI/TabGroup.js b/mobileweb/titanium/Ti/UI/TabGroup.js index 7d5062f3148..be97ab23bb0 100644 --- a/mobileweb/titanium/Ti/UI/TabGroup.js +++ b/mobileweb/titanium/Ti/UI/TabGroup.js @@ -1,25 +1,46 @@ -define(["Ti/_/declare", "Ti/_/css", "Ti/_/UI/SuperView", "Ti/UI"], function(declare, css, SuperView, UI) { +define(["Ti/_/declare", "Ti/_/css", "Ti/_/UI/SuperView", "Ti/UI/View", "Ti/UI", "Ti/_/lang"], function(declare, css, SuperView, View, UI, lang) { - var is = require.is; + var is = require.is, + postUpdateTabsBackground = { + post: "_updateTabsBackground" + }; return declare("Ti.UI.TabGroup", SuperView, { constructor: function(args){ + + this.layout = "vertical"; + + // Create the tabBarContainer class + var self = this; + var TabBarContainer = declare("Ti._.UI.TabGroup.TabBarContainer", View, { + _doLayout: function(originX, originY, parentWidth, parentHeight, centerHDefault, centerVDefault) { + var tabs = self.tabs, + numTabs = tabs.length, + tabWidth = Math.floor((parentWidth - (numTabs - 1) * self.tabDividerWidth) / numTabs); + for (var i = 0; i < numTabs - 1; i++) { + tabs[i]._tabWidth = tabWidth; + } + // Make the last tab consume the remaining space. Fractional widths look really bad in tabs. + tabs[i]._tabWidth = parentWidth - (numTabs - 1) * self.tabDividerWidth - tabWidth * (numTabs - 1); + View.prototype._doLayout.apply(this,arguments); + } + }); + // Create the tab bar - this.add(this._tabBarContainer = UI.createView({ - width: "100%", - height: "10%", - layout: "horizontal", - top: 0, - left: 0 + this.add(this._tabBarContainer = new TabBarContainer({ + left: 0, + right: 0, + layout: "horizontal" })); + this.tabHeight = "10%"; // Create the tab window container this.add(this._tabContentContainer = UI.createView({ - width: "100%", - height: "90%", left: 0, - top: "10%" + right: 0, + top: 0, + bottom: 0 })); this.tabs = []; @@ -28,16 +49,24 @@ define(["Ti/_/declare", "Ti/_/css", "Ti/_/UI/SuperView", "Ti/UI"], function(decl addTab: function(tab) { // Initialize the tabs, if necessary this.tabs = this.tabs || []; - - // Add the tab to the list and tab bar + + // Add the tab to the list var tabs = this.tabs; tabs.push(tab); tab._tabGroup = this; - this._tabBarContainer.add(tab); - this._setTabBarWidths(tabs); - // Set the active tab if there are currently no tabs - tabs.length == 1 && (this.properties.activeTab = tab); + // Set the active tab if there are currently no tabs, otherwise add a divider + if (tabs.length === 1) { + this.properties.activeTab = tab; + } else { + this._tabBarContainer.add(this._createTabDivider()); + } + + // Add the tab to the UI + this._tabBarContainer.add(tab); + + // Update the background on the tab + this._updateTabBackground(tab); }, removeTab: function(tab) { @@ -50,12 +79,19 @@ define(["Ti/_/declare", "Ti/_/css", "Ti/_/UI/SuperView", "Ti/UI"], function(decl // Remove the tab from the tab bar and recalculate the tab sizes this._tabBarContainer.remove(tab); - this._setTabBarWidths(tabs); // Update the active tab, if necessary tab === this._activeTab && this._activateTab(tabs[0]); } }, + + _createTabDivider: function() { + return Ti.UI.createView({ + width: this.tabDividerWidth, + height: "100%", + backgroundColor: this.tabDividerColor + }); + }, _activateTab: function(tab) { var tabs = this.tabs, @@ -63,27 +99,48 @@ define(["Ti/_/declare", "Ti/_/css", "Ti/_/UI/SuperView", "Ti/UI"], function(decl if (prev) { prev.active = false; - css.remove(prev.domNode, "TiActiveTab"); - this._tabContentContainer.remove(prev["window"]); + prev._doBackground(); + prev["window"] && this._tabContentContainer.remove(prev["window"]); } - css.add(tab.domNode, "TiActiveTab"); tab.active = true; - this._activeTab = tab; - this._tabContentContainer.add(tab["window"]); + tab["window"] && this._tabContentContainer.add(tab["window"]); this._state = { index: tabs.indexOf(tab), previousIndex: prev ? tabs.indexOf(prev) : -1, previousTab: prev, tab: tab }; + this._updateTabsBackground(); }, - - _setTabBarWidths: function(tabs) { - var tabWidth = (100 / tabs.length) + "%"; - for (var i in tabs) { - tabs[i]._tabWidth = tabWidth; + + _updateTabBackground: function(tab) { + var prefix = tab.active ? "activeTab" : "tabs"; + tab._defaultBackgroundColor = this[prefix + "BackgroundColor"]; + tab._defaultBackgroundImage = this[prefix + "BackgroundImage"]; + tab._defaultBackgroundFocusedColor = this[prefix + "BackgroundFocusedColor"]; + tab._defaultBackgroundFocusedImage = this[prefix + "BackgroundFocusedImage"]; + tab._defaultBackgroundDisabledColor = this[prefix + "BackgroundDisabledColor"]; + tab._defaultBackgroundDisabledImage = this[prefix + "BackgroundDisabledImage"]; + tab._defaultBackgroundSelectedColor = this[prefix + "BackgroundSelectedColor"]; + tab._defaultBackgroundSelectedImage = this[prefix + "BackgroundSelectedImage"]; + tab._doBackground(); + }, + + _updateTabsBackground: function() { + var tabs = this.tabs; + for (var i = 0; i < tabs.length; i++) { + this._updateTabBackground(tabs[i]); + } + }, + + _updateDividers: function(){ + var tabs = this._tabBarContainer.children; + for(var i = 1; i < tabs.length; i += 2) { + var tab = tabs[i]; + tab.width = this.tabDividerWidth; + tab.backgroundColor = this.tabDividerColor; } }, @@ -95,19 +152,20 @@ define(["Ti/_/declare", "Ti/_/css", "Ti/_/UI/SuperView", "Ti/UI"], function(decl activeTab: { set: function(value) { if (is(value, "Number")) { - if (!value in this.tabs) { - return; - } value = this.tabs[value]; } - - this._activateTab(value); + if (!value in this.tabs) { + return; + } return value; + }, + post: function(value) { + lang.isDef(value) && this._activateTab(value); } }, tabs: { - set: function(value, oldValue) { + set: function(value) { var i, tabBarContainer = this._tabBarContainer; @@ -115,18 +173,95 @@ define(["Ti/_/declare", "Ti/_/css", "Ti/_/UI/SuperView", "Ti/UI"], function(decl return; } - for (i in oldValue) { - tabBarContainer.remove(oldValue[i]); - } + tabBarContainer._removeAllChildren(); if (value.length) { - this._setTabBarWidths(value); this._activateTab(value[0]); - for (i in value) { + for (i = 0; i < value.length - 1; i++) { tabBarContainer.add(value[i]); + tabBarContainer.add(this._createTabDivider()); } + tabBarContainer.add(value[value.length - 1]); // No trailing divider } + return value; + }, + post: "_updateTabsBackground" + }, + + activeTabBackgroundColor: { + post: "_updateTabsBackground", + value: "#fff" + }, + + activeTabBackgroundImage: postUpdateTabsBackground, + + activeTabBackgroundDisabledColor: { + post: "_updateTabsBackground", + value: "#888" + }, + + activeTabBackgroundDisabledImage: postUpdateTabsBackground, + + activeTabBackgroundFocusedColor: { + post: "_updateTabsBackground", + value: "#ccc" + }, + + activeTabBackgroundFocusedImage: postUpdateTabsBackground, + + activeTabBackgroundSelectedColor: { + post: "_updateTabsBackground", + value: "#ddd" + }, + + activeTabBackgroundSelectedImage: postUpdateTabsBackground, + + tabsBackgroundColor: { + post: "_updateTabsBackground", + value: "#aaa" + }, + + tabsBackgroundImage: postUpdateTabsBackground, + + tabsBackgroundDisabledColor: { + post: "_updateTabsBackground", + value: "#666" + }, + + tabsBackgroundDisabledImage: postUpdateTabsBackground, + + tabsBackgroundFocusedColor: { + post: "_updateTabsBackground", + value: "#ccc" + }, + + tabsBackgroundFocusedImage: postUpdateTabsBackground, + + tabsBackgroundSelectedColor: { + post: "_updateTabsBackground", + value: "#ddd" + }, + + tabsBackgroundSelectedImage: postUpdateTabsBackground, + + tabDividerColor: { + post: function() { + this._updateDividers(); + }, + value: "#555" + }, + + tabDividerWidth: { + post: function() { + this._updateDividers(); + }, + value: 1 + }, + + tabHeight: { + set: function(value) { + this._tabBarContainer.height = value; return value; } } diff --git a/mobileweb/titanium/Ti/_/UI/Element.js b/mobileweb/titanium/Ti/_/UI/Element.js index 49d2e312ab8..edd884f7f95 100644 --- a/mobileweb/titanium/Ti/_/UI/Element.js +++ b/mobileweb/titanium/Ti/_/UI/Element.js @@ -443,28 +443,44 @@ define( _handleTouchEvent: function(type, e) { this.enabled && this.fireEvent(type, e); }, + + _defaultBackgroundColor: undef, + + _defaultBackgroundImage: undef, + + _defaultBackgroundDisabledColor: undef, + + _defaultBackgroundDisabledImage: undef, + + _defaultBackgroundFocusedColor: undef, + + _defaultBackgroundFocusedImage: undef, + + _defaultBackgroundSelectedColor: undef, + + _defaultBackgroundSelectedImage: undef, _doBackground: function(evt) { var evt = evt || {}, m = (evt.type || "").match(/mouse(over|out)/), node = this._focus.node, - bi = this.backgroundImage || "none", - bc = this.backgroundColor; + bi = this.backgroundImage || this._defaultBackgroundImage || "none", + bc = this.backgroundColor || this._defaultBackgroundColor; if (this._touching) { - bc = this.backgroundSelectedColor || bc; - bi = this.backgroundSelectedImage || bi; + bc = this.backgroundSelectedColor || this._defaultBackgroundSelectedColor || bc; + bi = this.backgroundSelectedImage || this._defaultBackgroundSelectedImage || bi; } m && (this._over = m[1] === "over"); if (!this._touching && this.focusable && this._over) { - bc = this.backgroundFocusedColor || bc; - bi = this.backgroundFocusedImage || bi; + bc = this.backgroundFocusedColor || this._defaultBackgroundFocusedColor || bc; + bi = this.backgroundFocusedImage || this._defaultBackgroundFocusedImage || bi; } if (!this.enabled) { - bc = this.backgroundDisabledColor || bc; - bi = this.backgroundDisabledImage || bi; + bc = this.backgroundDisabledColor || this._defaultBackgroundDisabledColor || bc; + bi = this.backgroundDisabledImage || this._defaultBackgroundDisabledImage || bi; } setStyle(node, {