Resolved FELIX-2149 /Configuration Status tabs are not properly left aligned/
https://issues.apache.org/jira/browse/FELIX-2149
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@926051 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole/LICENSE.tabspaging b/webconsole/LICENSE.tabspaging
new file mode 100644
index 0000000..beedc27
--- /dev/null
+++ b/webconsole/LICENSE.tabspaging
@@ -0,0 +1,19 @@
+Copyright (c) 2009, http://seyfertdesign.com/jquery/ui-tabs-paging.html
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/webconsole/NOTICE b/webconsole/NOTICE
index 15a8bd1..75798ad 100644
--- a/webconsole/NOTICE
+++ b/webconsole/NOTICE
@@ -44,6 +44,10 @@
This product includes software from the Mozilla Foundation
Licensed under the MIT License
+This product includes software from http://seyfertdesign.com/jquery/
+Copyright (c) 2009, http://seyfertdesign.com/
+Licensed under the MIT License
+
II. Used Software
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/ConfigurationRender.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/ConfigurationRender.java
index c47d033..552de34 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/ConfigurationRender.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/ConfigurationRender.java
@@ -48,7 +48,7 @@
private static final String LABEL = "config";
private static final String TITLE = "%configStatus.pluginTitle";
- private static final String[] CSS_REFS = null;
+ private static final String[] CSS_REFS = { "/res/ui/configurationrender.css" };
// use English as the locale for all non-display titles
private static final Locale DEFAULT = Locale.ENGLISH;
@@ -87,6 +87,9 @@
}
+ /**
+ * @see org.apache.felix.webconsole.SimpleWebConsolePlugin#deactivate()
+ */
public void deactivate()
{
// make sure the service tracker is closed and removed on deactivate
@@ -180,10 +183,10 @@
//ConfigurationWriter pw = new HtmlConfigurationWriter( response.getWriter() );
PrintWriter pw = response.getWriter();
-
+ pw.println( "<script type='text/javascript' src='${appRoot}/res/ui/ui.tabs.paging.js'></script>" );
pw.println( "<script type='text/javascript'>" );
pw.println( "// <![CDATA[" );
- pw.println("$(document).ready(function() {$('#tabs').tabs()} );");
+ pw.println( "$(document).ready(function() {$('#tabs').tabs().tabs('paging')} );" );
pw.println( "// ]]>" );
pw.println( "</script>" );
diff --git a/webconsole/src/main/resources/res/ui/configurationrender.css b/webconsole/src/main/resources/res/ui/configurationrender.css
index 75000de..370e1aa 100644
--- a/webconsole/src/main/resources/res/ui/configurationrender.css
+++ b/webconsole/src/main/resources/res/ui/configurationrender.css
@@ -15,77 +15,33 @@
* limitations under the License.
*/
-/* tabbed view */
-
-#divcfgprttabs {
+.ui-tabs-paging-next {
+ float: right !important;
}
-
-.divcfgprttabshidden {
- display: none;
+.ui-tabs-paging-prev,
+.ui-tabs-paging-next {
+ background: transparent !important;
+ border: 0 !important;
+ margin-bottom: 1px !important;
}
-
-#divcfgprttabs ul {
- list-style: none;
+.ui-tabs-paging-prev a,
+.ui-tabs-paging-next a {
+ display: block;
+ position: relative;
+ top: 1px;
+ border: 0;
+ z-index: 2;
+ padding: 0;
+ text-decoration: none;
+ background: transparent !important;
+ cursor: pointer;
}
-
-#divcfgprttabs ul li {
- display: inline-block;
- background: #fff;
+.ui-tabs-paging-next a:hover,
+.ui-tabs-paging-next a:focus,
+.ui-tabs-paging-next a:active,
+.ui-tabs-paging-prev a:hover,
+.ui-tabs-paging-prev a:focus,
+.ui-tabs-paging-prev a:active {
+ background: transparent
}
-
-#divcfgprttabs ul li.tabactive {
-}
-
-#divcfgprttabs ul li a {
- color: #6181A9;
- background-color: white;
- display: block;
- float: left;
- height: 100%;
- line-height: 2;
- padding: 0 10px 0 10px;
- cursor: pointer;
-}
-
-#divcfgprttabs ul li a.tabactive {
- background-color: #6181A9;
- color: white;
-}
-
-#divcfgprttabs ul li a:hover {
- color: white;
- background-color: #6181A9;
-}
-
-.menu {
- background: none;
- margin-bottom: 0;
- padding-left: 0;
-}
-.area {
- background: #fff;
- border: 1px solid #999;
- padding: 1px;
-}
-
-/* Contents container of the tabs */
-.tabcont {
- background: #fff;
- border: 1px solid #999;
- border-right: none;
- padding: 1px;
-}
-
-/* The actual content of the tabs */
-.space {
- padding: 10px;
-
- /* don't let this area make the display wider */
- width: 100px;
- overflow: visible;
-}
-
-.space div {
- font-family: monospace;
- white-space: pre;
-}
+.ui-tabs-paging-disabled { visibility: hidden }
diff --git a/webconsole/src/main/resources/res/ui/ui.tabs.paging.js b/webconsole/src/main/resources/res/ui/ui.tabs.paging.js
new file mode 100644
index 0000000..ef7dc3e
--- /dev/null
+++ b/webconsole/src/main/resources/res/ui/ui.tabs.paging.js
@@ -0,0 +1,270 @@
+/*
+Copyright (c) 2009, http://seyfertdesign.com/jquery/ui-tabs-paging.html
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+$.extend($.ui.tabs.prototype, {
+ paging: function(options) {
+ var opts = {
+ tabsPerPage: 0,
+ nextButton: '»',
+ prevButton: '«',
+ follow: false,
+ cycle: false,
+ selectOnAdd: false,
+ followOnSelect: false
+ };
+
+ opts = $.extend(opts, options);
+
+ var self = this, initialized = false, currentPage,
+ buttonWidth, containerWidth, allTabsWidth, tabWidths,
+ maxPageWidth, pages, resizeTimer = null,
+ windowHeight = $(window).height(), windowWidth = $(window).width();
+
+ function init() {
+ destroy();
+
+ allTabsWidth = 0, currentPage = 0, maxPageWidth = 0, buttonWidth = 0,
+ pages = new Array(), tabWidths = new Array(), selectedTabWidths = new Array();
+
+ containerWidth = self.element.width();
+
+ // loops through LIs, get width of each tab when selected and unselected.
+ var maxDiff = 0; // the max difference between a selected and unselected tab
+ self.lis.each(function(i) {
+ if (i == self.options.selected) {
+ selectedTabWidths[i] = $(this).outerWidth({ margin: true });
+ tabWidths[i] = self.lis.eq(i).removeClass('ui-tabs-selected').outerWidth({ margin: true });
+ self.lis.eq(i).addClass('ui-tabs-selected');
+ maxDiff = Math.min(maxDiff, Math.abs(selectedTabWidths[i] - tabWidths[i]));
+ allTabsWidth += tabWidths[i];
+ } else {
+ tabWidths[i] = $(this).outerWidth({ margin: true });
+ selectedTabWidths[i] = self.lis.eq(i).addClass('ui-tabs-selected').outerWidth({ margin: true });
+ self.lis.eq(i).removeClass('ui-tabs-selected');
+ maxDiff = Math.max(maxDiff, Math.abs(selectedTabWidths[i] - tabWidths[i]));
+ allTabsWidth += tabWidths[i];
+ }
+ });
+ // fix padding issues with buttons
+ // TODO determine a better way to handle this
+ allTabsWidth += maxDiff + ($.browser.msie?4:0) + 9;
+
+ // if the width of all tables is greater than the container's width, calculate the pages
+ if (allTabsWidth > containerWidth) {
+ // create next button
+ li = $('<li></li>')
+ .addClass('ui-state-default ui-tabs-paging-next')
+ .append($('<a href="#"></a>')
+ .click(function() { page('next'); return false; })
+ .html(opts.nextButton));
+
+ self.lis.eq(self.length()-1).after(li);
+ buttonWidth = li.outerWidth({ margin: true });
+
+ // create prev button
+ li = $('<li></li>')
+ .addClass('ui-state-default ui-tabs-paging-prev')
+ .append($('<a href="#"></a>')
+ .click(function() { page('prev'); return false; })
+ .html(opts.prevButton));
+ self.lis.eq(0).before(li);
+ buttonWidth += li.outerWidth({ margin: true });
+
+ // TODO determine fix for padding issues to next button
+ buttonWidth += 19;
+
+ var pageIndex = 0, pageWidth = 0, maxTabPadding = 0;
+
+ // start calculating pageWidths
+ for (var i = 0; i < tabWidths.length; i++) {
+ // if first tab of page or selected tab's padding larger than the current max, set the maxTabPadding
+ if (pageWidth == 0 || selectedTabWidths[i] - tabWidths[i] > maxTabPadding)
+ maxTabPadding = (selectedTabWidths[i] - tabWidths[i]);
+
+ // if first tab of page, initialize pages variable for page
+ if (pages[pageIndex] == null) {
+ pages[pageIndex] = { start: i };
+
+ } else if ((i > 0 && (i % opts.tabsPerPage) == 0) || (tabWidths[i] + pageWidth + buttonWidth + 12) > containerWidth) {
+ if ((pageWidth + maxTabPadding) > maxPageWidth)
+ maxPageWidth = (pageWidth + maxTabPadding);
+ pageIndex++;
+ pages[pageIndex] = { start: i };
+ pageWidth = 0;
+ }
+ pages[pageIndex].end = i+1;
+ pageWidth += tabWidths[i];
+ if (i == self.options.selected) currentPage = pageIndex;
+ }
+ if ((pageWidth + maxTabPadding) > maxPageWidth)
+ maxPageWidth = (pageWidth + maxTabPadding);
+
+ // hide all tabs then show tabs for current page
+ self.lis.hide().slice(pages[currentPage].start, pages[currentPage].end).show();
+ if (currentPage == (pages.length - 1) && !opts.cycle)
+ disableButton('next');
+ if (currentPage == 0 && !opts.cycle)
+ disableButton('prev');
+
+ // calculate the right padding for the next button
+ buttonPadding = containerWidth - maxPageWidth - buttonWidth;
+ if (buttonPadding > 0)
+ $('.ui-tabs-paging-next', self.element).css({ paddingRight: buttonPadding + 'px' });
+
+ initialized = true;
+ } else {
+ destroy();
+ }
+
+ $(window).bind('resize', handleResize);
+ }
+
+ function page(direction) {
+ currentPage = currentPage + (direction == 'prev'?-1:1);
+
+ if ((direction == 'prev' && currentPage < 0 && opts.cycle) ||
+ (direction == 'next' && currentPage >= pages.length && !opts.cycle))
+ currentPage = pages.length - 1;
+ else if ((direction == 'prev' && currentPage < 0) ||
+ (direction == 'next' && currentPage >= pages.length && opts.cycle))
+ currentPage = 0;
+
+ var start = pages[currentPage].start;
+ var end = pages[currentPage].end;
+ self.lis.hide().slice(start, end).show();
+
+ if (direction == 'prev') {
+ enableButton('next');
+ if (opts.follow && (self.options.selected < start || self.options.selected > (end-1))) self.select(end-1);
+ if (!opts.cycle && start <= 0) disableButton('prev');
+ } else {
+ enableButton('prev');
+ if (opts.follow && (self.options.selected < start || self.options.selected > (end-1))) self.select(start);
+ if (!opts.cycle && end >= self.length()) disableButton('next');
+ }
+ }
+
+ function disableButton(direction) {
+ $('.ui-tabs-paging-'+direction, self.element).addClass('ui-tabs-paging-disabled');
+ }
+
+ function enableButton(direction) {
+ $('.ui-tabs-paging-'+direction, self.element).removeClass('ui-tabs-paging-disabled');
+ }
+
+ // special function defined to handle IE6 and IE7 resize issues
+ function handleResize() {
+ if (resizeTimer) clearTimeout(resizeTimer);
+
+ if (windowHeight != $(window).height() || windowWidth != $(window).width())
+ resizeTimer = setTimeout(reinit, 100);
+ }
+
+ function reinit() {
+ windowHeight = $(window).height();
+ windowWidth = $(window).width();
+ init();
+ }
+
+ function destroy() {
+ // remove buttons
+ $('.ui-tabs-paging-next', self.element).remove();
+ $('.ui-tabs-paging-prev', self.element).remove();
+
+ // show all tabs
+ self.lis.show();
+
+ initialized = false;
+
+ $(window).unbind('resize', handleResize);
+ }
+
+ // reconfigure "ui.tabs" add/remove events to reinit paging
+ var tabsAdd = self.add;
+ self.add = function(url, label, index) {
+ // remove paging buttons before adding a tab
+ if (initialized)
+ destroy();
+
+ tabsAdd.apply(this, [url, label, index]);
+
+ if (opts.selectOnAdd) {
+ if (index == undefined) index = this.lis.length-1;
+ this.select(index);
+ }
+ // re-initialize paging buttons
+ init();
+ };
+ var tabsRemove = self.remove;
+ self.remove = function(index) {
+ // remove paging buttons before removing a tab
+ if (initialized)
+ destroy();
+
+ tabsRemove.apply(this, [index]);
+
+ // re-initialize paging buttons
+ init();
+ };
+ // reconfigure "ui.tabs" select event to change pages if new tab is selected
+ var tabsSelect = self.select;
+ self.select = function(index) {
+ tabsSelect.apply(this, [index]);
+
+ // if paging is not initialized or it is not configured to
+ // change pages when a new tab is selected, then do nothing
+ if (!initialized || !opts.followOnSelect)
+ return;
+
+ // find the new page based on index of the tab selected
+ for (i in pages) {
+ var start = pages[i].start;
+ var end = pages[i].end;
+ if (index >= start && index < end) {
+ // if the the tab selected is not within the currentPage of tabs, then change pages
+ if (i != currentPage) {
+ self.lis.hide().slice(start, end).show();
+
+ currentPage = parseInt(i);
+ if (currentPage == 0) {
+ enableButton('next');
+ if (!opts.cycle && start <= 0) disableButton('prev');
+ } else {
+ enableButton('prev');
+ if (!opts.cycle && end >= self.length()) disableButton('next');
+ }
+ }
+ break;
+ }
+ }
+ };
+
+ // add, remove, and destroy functions specific for paging
+ $.extend($.ui.tabs.prototype, {
+ pagingDestroy: function() {
+ destroy();
+ }
+ });
+
+ init();
+ }
+});