jenkins-bot has submitted this change and it was merged. Change subject: Add feature: <tab>s that show up in every tab ......................................................................
Add feature: <tab>s that show up in every tab Using index="*" for a <tab> tag will now make it show up for every single tab. This is useful when nesting toggle boxes or dropdown menus inside tab menus. Also fixed a bug that made it impossible to use {{#tab:#1|cont}} syntax, because index="#1" would be set. Change-Id: Iff726f885bbd4b55d66dc0d2055e64eb7344cb4d --- M Tabs.body.php M ext.tabs.css M ext.tabs.js 3 files changed, 66 insertions(+), 40 deletions(-) Approvals: Joeytje50: Looks good to me, approved jenkins-bot: Verified diff --git a/Tabs.body.php b/Tabs.body.php index 7aa8d9f..7383443 100644 --- a/Tabs.body.php +++ b/Tabs.body.php @@ -66,42 +66,47 @@ } // Default value for the tab's given index: index attribute's value, or else the index of the tab with the same name as name attribute, or else the tab index if (!$nested) { - $index = 0; // indices do nothing for non-nested tabs, so don't even bother doing the computations. + $index = -1; // indices do nothing for non-nested tabs, so don't even bother doing the computations. } elseif (isset($attr['index']) && intval($attr['index']) <= count($names)) { $index = intval($attr['index']); // if the index is given, and it isn't greater than the current index + 1. - } elseif (isset($attr['name']) && array_search($attr['name'], $names) !== false) + } elseif (isset($attr['index']) && $attr['index'] == '*') { + $index = 0; //use wildcard index: this tab's contents shows up for every single tab; + //this makes it possible to have a dropdown box inside a <tabs> box, which shows up for every tab. + } elseif (isset($attr['name']) && array_search($attr['name'], $names) !== false) { $index = array_search($attr['name'], $names)+1; // if index is not defined, but the name is, use the index of the tabname. - else { + } else { $index = count($names)+1; // index of this tab in this scope. Plus one because tabs are 1-based, arrays are 0-based. } $classPrefix = ''; - if ($nested) // Note: This is defined seperately for toggleboxes, because of the different classes required. + if ($nested) {// Note: This is defined seperately for toggleboxes, because of the different classes required. $classPrefix .= "tabs-content tabs-content-$index"; - - if (!isset($attr['class'])) - $attr['class'] = $classPrefix; // only the prefix if no classes have been defined - else - $attr['class'] = trim("$classPrefix ".htmlspecialchars($attr['class'])); - - if (isset($names[$index-1])) {// if array $names already has a name defined at position $index, use that. - $name = $names[$index-1]; // minus 1 because tabs are 1-based, arrays 0-based. - } else {// otherwise, use the entered name, or the $index with a "Tab " prefix if it is not defined or empty. - $name = trim(isset($attr['name']) && $attr['name'] ? $attr['name'] : wfMessage('tabs-tab-label', $index)); } - + if (isset($attr['class'])) { + $attr['class'] = trim("$classPrefix ".htmlspecialchars($attr['class'])); + } else { + $attr['class'] = $classPrefix; // only the prefix if no classes have been defined + } + if ($index !== 0) { + if (isset($names[$index-1])) { // if array $names already has a name defined at position $index, use that. + $name = $names[$index-1]; // minus 1 because tabs are 1-based, arrays 0-based. + } else { // otherwise, use the entered name, or the $index with a "Tab " prefix if it is not defined or empty. + $name = trim(isset($attr['name']) && $attr['name'] ? $attr['name'] : wfMessage('tabs-tab-label', $index)); + } + } if (!$nested) { // This runs when the tab is not nested inside a <tabs> tag. $container = $this->renderBox($input, $attr, $parser); } else { // this runs when the tab is nested inside a <tabs> tag. - if (array_search($name, $names) === false) // append name if it's not already in the list. + if ($index !== 0 && array_search($name, $names) === false) {// append name if it's not already in the list. $names[] = $name; - - if (isset($attr['block'])) + } + if (isset($attr['block'])) { $ib = 'tabs-block '; - elseif (isset($attr['inline'])) + } elseif (isset($attr['inline'])) { $ib = 'tabs-inline '; - else + } else { $ib = ''; + } $attr['class'] = $ib.$attr['class']; $container = array( '', @@ -109,7 +114,10 @@ 'div', $this->getSafeAttrs($attr) ); - $parser->tabsData['labels'][intval($index)] = $name; // Store the index and the name so this can be used within the <tabs> hook to create labels + if ($index !== 0) { + // Store the index and the name so this can be used within the <tabs> hook to create labels + $parser->tabsData['labels'][intval($index)] = $name; + } } if ($input === null) return ''; // return empty string if the tag is self-closing. This can be used to pre-define tabs for referring to via the index later. @@ -265,7 +273,7 @@ /** * Renders parser function for simpler inline tab syntax ({{#tab:}}) * @param Parser $parser - * @param string $index A comma-seperated list of tab names or indices. Integers will always be interpreted as indices. + * @param string $index A comma-seperated list of tab names or indices. Integers prefixed with '#' will always be interpreted as indices. * @return string A converted list of <tab> tags, further to be processed by the parser. */ public function renderPf($parser, $index) { @@ -280,7 +288,7 @@ $index_i = isset($index[$i-1]) ? trim($index[$i-1]) : ''; if (preg_match('/^#\d+$/',$index_i) && intval(substr($index_i,1)) > 0) { //only assign an index if the attribute is just digits, preceded by # - $attr = "index=\"$index_i\""; + $attr = 'index="'.substr($index_i,1).'"'; $isname = false; } elseif ($index_i) { // only assign a name if the name attribute isn't just whitespace diff --git a/ext.tabs.css b/ext.tabs.css index 7329c3d..ebd5394 100644 --- a/ext.tabs.css +++ b/ext.tabs.css @@ -22,11 +22,15 @@ /** * This is for testing if the browser supports the :not() selector. !important is used to ensure this style doesn't change. - * The "sans-serif" ("without-serif") and "serif" fonts are used to indicate "sans" :not()-support or with. + * The "sans-serif" ("without-serif") and "serif" fonts are used to indicate :not()-support (so also :checked support, since those + * selectors gained support in almost every browser at the very same moment). "sans-serif" indicates no support; "serif" indicates :not() support. * This form is used as a "testcase" because it is hidden from view anyway, and always present when any <tab> or <tabs> tags are present. * The margin: 0px is to determine whether the browser supports the general sibling selector ~. If it doesn't, there is "no margin" for interactivity, so JS is not activated. */ -#tabs-inputform {font-family: sans-serif !important;margin: 0px !important;} +#tabs-inputform { + font-family: sans-serif !important; + margin: 0px !important; +} head~body #tabs-inputform {margin: 1px !important;} body:not(oldbrowser) #tabs-inputform {font-family: serif !important;} @@ -91,6 +95,15 @@ display: inline-block; vertical-align: bottom; } +.tabs-tabbox .tabs-content-0 { + display: inline-block; +} +.tabs-tabbox .tabs-block.tabs-content-0 { + display: block; +} +.tabs-tabbox .tabs-inline.tabs-content-0 { + display: inline; +} .tabs-plain > .tabs-label { border: 1px solid #AAA; border-radius: 8px; @@ -105,6 +118,7 @@ .tabs-togglebox > .tabs-container { display: inline-block; /* this is to make the box the minimal width it needs to be */ + width: inherit; padding: 0; border-radius: 8px; } diff --git a/ext.tabs.js b/ext.tabs.js index 2c11d88..5ed0c87 100644 --- a/ext.tabs.js +++ b/ext.tabs.js @@ -1,9 +1,13 @@ $(function() { - if ($('#tabs-inputform').css('font-family').replace(/["']/g,'') == 'sans-serif' && $('#tabs-inputform').css('margin') == '1px') { // Credit for this testing method: 2astalavista @ http://stackoverflow.com/a/21095568/1256925 + // The font will be sans-serif if the :not() property is supported. The margin will be 1px if the sibling selector is supported. + if ($('#tabs-inputform').css('font-family').replace(/["']/g,'') == 'sans-serif' && $('#tabs-inputform').css('margin') == '1px') { $(function() { $('body').addClass('tabs-oldbrowserscript'); // Make the unselected tabs hide when the browser loads this script - $('.tabs-label').click(function(e) { $('#'+$(this).attr('for')).click(); e.preventDefault(); return false; }); + $('.tabs-label').click(function(e) { + $('#'+$(this).attr('for')).click(); e.preventDefault(); + return false; + }); $('.tabs-input').each(function() { if (this.checked) $(this).addClass('checked'); // Adds checked class to each checked box }).change(function() { @@ -15,9 +19,9 @@ }); moveToHash(); }); - } else + } else { $(moveToHash); - + } /** * Imitates the normal feature in browsers to scroll to an id that has the same id as the url fragment/hash. * This makes it unnecessary to use actual ids on the tabs, which could cause the same id to occur twice in the same document. @@ -42,17 +46,17 @@ * Idea for the use of <detail> and <summary> based on http://stackoverflow.com/q/21357641/1256925 */ var nua = navigator.userAgent; - var is_android = ((nua.indexOf('Mozilla/5.0') > -1 && nua.indexOf('Android ') > -1 && nua.indexOf('AppleWebKit') > -1) && !(nua.indexOf('Chrome') > -1)); - if (is_android) { - function replaces() { //General replacement function for both tags - var tagName = $(this).is('.tabs-container') ? 'details' : 'summary'; //determine the required tag name - var $newNode = $('<'+tagName+'/>').html($(this).html()); - for (var i=0;i<this.attributes.length;i++) { //copy all attributes from the original element - if (this.attributes[i].nodeName === 'for') continue; //don't copy the label's for="" attribute, since it's not needed here. - $newNode.attr(this.attributes[i].nodeName, this.attributes[i].value); - } - return $newNode; + var is_android = (nua.indexOf('Mozilla/5.0') > -1 && nua.indexOf('Android ') > -1 && nua.indexOf('AppleWebKit') > -1 && nua.indexOf('Chrome') === -1); + function replaces() { //General replacement function for both tags + var tagName = $(this).is('.tabs-container') ? 'details' : 'summary'; //determine the required tag name + var $newNode = $('<'+tagName+'/>').html($(this).html()); + for (var i=0;i<this.attributes.length;i++) { //copy all attributes from the original element + if (this.attributes[i].nodeName === 'for') continue; //don't copy the label's for="" attribute, since it's not needed here. + $newNode.attr(this.attributes[i].nodeName, this.attributes[i].value); } + return $newNode; + } + if (is_android) { $('.tabs-togglebox .tabs-container').not('.tabs-dropdown .tabs-container').replaceWith(replaces); //do not select dropdowns, which already work in Android $('.tabs-togglebox .tabs-label').not('.tabs-dropdown .tabs-label').each(function() { if ($(this).prevAll('input').prop('checked')) { //preserve open state of the toggle box @@ -60,4 +64,4 @@ } }).replaceWith(replaces); //Run this *after* the .tabs-container has finished, otherwise all .tabs-label elements will be skipped. } -}); \ No newline at end of file +}); -- To view, visit https://gerrit.wikimedia.org/r/184126 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Iff726f885bbd4b55d66dc0d2055e64eb7344cb4d Gerrit-PatchSet: 3 Gerrit-Project: mediawiki/extensions/Tabs Gerrit-Branch: master Gerrit-Owner: Joeytje50 <joeytj...@gmail.com> Gerrit-Reviewer: Joeytje50 <joeytj...@gmail.com> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits