diff --git a/css/admin.css b/css/admin.css new file mode 100644 index 0000000000000000000000000000000000000000..b37ac91402748a7ab371624fb8917aab4f6390b9 --- /dev/null +++ b/css/admin.css @@ -0,0 +1,97 @@ +/* $Id$ */ + +.views-tabset .views-tab fieldset { + margin-top: 0; +} + +.views-tabset .views-tabs ul { + list-style-type: none !important; + list-style-image: none !important; + border: 1px solid black; + margin: 0; + padding: 0; +} + +.views-tabset .views-tabs ul li { + list-style-type: none; + list-style-image: none; + background: none; + margin-left: 0; +} + +.views-tabset .views-tabs ul li.active { + background: #ccc; + margin-left: 0; +} + + +.views-tabset .views-tabs { + float: left; + width: 120px; +} + +.views-tabset .extra { + text-align: center; +} + +.views-tabset .extra input { + margin-top: 0; +} + +.views-tabset .views-tab-area { + border: 1px solid black; + margin-left: 119px; /* 120 -1 causes borders to overlap */ + min-height: 300px; + _height: 300px; /* stupid IE hack */ +} + +.views-tab-area .tab-section { + width: 33%; + padding: 0; + margin: 0; + float: left; + min-height: 300px; + _height: 300px; +} + +.views-tab-area .tab-section .inside { + margin: 0; + padding: 2px 5px; +} + +.views-tab-area .tab-section .links { + float: right; +} + +.views-tab-area .tab-section .links a { + font-size: small; +} + +.views-tab-area .middle { + width: 34%; + background-color: #ccc; +} + +.views-tab-area dl { + margin: 0; +} + +.views-basic-info { + border: 1px solid black; + padding: 2px 5px; + background-color: #eee; +} + +.views-ajax-pad { + border: 1px solid black; + margin-top: 10px; + min-height: 200px; + _height: 200px; /* stupid IE */ +} + +.views-ajax-pad .message { + margin-top: 75px; + text-align: center; +} + + diff --git a/css/tabs.css b/css/tabs.css new file mode 100644 index 0000000000000000000000000000000000000000..5108f579741f75e2f2b2af4d968c0102b7139c28 --- /dev/null +++ b/css/tabs.css @@ -0,0 +1,3 @@ +.ui-tabs-hide { + display: none; +} diff --git a/js/base.js b/js/base.js new file mode 100644 index 0000000000000000000000000000000000000000..8d8b1a28b0bd687207cc8f24a8d268f54e2962b9 --- /dev/null +++ b/js/base.js @@ -0,0 +1,11 @@ +Drupal.Views = {}; + +/** + * jQuery UI tabs, Views integration component + */ + +Drupal.behaviors.viewsTabs = function (context) { + $('.views-tabset:not(.views-processed)').addClass('views-processed').tabs({ + selectedClass: 'active' + }); +} diff --git a/js/tabs.js b/js/tabs.js new file mode 100644 index 0000000000000000000000000000000000000000..62ce8a3ea58680d99a0db9a006f9b11f4bf3b242 --- /dev/null +++ b/js/tabs.js @@ -0,0 +1,433 @@ +/** + * jQuery UI Tabs (Tabs 3) + */ +(function($) { + + // if the UI scope is not availalable, add it + $.ui = $.ui || {}; + + $.fn.tabs = function(initial, options) { + if (initial && initial.constructor == Object) { // shift arguments + options = initial; + initial = null; + } + options = options || {}; + + // first get initial tab from options + initial = initial && initial.constructor == Number && --initial || 0; + + return this.each(function() { + new $.ui.tabs(this, $.extend(options, { initial: initial })); + }); + }; + + // chainable tabs methods + $.each(['add', 'remove', 'enable', 'disable', 'click', 'load'], function(i, method) { + $.fn[method + 'Tab'] = function() { + var args = arguments; + return this.each(function() { + var instance = $.ui.tabs.instances[this.UI_TABS_UUID]; + instance[method].apply(instance, args); + }); + }; + }); + $.fn.selectedTab = function(returnElement) { + var selected; + if (returnElement) { + + } else { + + } + return selected; + }; + + $.ui.tabs = function(el, options) { + + this.source = el; + + this.options = $.extend({ + + // basic setup + initial: 0, + event: 'click', + disabled: [], + // TODO bookmarkable: $.ajaxHistory ? true : false, + unselected: false, + toggle: options.unselected ? true : false, + + // Ajax + spinner: 'Loading…', + cache: false, + hashPrefix: 'tab-', + + // animations + /*fxFade: null, + fxSlide: null, + fxShow: null, + fxHide: null,*/ + fxSpeed: 'normal', + /*fxShowSpeed: null, + fxHideSpeed: null,*/ + + // callbacks + add: function() {}, + remove: function() {}, + enable: function() {}, + disable: function() {}, + click: function() {}, + hide: function() {}, + show: function() {}, + load: function() {}, + + // CSS classes + navClass: 'ui-tabs-nav', + selectedClass: 'ui-tabs-selected', + disabledClass: 'ui-tabs-disabled', + containerClass: 'ui-tabs-container', + hideClass: 'ui-tabs-hide', + loadingClass: 'ui-tabs-loading' + + }, options); + + this.tabify(true); + + // save instance for later + var uuid = 'instance-' + $.ui.tabs.prototype.count++; + $.ui.tabs.instances[uuid] = this; + this.source['UI_TABS_UUID'] = uuid; + + }; + + // static + $.ui.tabs.instances = {}; + + $.extend($.ui.tabs.prototype, { + animating: false, + count: 0, + tabify: function(init) { + + this.$tabs = $('a:first-child', this.source); + this.$containers = $([]); + + var self = this, o = this.options; + + this.$tabs.each(function(i, a) { + // inline tab + if (a.hash && a.hash.replace('#', '')) { // safari 2 reports '#' for an empty hash + self.$containers = self.$containers.add(a.hash); + } + // remote tab + else { + var id = a.title && a.title.replace(/\s/g, '_') || o.hashPrefix + (self.count + 1) + '-' + (i + 1), url = a.href; + a.href = '#' + id; + a.url = url; + self.$containers = self.$containers.add( + $('#' + id)[0] || $('
') + .insertAfter( self.$containers[i - 1] || self.source ) + ); + } + }); + + if (init) { + + // Try to retrieve initial tab from fragment identifier in url if present, + // otherwise try to find selected class attribute on
  • . + this.$tabs.each(function(i, a) { + if (location.hash) { + if (a.hash == location.hash) { + o.initial = i; + // prevent page scroll to fragment + //if (($.browser.msie || $.browser.opera) && !o.remote) { + if ($.browser.msie || $.browser.opera) { + var $toShow = $(location.hash), toShowId = $toShow.attr('id'); + $toShow.attr('id', ''); + setTimeout(function() { + $toShow.attr('id', toShowId); // restore id + }, 500); + } + scrollTo(0, 0); + return false; // break + } + } else if ( $(a).parents('li:eq(0)').is('li.' + o.selectedClass) ) { + o.initial = i; + return false; // break + } + }); + + // attach necessary classes for styling if not present + $(this.source).is('.' + o.navClass) || $(this.source).addClass(o.navClass); + this.$containers.each(function() { + var $this = $(this); + $this.is('.' + o.containerClass) || $this.addClass(o.containerClass); + }); + + // highlight tab accordingly + var $lis = $('li', this.source); + this.$containers.addClass(o.hideClass); + $lis.removeClass(o.selectedClass); + if (!o.unselected) { + this.$containers.slice(o.initial, o.initial + 1).show(); + $lis.slice(o.initial, o.initial + 1).addClass(o.selectedClass); + } + + // trigger load of initial tab is remote tab + if (this.$tabs[o.initial].url) { + this.load(o.initial + 1, this.$tabs[o.initial].url); + if (o.cache) { + this.$tabs[o.initial].url = null; // if loaded once do not load them again + } + } + + // disabled tabs + for (var i = 0, position; position = o.disabled[i]; i++) { + this.disable(position); + } + + } + + // setup animations + var showAnim = {}, hideAnim = {}, showSpeed = o.fxShowSpeed || o.fxSpeed, + hideSpeed = o.fxHideSpeed || o.fxSpeed; + if (o.fxSlide || o.fxFade) { + if (o.fxSlide) { + showAnim['height'] = 'show'; + hideAnim['height'] = 'hide'; + } + if (o.fxFade) { + showAnim['opacity'] = 'show'; + hideAnim['opacity'] = 'hide'; + } + } else { + if (o.fxShow) { + showAnim = o.fxShow; + } else { // use some kind of animation to prevent browser scrolling to the tab + showAnim['min-width'] = 0; // avoid opacity, causes flicker in Firefox + showSpeed = 1; // as little as 1 is sufficient + } + if (o.fxHide) { + hideAnim = o.fxHide; + } else { // use some kind of animation to prevent browser scrolling to the tab + hideAnim['min-width'] = 0; // avoid opacity, causes flicker in Firefox + hideSpeed = 1; // as little as 1 is sufficient + } + } + + // callbacks + var click = o.click, hide = o.hide, show = o.show; + + // reset some styles to maintain print style sheets etc. + var resetCSS = { display: '', overflow: '', height: '' }; + if (!$.browser.msie) { // not in IE to prevent ClearType font issue + resetCSS['opacity'] = ''; + } + + // hide a tab, animation prevents browser scrolling to fragment + function hideTab(clicked, $hide, $show) { + $hide.animate(hideAnim, hideSpeed, function() { // + $hide.addClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc. + hide(clicked, $show, $hide[0]); + if ($show) { + showTab(clicked, $hide, $show); + } + }); + } + + // show a tab, animation prevents browser scrolling to fragment + function showTab(clicked, $hide, $show) { + // show next tab + if (!(o.fxSlide || o.fxFade || o.fxShow)) { + $show.css('display', 'block'); // prevent occasionally occuring flicker in Firefox cause by gap between showing and hiding the tab containers + } + $show.animate(showAnim, showSpeed, function() { + $show.removeClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc. + if ($.browser.msie) { + $hide[0].style.filter = ''; + $show[0].style.filter = ''; + } + show(clicked, $show[0], $hide[0]); + self.animating = false; + }); + + } + + // switch a tab + function switchTab(clicked, $hide, $show) { + /*if (o.bookmarkable && trueClick) { // add to history only if true click occured, not a triggered click + $.ajaxHistory.update(clicked.hash); + }*/ + $(clicked).parents('li:eq(0)').addClass(o.selectedClass) + .siblings().removeClass(o.selectedClass); + hideTab(clicked, $hide, $show); + } + + // tab click handler + function tabClick(e) { + + //var trueClick = e.clientX; // add to history only if true click occured, not a triggered click + var $li = $(this).parents('li:eq(0)'), $hide = self.$containers.filter(':visible'), $show = $(this.hash); + + // if tab may be closed + if (o.toggle && !$li.is('.' + o.disabledClass) && !self.animating) { + if ($li.is('.' + o.selectedClass)) { + $li.removeClass(o.selectedClass); + hideTab(this, $hide); + this.blur(); + return false; + } else if (!$hide.length) { + $li.addClass(o.selectedClass); + showTab(this, $hide, $show); + this.blur(); + return false; + } + } + + // If tab is already selected or disabled, animation is still running or click callback + // returns false stop here. + // Check if click handler returns false last so that it is not executed for a disabled tab! + if ($li.is('.' + o.selectedClass + ', .' + o.disabledClass) + || self.animating || click(this, $show[0], $hide[0]) === false) { + this.blur(); + return false; + } + + self.animating = true; + + // show new tab + if ($show.length) { + + // prevent scrollbar scrolling to 0 and than back in IE7, happens only if bookmarking/history is enabled + /*if ($.browser.msie && o.bookmarkable) { + var showId = this.hash.replace('#', ''); + $show.attr('id', ''); + setTimeout(function() { + $show.attr('id', showId); // restore id + }, 0); + }*/ + + if (this.url) { // remote tab + var a = this; + self.load(self.$tabs.index(this) + 1, this.url, function() { + switchTab(a, $hide, $show); + }); + if (o.cache) { + this.url = null; // if loaded once do not load them again + } + } else { + switchTab(this, $hide, $show); + } + + // Set scrollbar to saved position - need to use timeout with 0 to prevent browser scroll to target of hash + /*var scrollX = window.pageXOffset || document.documentElement && document.documentElement.scrollLeft || document.body.scrollLeft || 0; + var scrollY = window.pageYOffset || document.documentElement && document.documentElement.scrollTop || document.body.scrollTop || 0; + setTimeout(function() { + scrollTo(scrollX, scrollY); + }, 0);*/ + + } else { + throw 'jQuery UI Tabs: Mismatching fragment identifier.'; + } + + this.blur(); // prevent IE from keeping other link focussed when using the back button + + //return o.bookmarkable && !!trueClick; // convert trueClick == undefined to Boolean required in IE + return false; + + } + + // attach click event, avoid duplicates from former tabifying + this.$tabs.unbind(o.event, tabClick).bind(o.event, tabClick); + + }, + add: function(url, text, position) { + if (url && text) { + var o = this.options; + position = position || this.$tabs.length; // append by default + if (position >= this.$tabs.length) { + var method = 'insertAfter'; + position = this.$tabs.length; + } else { + var method = 'insertBefore'; + } + if (url.indexOf('#') == 0) { // ajax container is created by tabify automatically + var $container = $(url); + // try to find an existing element before creating a new one + ($container.length && $container || $('
    ')) + [method](this.$containers[position - 1]); + } + $('
  • ' + text + '
  • ') + [method](this.$tabs.slice(position - 1, position).parents('li:eq(0)')); + this.tabify(); + o.add(this.$tabs[position - 1], this.$containers[position - 1]); // callback + } else { + throw 'jQuery UI Tabs: Not enough arguments to add tab.'; + } + }, + remove: function(position) { + if (position && position.constructor == Number) { + this.$tabs.slice(position - 1, position).parents('li:eq(0)').remove(); + this.$containers.slice(position - 1, position).remove(); + this.tabify(); + } + this.options.remove(); // callback + }, + enable: function(position) { + var $li = this.$tabs.slice(position - 1, position).parents('li:eq(0)'), o = this.options; + $li.removeClass(o.disabledClass); + if ($.browser.safari) { // fix disappearing tab after enabling in Safari... TODO check Safari 3 + $li.animate({ opacity: 1 }, 1, function() { + $li.css({ opacity: '' }); + }); + } + o.enable(this.$tabs[position - 1], this.$containers[position - 1]); // callback + }, + disable: function(position) { + var $li = this.$tabs.slice(position - 1, position).parents('li:eq(0)'), o = this.options; + if ($.browser.safari) { // fix opacity of tab after disabling in Safari... TODO check Safari 3 + $li.animate({ opacity: 0 }, 1, function() { + $li.css({ opacity: '' }); + }); + } + $li.addClass(this.options.disabledClass); + o.disable(this.$tabs[position - 1], this.$containers[position - 1]); // callback + }, + click: function(position) { + this.$tabs.slice(position - 1, position).trigger('click'); + }, + load: function(position, url, callback) { + var self = this, + o = this.options, + $a = this.$tabs.slice(position - 1, position).addClass(o.loadingClass), + $span = $('span', $a), + text = $span.html(); + + // shift arguments + if (url && url.constructor == Function) { + callback = url; + } + + // set new URL + if (url) { + $a[0].url = url; + } + + // load + if (o.spinner) { + $span.html('' + o.spinner + ''); + } + setTimeout(function() { // timeout is again required in IE, "wait" for id being restored + $($a[0].hash).load(url, function() { + if (o.spinner) { + $span.html(text); + } + $a.removeClass(o.loadingClass); + // This callback is needed because the switch has to take place after loading + // has completed. + if (callback && callback.constructor == Function) { + callback(); + } + o.load(self.$tabs[position - 1], self.$containers[position - 1]); // callback + }); + }, 0); + } + }); +})(jQuery);