| Index: trunk/extensions/CategoryTree/CategoryTree.js |
| — | — | @@ -34,7 +34,7 @@ |
| 35 | 35 | lnk.title= categoryTreeCollapseMsg; |
| 36 | 36 | lnk.onclick= function() { categoryTreeCollapseNode(cat, options, lnk) } |
| 37 | 37 | |
| 38 | | - if (lnk.className != "CategoryTreeLoaded") { |
| | 38 | + if (!lnk.className.match(/(^| )CategoryTreeLoaded($| )/)) { |
| 39 | 39 | categoryTreeLoadNode(cat, options, lnk, div); |
| 40 | 40 | } |
| 41 | 41 | } |
| — | — | @@ -58,40 +58,52 @@ |
| 59 | 59 | categoryTreeLoadChildren(cat, options, div) |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | | - function categoryTreeEncodeOptions(options) { |
| 63 | | - var opt = ""; |
| | 62 | + function categoryTreeEncodeValue(value) { |
| | 63 | + switch (typeof value) { |
| | 64 | + case 'function': |
| | 65 | + throw new Error("categoryTreeEncodeValue encountered a function"); |
| | 66 | + break; |
| 64 | 67 | |
| 65 | | - for (k in options) { |
| 66 | | - v = options[k]; |
| 67 | | - |
| 68 | | - switch (typeof v) { |
| 69 | 68 | case 'string': |
| 70 | | - v = '"' + v.replace(/([\\"'])/g, "\\$1") + '"'; |
| | 69 | + s = '"' + value.replace(/([\\"'])/g, "\\$1") + '"'; |
| 71 | 70 | break; |
| 72 | 71 | |
| 73 | 72 | case 'number': |
| 74 | 73 | case 'boolean': |
| 75 | 74 | case 'null': |
| 76 | | - v = String(v); |
| | 75 | + s = String(value); |
| 77 | 76 | break; |
| 78 | 77 | |
| 79 | 78 | case 'object': |
| 80 | | - if ( !v ) v = 'null'; |
| 81 | | - else throw new Error("categoryTreeLoadChildren can not encode complex types"); |
| | 79 | + if ( !value ) { |
| | 80 | + s = 'null'; |
| | 81 | + } |
| | 82 | + else if (typeof value.length === 'number' && !(value.propertyIsEnumerable('length'))) { |
| | 83 | + s = ''; |
| | 84 | + for (i = 0; i<value.length; i++) { |
| | 85 | + v = value[i]; |
| | 86 | + if ( s!='' ) s += ', '; |
| | 87 | + s += categoryTreeEncodeValue( v ); |
| | 88 | + } |
| | 89 | + s = '[' + s + ']'; |
| | 90 | + } |
| | 91 | + else { |
| | 92 | + s = ''; |
| | 93 | + for (k in value) { |
| | 94 | + v = value[k]; |
| | 95 | + if ( s!='' ) s += ', '; |
| | 96 | + s += categoryTreeEncodeValue( k ); |
| | 97 | + s += ': '; |
| | 98 | + s += categoryTreeEncodeValue( v ); |
| | 99 | + } |
| | 100 | + s = '{' + s + '}'; |
| | 101 | + } |
| 82 | 102 | break; |
| 83 | | - |
| 84 | 103 | default: |
| 85 | | - throw new Error("categoryTreeLoadChildren encountered strange variable type " + (typeof v)); |
| | 104 | + throw new Error("categoryTreeEncodeValue encountered strange variable type " + (typeof value)); |
| 86 | 105 | } |
| 87 | 106 | |
| 88 | | - if ( opt != "" ) opt += ", "; |
| 89 | | - opt += k; |
| 90 | | - opt += ":"; |
| 91 | | - opt += v; |
| 92 | | - } |
| 93 | | - |
| 94 | | - opt = "{"+opt+"}"; |
| 95 | | - return opt; |
| | 107 | + return s; |
| 96 | 108 | } |
| 97 | 109 | |
| 98 | 110 | function categoryTreeLoadChildren(cat, options, div) { |
| — | — | @@ -130,6 +142,6 @@ |
| 131 | 143 | div.innerHTML= result; |
| 132 | 144 | } |
| 133 | 145 | |
| 134 | | - var opt = categoryTreeEncodeOptions(options); |
| | 146 | + var opt = categoryTreeEncodeValue(options); |
| 135 | 147 | sajax_do_call( "efCategoryTreeAjaxWrapper", [cat, opt, 'json'] , f ); |
| 136 | 148 | } |
| Index: trunk/extensions/CategoryTree/CategoryTreeFunctions.php |
| — | — | @@ -33,12 +33,60 @@ |
| 34 | 34 | $this->mOptions['mode'] = self::decodeMode( $this->mOptions['mode'] ); |
| 35 | 35 | $this->mOptions['hideprefix'] = self::decodeHidePrefix( $this->mOptions['hideprefix'] ); |
| 36 | 36 | $this->mOptions['showcount'] = self::decodeBoolean( $this->mOptions['showcount'] ); |
| | 37 | + $this->mOptions['namespaces'] = self::decodeNamespaces( $this->mOptions['namespaces'] ); |
| | 38 | + |
| | 39 | + if ( $this->mOptions['namespaces'] ) { |
| | 40 | + # automatically adjust mode to match namespace filter |
| | 41 | + if ( sizeof( $this->mOptions['namespaces'] ) === 1 |
| | 42 | + && $this->mOptions['namespaces'][0] == NS_CATEGORY ) { |
| | 43 | + $this->mOptions['mode'] = CT_MODE_CATEGORIES; |
| | 44 | + } else if ( !in_array( NS_IMAGE, $this->mOptions['namespaces'] ) ) { |
| | 45 | + $this->mOptions['mode'] = CT_MODE_PAGES; |
| | 46 | + } else { |
| | 47 | + $this->mOptions['mode'] = CT_MODE_ALL; |
| | 48 | + } |
| | 49 | + } |
| 37 | 50 | } |
| 38 | 51 | |
| 39 | 52 | function getOption( $name ) { |
| 40 | 53 | return $this->mOptions[$name]; |
| 41 | 54 | } |
| 42 | 55 | |
| | 56 | + static function decodeNamespaces( $nn ) { |
| | 57 | + global $wgContLang; |
| | 58 | + |
| | 59 | + if ( !$nn ) |
| | 60 | + return false; |
| | 61 | + |
| | 62 | + if ( !is_array($nn) ) |
| | 63 | + $nn = preg_split( '![\s#:|]+!', $nn ); |
| | 64 | + |
| | 65 | + $namespaces = array(); |
| | 66 | + |
| | 67 | + foreach ( $nn as $n ) { |
| | 68 | + if ( is_int( $n ) ) { |
| | 69 | + $ns = $n; |
| | 70 | + } |
| | 71 | + else { |
| | 72 | + $n = trim( $n ); |
| | 73 | + if ( $n === '' ) continue; |
| | 74 | + |
| | 75 | + $lower = strtolower( $n ); |
| | 76 | + |
| | 77 | + if ( is_numeric($n) ) $ns = (int)$n; |
| | 78 | + elseif ( $n == '-' || $n == '_' || $n == '*' || $lower == 'main' ) $ns = NS_MAIN; |
| | 79 | + else $ns = $wgContLang->getNsIndex( $n ); |
| | 80 | + } |
| | 81 | + |
| | 82 | + if ( is_int( $ns ) ) { |
| | 83 | + $namespaces[] = $ns; |
| | 84 | + } |
| | 85 | + } |
| | 86 | + |
| | 87 | + sort( $namespaces ); # get elements into canonical order |
| | 88 | + return $namespaces; |
| | 89 | + } |
| | 90 | + |
| 43 | 91 | static function decodeMode( $mode ) { |
| 44 | 92 | global $wgCategoryTreeDefaultOptions; |
| 45 | 93 | |
| — | — | @@ -199,6 +247,7 @@ |
| 200 | 248 | $key = ""; |
| 201 | 249 | |
| 202 | 250 | foreach ( $this->mOptions as $k => $v ) { |
| | 251 | + if ( is_array( $v ) ) $v = implode( '|', $v ); |
| 203 | 252 | $key .= $k . ':' . $v . ';'; |
| 204 | 253 | } |
| 205 | 254 | |
| — | — | @@ -341,11 +390,19 @@ |
| 342 | 391 | |
| 343 | 392 | |
| 344 | 393 | $mode = $this->getOption('mode'); |
| | 394 | + $namespaces = $this->getOption('namespaces'); |
| 345 | 395 | |
| 346 | | - #namespace filter. Should be configurable |
| 347 | | - if ( $mode == CT_MODE_ALL ) $nsmatch = ''; |
| 348 | | - else if ( $mode == CT_MODE_PAGES ) $nsmatch = ' AND cat.page_namespace != ' . NS_IMAGE; |
| 349 | | - else $nsmatch = ' AND cat.page_namespace = ' . NS_CATEGORY; |
| | 396 | + #namespace filter. |
| | 397 | + if ( $namespaces ) { |
| | 398 | + #NOTE: we assume that the $namespaces array contains only integers! |
| | 399 | + if ( sizeof( $namespaces ) === 1 ) $nsmatch = ' AND cat.page_namespace = ' . $namespaces[0] . ' '; |
| | 400 | + else $nsmatch = ' AND cat.page_namespace IN ( ' . implode( ', ', $namespaces ) . ') '; |
| | 401 | + } |
| | 402 | + else { |
| | 403 | + if ( $mode == CT_MODE_ALL ) $nsmatch = ''; |
| | 404 | + else if ( $mode == CT_MODE_PAGES ) $nsmatch = ' AND cat.page_namespace != ' . NS_IMAGE; |
| | 405 | + else $nsmatch = ' AND cat.page_namespace = ' . NS_CATEGORY; |
| | 406 | + } |
| 350 | 407 | |
| 351 | 408 | #additional stuff to be used if "transaltion" by interwiki-links is desired |
| 352 | 409 | $transFields = ''; |
| — | — | @@ -551,13 +608,15 @@ |
| 552 | 609 | |
| 553 | 610 | $linkattr[ 'class' ] = "CategoryTreeToggle"; |
| 554 | 611 | |
| 555 | | - if ( $count === 0 ) { |
| | 612 | + /*if ( $count === 0 ) { |
| 556 | 613 | $tag = 'span'; |
| 557 | 614 | $txt = wfMsgNoTrans( 'categorytree-empty-bullet' ); |
| 558 | 615 | } |
| 559 | | - else if ( $children == 0 || $loadchildren ) { |
| | 616 | + else*/ |
| | 617 | + if ( $children == 0 || $loadchildren ) { |
| 560 | 618 | $tag = 'a'; |
| 561 | | - $txt = wfMsgNoTrans( 'categorytree-expand-bullet' ); |
| | 619 | + if ( $count === 0 ) $txt = wfMsgNoTrans( 'categorytree-empty-bullet' ); |
| | 620 | + else $txt = wfMsgNoTrans( 'categorytree-expand-bullet' ); |
| 562 | 621 | $linkattr[ 'onclick' ] = "this.href='javascript:void(0)'; categoryTreeExpandNode('".Xml::escapeJsString($key)."',".$this->getOptionsAsJsStructure().",this);"; |
| 563 | 622 | # Don't load this message for ajax requests, so that we don't have to initialise $wgLang |
| 564 | 623 | $linkattr[ 'title' ] = $this->mIsAjaxRequest ? '##LOAD##' : wfMsgNoTrans('categorytree-expand'); |
| — | — | @@ -593,7 +652,19 @@ |
| 594 | 653 | $s .= "\n\t\t"; |
| 595 | 654 | $s .= Xml::openElement( 'div', array( 'class' => 'CategoryTreeChildren', 'style' => $children > 0 ? "display:block" : "display:none" ) ); |
| 596 | 655 | |
| 597 | | - if ( $children > 0 && !$loadchildren) $s .= $this->renderChildren( $title, $children ); |
| | 656 | + if ( $ns == NS_CATEGORY && $children > 0 && !$loadchildren) { |
| | 657 | + $children = $this->renderChildren( $title, $children ); |
| | 658 | + if ( $children == '' ) { |
| | 659 | + $s .= Xml::openElement( 'i', array( 'class' => 'CategoryTreeNotice' ) ); |
| | 660 | + if ( $mode == CT_MODE_CATEGORIES ) $s .= wfMsgExt( 'categorytree-no-subcategories', 'parsemag'); |
| | 661 | + else if ( $mode == CT_MODE_PAGES ) $s .= wfMsgExt( 'categorytree-no-pages', 'parsemag'); |
| | 662 | + else $s .= wfMsgExt( 'categorytree-nothing-found', 'parsemag'); |
| | 663 | + $s .= Xml::closeElement( 'i' ); |
| | 664 | + } else { |
| | 665 | + $s .= $children; |
| | 666 | + } |
| | 667 | + } |
| | 668 | + |
| 598 | 669 | $s .= Xml::closeElement( 'div' ); |
| 599 | 670 | $s .= Xml::closeElement( 'div' ); |
| 600 | 671 | |
| Index: trunk/extensions/CategoryTree/CategoryTree.php |
| — | — | @@ -67,7 +67,7 @@ |
| 68 | 68 | $wgCategoryTreeDefaultOptions['mode'] = NULL; # will be set to $wgCategoryTreeDefaultMode in efCategoryTree(); compatibility quirk |
| 69 | 69 | $wgCategoryTreeDefaultOptions['hideprefix'] = NULL; # will be set to $wgCategoryTreeDefaultMode in efCategoryTree(); compatibility quirk |
| 70 | 70 | $wgCategoryTreeDefaultOptions['showcount'] = false; |
| 71 | | -#TODO: hideprefix: always, never, catonly, catonly_if_onlycat |
| | 71 | +$wgCategoryTreeDefaultOptions['namespaces'] = false; # false means "no filter" |
| 72 | 72 | |
| 73 | 73 | $wgCategoryTreeCategoryPageMode = CT_MODE_CATEGORIES; |
| 74 | 74 | $wgCategoryTreeCategoryPageOptions = array(); #Options to be used for category pages |
| — | — | @@ -115,7 +115,6 @@ |
| 116 | 116 | $wgHooks['ArticleFromTitle'][] = 'efCategoryTreeArticleFromTitle'; |
| 117 | 117 | $wgHooks['LanguageGetMagic'][] = 'efCategoryTreeGetMagic'; |
| 118 | 118 | |
| 119 | | - |
| 120 | 119 | /** |
| 121 | 120 | * register Ajax function |
| 122 | 121 | */ |