Index: trunk/extensions/SelectCategory/SelectCategoryFunctions.php |
— | — | @@ -30,10 +30,19 @@ |
31 | 31 | array( |
32 | 32 | 'rel' => 'stylesheet', |
33 | 33 | 'type' => 'text/css', |
34 | | - 'href' => "$wgScriptPath/extensions/SelectCategory/SelectCategory.css" |
| 34 | + 'href' => $wgScriptPath.'/extensions/SelectCategory/SelectCategory.css' |
35 | 35 | ) |
36 | 36 | ); |
37 | | - |
| 37 | + $wgOut->addLink( |
| 38 | + array( |
| 39 | + 'rel' => 'stylesheet', |
| 40 | + 'type' => 'text/css', |
| 41 | + 'href' => $wgScriptPath.'/extensions/SelectCategory/jquery.treeview.css' |
| 42 | + ) |
| 43 | + ); |
| 44 | + $wgOut->addScript( '<script src="'.$wgScriptPath.'/extensions/SelectCategory/jquery.treeview.js" type="text/javascript"></script>' ); |
| 45 | + $wgOut->addScript( '<script src="'.$wgScriptPath.'/extensions/SelectCategory/SelectCategory.js" type="text/javascript"></script>' ); |
| 46 | + |
38 | 47 | $m_skin =& $wgUser->getSkin(); |
39 | 48 | |
40 | 49 | # Get all categories from wiki: |
— | — | @@ -64,7 +73,8 @@ |
65 | 74 | $m_pageObj->$m_place .= "\n$m_textBefore"; |
66 | 75 | |
67 | 76 | # Begin list output, use <div> to enable custom formatting |
68 | | - $m_pageObj->$m_place .= '<div id="SelectCategoryList">'; |
| 77 | + $m_level = 0; |
| 78 | + $m_pageObj->$m_place .= '<ul id="SelectCategoryList">'; |
69 | 79 | foreach( $m_allCats as $m_cat => $m_depth ) { |
70 | 80 | $checked = ''; |
71 | 81 | # See if the category was already added, so check it |
— | — | @@ -74,38 +84,35 @@ |
75 | 85 | # Clean HTML Output: |
76 | 86 | $category = htmlspecialchars( $m_cat ); |
77 | 87 | |
78 | | - # Calculate indention of subcategories |
79 | | - $indention = 0; |
80 | | - for( $i = 0; $i <= $m_depth; $i++ ) { |
81 | | - $indention = 15 * $i; |
| 88 | + # iterate through levels and adjust divs accordingly |
| 89 | + while( $m_level < $m_depth ) { |
82 | 90 | # Collapse subcategories after reaching the configured MaxLevel |
83 | | - if( $i > $wgSelectCategoryMaxLevel ) { |
84 | | - $display = 'display:none;'; |
| 91 | + if( $m_level >= ( $wgSelectCategoryMaxLevel - 1 ) ) { |
| 92 | + $m_class = 'display:none;'; |
85 | 93 | } else { |
86 | | - $display = ''; |
| 94 | + $m_class = 'display:block;'; |
87 | 95 | } |
88 | | - # Check if we have reached the MaxLevel [-] or not [+] |
89 | | - if( $i == $wgSelectCategoryMaxLevel ) { |
90 | | - $sign = '[+]'; |
91 | | - } else { |
92 | | -# $sign = '[−]'; |
93 | | - } |
94 | | - # Check if there are more subcategories |
95 | | -# if( $m_allCats[] > $m_depth ) |
| 96 | + $m_pageObj->$m_place .= '<ul style="'.$m_class.'">'."\n"; |
| 97 | + $m_level++; |
96 | 98 | } |
| 99 | + if( $m_level == $m_depth ) $m_pageObj->$m_place .= '</li>'."\n"; |
| 100 | + while( $m_level > $m_depth ) { |
| 101 | + $m_pageObj->$m_place .= '</ul></li>'."\n"; |
| 102 | + $m_level--; |
| 103 | + } |
97 | 104 | # Clean names for text output |
98 | 105 | $title = str_replace( '_', ' ', $category ); |
99 | 106 | $m_title = $wgTitle->newFromText( $category, NS_CATEGORY ); |
100 | 107 | # Output the actual checkboxes, indented |
101 | | - $m_pageObj->$m_place .= ' |
102 | | - <div id="sc_'.$category.'" style="'.$display.'"> |
103 | | - <span style="padding-left:'.$indention.'px; width:10px; overflow:hidden;">'.$sign.'</span> |
104 | | - <input type="checkbox" name="SelectCategoryList[]" value="'.$category.'" class="checkbox" '.$checked.' /> |
105 | | - '.$m_skin->link( $m_title, $title ).' |
106 | | - </div>'; |
| 108 | + $m_pageObj->$m_place .= '<li><input type="checkbox" name="SelectCategoryList[]" value="'.$category.'" class="checkbox" '.$checked.' />'.$m_skin->link( $m_title, $title )."\n"; |
| 109 | + # set id for next level |
| 110 | + $m_level_id = 'sc_'.$m_cat; |
107 | 111 | } # End walking through cats (foreach) |
108 | | - # End of list output |
109 | | - $m_pageObj->$m_place .= '</div>'; |
| 112 | + # End of list output - close all remaining divs |
| 113 | + while( $m_level > -1 ) { |
| 114 | + $m_pageObj->$m_place .= '</li></ul>'."\n"; |
| 115 | + $m_level--; |
| 116 | + } |
110 | 117 | |
111 | 118 | # Print localised help string: |
112 | 119 | $m_pageObj->$m_place .= "<!-- SelectCategory end -->\n"; |
Index: trunk/extensions/SelectCategory/jquery.treeview.css |
— | — | @@ -0,0 +1,74 @@ |
| 2 | +.treeview, .treeview ul {
|
| 3 | + padding: 0;
|
| 4 | + margin: 0;
|
| 5 | + list-style: none; |
| 6 | +} |
| 7 | + |
| 8 | +.treeview ul { |
| 9 | + background-color: white; |
| 10 | + margin-top: 4px; |
| 11 | +}
|
| 12 | +
|
| 13 | +.treeview .hitarea {
|
| 14 | + background: url(images/treeview-default.gif) -64px -25px no-repeat;
|
| 15 | + height: 16px;
|
| 16 | + width: 16px;
|
| 17 | + margin-left: -16px;
|
| 18 | + float: left;
|
| 19 | + cursor: pointer;
|
| 20 | +}
|
| 21 | +/* fix for IE6 */
|
| 22 | +* html .hitarea {
|
| 23 | + display: inline;
|
| 24 | + float:none; |
| 25 | +}
|
| 26 | +
|
| 27 | +.treeview li {
|
| 28 | + margin: 0;
|
| 29 | + padding: 3px 0pt 3px 16px;
|
| 30 | +}
|
| 31 | +
|
| 32 | +.treeview a.selected {
|
| 33 | + background-color: #eee;
|
| 34 | +}
|
| 35 | +
|
| 36 | +#treecontrol { margin: 1em 0; display: none; }
|
| 37 | +
|
| 38 | +.treeview .hover { color: red; cursor: pointer; }
|
| 39 | +
|
| 40 | +.treeview li { background: url(images/treeview-default-line.gif) 0 0 no-repeat; }
|
| 41 | +.treeview li.collapsable, .treeview li.expandable { background-position: 0 -176px; }
|
| 42 | +
|
| 43 | +.treeview .expandable-hitarea { background-position: -80px -3px; }
|
| 44 | +
|
| 45 | +.treeview li.last { background-position: 0 -1766px }
|
| 46 | +.treeview li.lastCollapsable, .treeview li.lastExpandable { background-image: url(images/treeview-default.gif); } |
| 47 | +.treeview li.lastCollapsable { background-position: 0 -111px } |
| 48 | +.treeview li.lastExpandable { background-position: -32px -67px }
|
| 49 | +
|
| 50 | +.treeview div.lastCollapsable-hitarea, .treeview div.lastExpandable-hitarea { background-position: 0; } |
| 51 | +
|
| 52 | +.treeview-red li { background-image: url(images/treeview-red-line.gif); }
|
| 53 | +.treeview-red .hitarea, .treeview-red li.lastCollapsable, .treeview-red li.lastExpandable { background-image: url(images/treeview-red.gif); }
|
| 54 | +
|
| 55 | +.treeview-black li { background-image: url(images/treeview-black-line.gif); }
|
| 56 | +.treeview-black .hitarea, .treeview-black li.lastCollapsable, .treeview-black li.lastExpandable { background-image: url(images/treeview-black.gif); }
|
| 57 | +
|
| 58 | +.treeview-gray li { background-image: url(images/treeview-gray-line.gif); }
|
| 59 | +.treeview-gray .hitarea, .treeview-gray li.lastCollapsable, .treeview-gray li.lastExpandable { background-image: url(images/treeview-gray.gif); }
|
| 60 | +
|
| 61 | +.treeview-famfamfam li { background-image: url(images/treeview-famfamfam-line.gif); }
|
| 62 | +.treeview-famfamfam .hitarea, .treeview-famfamfam li.lastCollapsable, .treeview-famfamfam li.lastExpandable { background-image: url(images/treeview-famfamfam.gif); }
|
| 63 | +
|
| 64 | +.treeview .placeholder {
|
| 65 | + background: url(images/ajax-loader.gif) 0 0 no-repeat;
|
| 66 | + height: 16px;
|
| 67 | + width: 16px;
|
| 68 | + display: block;
|
| 69 | +}
|
| 70 | +
|
| 71 | +.filetree li { padding: 3px 0 2px 16px; }
|
| 72 | +.filetree span.folder, .filetree span.file { padding: 1px 0 1px 16px; display: block; }
|
| 73 | +.filetree span.folder { background: url(images/folder.gif) 0 0 no-repeat; }
|
| 74 | +.filetree li.expandable span.folder { background: url(images/folder-closed.gif) 0 0 no-repeat; }
|
| 75 | +.filetree span.file { background: url(images/file.gif) 0 0 no-repeat; }
|
Index: trunk/extensions/SelectCategory/jquery.treeview.js |
— | — | @@ -0,0 +1,256 @@ |
| 2 | +/* |
| 3 | + * Treeview 1.4.1 - jQuery plugin to hide and show branches of a tree |
| 4 | + * |
| 5 | + * http://bassistance.de/jquery-plugins/jquery-plugin-treeview/ |
| 6 | + * http://docs.jquery.com/Plugins/Treeview |
| 7 | + * |
| 8 | + * Copyright (c) 2007 Jörn Zaefferer |
| 9 | + * |
| 10 | + * Dual licensed under the MIT and GPL licenses: |
| 11 | + * http://www.opensource.org/licenses/mit-license.php |
| 12 | + * http://www.gnu.org/licenses/gpl.html |
| 13 | + * |
| 14 | + * Revision: $Id: jquery.treeview.js 5759 2008-07-01 07:50:28Z joern.zaefferer $ |
| 15 | + * |
| 16 | + */ |
| 17 | + |
| 18 | +;(function($j) { |
| 19 | + |
| 20 | + // TODO rewrite as a widget, removing all the extra plugins |
| 21 | + $j.extend($j.fn, { |
| 22 | + swapClass: function(c1, c2) { |
| 23 | + var c1Elements = this.filter('.' + c1); |
| 24 | + this.filter('.' + c2).removeClass(c2).addClass(c1); |
| 25 | + c1Elements.removeClass(c1).addClass(c2); |
| 26 | + return this; |
| 27 | + }, |
| 28 | + replaceClass: function(c1, c2) { |
| 29 | + return this.filter('.' + c1).removeClass(c1).addClass(c2).end(); |
| 30 | + }, |
| 31 | + hoverClass: function(className) { |
| 32 | + className = className || "hover"; |
| 33 | + return this.hover(function() { |
| 34 | + $j(this).addClass(className); |
| 35 | + }, function() { |
| 36 | + $j(this).removeClass(className); |
| 37 | + }); |
| 38 | + }, |
| 39 | + heightToggle: function(animated, callback) { |
| 40 | + animated ? |
| 41 | + this.animate({ height: "toggle" }, animated, callback) : |
| 42 | + this.each(function(){ |
| 43 | + jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ](); |
| 44 | + if(callback) |
| 45 | + callback.apply(this, arguments); |
| 46 | + }); |
| 47 | + }, |
| 48 | + heightHide: function(animated, callback) { |
| 49 | + if (animated) { |
| 50 | + this.animate({ height: "hide" }, animated, callback); |
| 51 | + } else { |
| 52 | + this.hide(); |
| 53 | + if (callback) |
| 54 | + this.each(callback); |
| 55 | + } |
| 56 | + }, |
| 57 | + prepareBranches: function(settings) { |
| 58 | + if (!settings.prerendered) { |
| 59 | + // mark last tree items |
| 60 | + this.filter(":last-child:not(ul)").addClass(CLASSES.last); |
| 61 | + // collapse whole tree, or only those marked as closed, anyway except those marked as open |
| 62 | + this.filter((settings.collapsed ? "" : "." + CLASSES.closed) + ":not(." + CLASSES.open + ")").find(">ul").hide(); |
| 63 | + } |
| 64 | + // return all items with sublists |
| 65 | + return this.filter(":has(>ul)"); |
| 66 | + }, |
| 67 | + applyClasses: function(settings, toggler) { |
| 68 | + // TODO use event delegation |
| 69 | + this.filter(":has(>ul):not(:has(>a))").find(">span").unbind("click.treeview").bind("click.treeview", function(event) { |
| 70 | + // don't handle click events on children, eg. checkboxes |
| 71 | + if ( this == event.target ) |
| 72 | + toggler.apply($j(this).next()); |
| 73 | + }).add( $j("a", this) ).hoverClass(); |
| 74 | + |
| 75 | + if (!settings.prerendered) { |
| 76 | + // handle closed ones first |
| 77 | + this.filter(":has(>ul:hidden)") |
| 78 | + .addClass(CLASSES.expandable) |
| 79 | + .replaceClass(CLASSES.last, CLASSES.lastExpandable); |
| 80 | + |
| 81 | + // handle open ones |
| 82 | + this.not(":has(>ul:hidden)") |
| 83 | + .addClass(CLASSES.collapsable) |
| 84 | + .replaceClass(CLASSES.last, CLASSES.lastCollapsable); |
| 85 | + |
| 86 | + // create hitarea if not present |
| 87 | + var hitarea = this.find("div." + CLASSES.hitarea); |
| 88 | + if (!hitarea.length) |
| 89 | + hitarea = this.prepend("<div class=\"" + CLASSES.hitarea + "\"/>").find("div." + CLASSES.hitarea); |
| 90 | + hitarea.removeClass().addClass(CLASSES.hitarea).each(function() { |
| 91 | + var classes = ""; |
| 92 | + $j.each($j(this).parent().attr("class").split(" "), function() { |
| 93 | + classes += this + "-hitarea "; |
| 94 | + }); |
| 95 | + $j(this).addClass( classes ); |
| 96 | + }) |
| 97 | + } |
| 98 | + |
| 99 | + // apply event to hitarea |
| 100 | + this.find("div." + CLASSES.hitarea).click( toggler ); |
| 101 | + }, |
| 102 | + treeview: function(settings) { |
| 103 | + |
| 104 | + settings = $j.extend({ |
| 105 | + cookieId: "treeview" |
| 106 | + }, settings); |
| 107 | + |
| 108 | + if ( settings.toggle ) { |
| 109 | + var callback = settings.toggle; |
| 110 | + settings.toggle = function() { |
| 111 | + return callback.apply($j(this).parent()[0], arguments); |
| 112 | + }; |
| 113 | + } |
| 114 | + |
| 115 | + // factory for treecontroller |
| 116 | + function treeController(tree, control) { |
| 117 | + // factory for click handlers |
| 118 | + function handler(filter) { |
| 119 | + return function() { |
| 120 | + // reuse toggle event handler, applying the elements to toggle |
| 121 | + // start searching for all hitareas |
| 122 | + toggler.apply( $j("div." + CLASSES.hitarea, tree).filter(function() { |
| 123 | + // for plain toggle, no filter is provided, otherwise we need to check the parent element |
| 124 | + return filter ? $j(this).parent("." + filter).length : true; |
| 125 | + }) ); |
| 126 | + return false; |
| 127 | + }; |
| 128 | + } |
| 129 | + // click on first element to collapse tree |
| 130 | + $j("a:eq(0)", control).click( handler(CLASSES.collapsable) ); |
| 131 | + // click on second to expand tree |
| 132 | + $j("a:eq(1)", control).click( handler(CLASSES.expandable) ); |
| 133 | + // click on third to toggle tree |
| 134 | + $j("a:eq(2)", control).click( handler() ); |
| 135 | + } |
| 136 | + |
| 137 | + // handle toggle event |
| 138 | + function toggler() { |
| 139 | + $j(this) |
| 140 | + .parent() |
| 141 | + // swap classes for hitarea |
| 142 | + .find(">.hitarea") |
| 143 | + .swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea ) |
| 144 | + .swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea ) |
| 145 | + .end() |
| 146 | + // swap classes for parent li |
| 147 | + .swapClass( CLASSES.collapsable, CLASSES.expandable ) |
| 148 | + .swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable ) |
| 149 | + // find child lists |
| 150 | + .find( ">ul" ) |
| 151 | + // toggle them |
| 152 | + .heightToggle( settings.animated, settings.toggle ); |
| 153 | + if ( settings.unique ) { |
| 154 | + $j(this).parent() |
| 155 | + .siblings() |
| 156 | + // swap classes for hitarea |
| 157 | + .find(">.hitarea") |
| 158 | + .replaceClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea ) |
| 159 | + .replaceClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea ) |
| 160 | + .end() |
| 161 | + .replaceClass( CLASSES.collapsable, CLASSES.expandable ) |
| 162 | + .replaceClass( CLASSES.lastCollapsable, CLASSES.lastExpandable ) |
| 163 | + .find( ">ul" ) |
| 164 | + .heightHide( settings.animated, settings.toggle ); |
| 165 | + } |
| 166 | + } |
| 167 | + this.data("toggler", toggler); |
| 168 | + |
| 169 | + function serialize() { |
| 170 | + function binary(arg) { |
| 171 | + return arg ? 1 : 0; |
| 172 | + } |
| 173 | + var data = []; |
| 174 | + branches.each(function(i, e) { |
| 175 | + data[i] = $j(e).is(":has(>ul:visible)") ? 1 : 0; |
| 176 | + }); |
| 177 | + $j.cookie(settings.cookieId, data.join(""), settings.cookieOptions ); |
| 178 | + } |
| 179 | + |
| 180 | + function deserialize() { |
| 181 | + var stored = $j.cookie(settings.cookieId); |
| 182 | + if ( stored ) { |
| 183 | + var data = stored.split(""); |
| 184 | + branches.each(function(i, e) { |
| 185 | + $j(e).find(">ul")[ parseInt(data[i]) ? "show" : "hide" ](); |
| 186 | + }); |
| 187 | + } |
| 188 | + } |
| 189 | + |
| 190 | + // add treeview class to activate styles |
| 191 | + this.addClass("treeview"); |
| 192 | + |
| 193 | + // prepare branches and find all tree items with child lists |
| 194 | + var branches = this.find("li").prepareBranches(settings); |
| 195 | + |
| 196 | + switch(settings.persist) { |
| 197 | + case "cookie": |
| 198 | + var toggleCallback = settings.toggle; |
| 199 | + settings.toggle = function() { |
| 200 | + serialize(); |
| 201 | + if (toggleCallback) { |
| 202 | + toggleCallback.apply(this, arguments); |
| 203 | + } |
| 204 | + }; |
| 205 | + deserialize(); |
| 206 | + break; |
| 207 | + case "location": |
| 208 | + var current = this.find("a").filter(function() { |
| 209 | + return this.href.toLowerCase() == location.href.toLowerCase(); |
| 210 | + }); |
| 211 | + if ( current.length ) { |
| 212 | + // TODO update the open/closed classes |
| 213 | + var items = current.addClass("selected").parents("ul, li").add( current.next() ).show(); |
| 214 | + if (settings.prerendered) { |
| 215 | + // if prerendered is on, replicate the basic class swapping |
| 216 | + items.filter("li") |
| 217 | + .swapClass( CLASSES.collapsable, CLASSES.expandable ) |
| 218 | + .swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable ) |
| 219 | + .find(">.hitarea") |
| 220 | + .swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea ) |
| 221 | + .swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea ); |
| 222 | + } |
| 223 | + } |
| 224 | + break; |
| 225 | + } |
| 226 | + |
| 227 | + branches.applyClasses(settings, toggler); |
| 228 | + |
| 229 | + // if control option is set, create the treecontroller and show it |
| 230 | + if ( settings.control ) { |
| 231 | + treeController(this, settings.control); |
| 232 | + $j(settings.control).show(); |
| 233 | + } |
| 234 | + |
| 235 | + return this; |
| 236 | + } |
| 237 | + }); |
| 238 | + |
| 239 | + // classes used by the plugin |
| 240 | + // need to be styled via external stylesheet, see first example |
| 241 | + $j.treeview = {}; |
| 242 | + var CLASSES = ($j.treeview.classes = { |
| 243 | + open: "open", |
| 244 | + closed: "closed", |
| 245 | + expandable: "expandable", |
| 246 | + expandableHitarea: "expandable-hitarea", |
| 247 | + lastExpandableHitarea: "lastExpandable-hitarea", |
| 248 | + collapsable: "collapsable", |
| 249 | + collapsableHitarea: "collapsable-hitarea", |
| 250 | + lastCollapsableHitarea: "lastCollapsable-hitarea", |
| 251 | + lastCollapsable: "lastCollapsable", |
| 252 | + lastExpandable: "lastExpandable", |
| 253 | + last: "last", |
| 254 | + hitarea: "hitarea" |
| 255 | + }); |
| 256 | + |
| 257 | +})(jQuery); |
\ No newline at end of file |
Index: trunk/extensions/SelectCategory/SelectCategory.css |
— | — | @@ -14,9 +14,6 @@ |
15 | 15 | padding: .1em; |
16 | 16 | } |
17 | 17 | |
18 | | -ul#SelectCategoryList { |
19 | | - list-style-image: none; |
20 | | - list-style-type: none; |
| 18 | +ul#SelectCategoryList, #SelectCategoryList ul { |
| 19 | + list-style: none outside none !important; |
21 | 20 | } |
22 | | - |
23 | | - |
Index: trunk/extensions/SelectCategory/images/treeview-default.gif |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes on: trunk/extensions/SelectCategory/images/treeview-default.gif |
___________________________________________________________________ |
Added: svn:mime-type |
24 | 21 | + application/octet-stream |
Index: trunk/extensions/SelectCategory/images/treeview-default-line.gif |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes on: trunk/extensions/SelectCategory/images/treeview-default-line.gif |
___________________________________________________________________ |
Added: svn:mime-type |
25 | 22 | + application/octet-stream |
Index: trunk/extensions/SelectCategory/CHANGELOG |
— | — | @@ -1,3 +1,6 @@ |
| 2 | +* v0.8 |
| 3 | + - using JQuery Treeview to collapse / expand branches |
| 4 | + |
2 | 5 | * v0.7dev |
3 | 6 | - Update to comply to the current MediaWiki core (Patch by Lambert Lum) |
4 | 7 | - Changed the user interface to use checkboxes instead of scrolling lists |
Index: trunk/extensions/SelectCategory/SelectCategory.js |
— | — | @@ -0,0 +1,5 @@ |
| 2 | +$j( document ).ready( function() { |
| 3 | + $j( "#SelectCategoryList" ).treeview( { |
| 4 | + collapsed: true |
| 5 | + }); |
| 6 | +} ); |
\ No newline at end of file |