r82172 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r82171‎ | r82172 | r82173 >
Date:17:38, 15 February 2011
Author:80686
Status:deferred
Tags:
Comment:
new version 0.8, including jquery based treeview
Modified paths:
  • /trunk/extensions/SelectCategory/CHANGELOG (modified) (history)
  • /trunk/extensions/SelectCategory/SelectCategory.css (modified) (history)
  • /trunk/extensions/SelectCategory/SelectCategory.js (added) (history)
  • /trunk/extensions/SelectCategory/SelectCategoryFunctions.php (modified) (history)
  • /trunk/extensions/SelectCategory/images (added) (history)
  • /trunk/extensions/SelectCategory/images/treeview-default-line.gif (added) (history)
  • /trunk/extensions/SelectCategory/images/treeview-default.gif (added) (history)
  • /trunk/extensions/SelectCategory/jquery.treeview.css (added) (history)
  • /trunk/extensions/SelectCategory/jquery.treeview.js (added) (history)

Diff [purge]

Index: trunk/extensions/SelectCategory/SelectCategoryFunctions.php
@@ -30,10 +30,19 @@
3131 array(
3232 'rel' => 'stylesheet',
3333 'type' => 'text/css',
34 - 'href' => "$wgScriptPath/extensions/SelectCategory/SelectCategory.css"
 34+ 'href' => $wgScriptPath.'/extensions/SelectCategory/SelectCategory.css'
3535 )
3636 );
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+
3847 $m_skin =& $wgUser->getSkin();
3948
4049 # Get all categories from wiki:
@@ -64,7 +73,8 @@
6574 $m_pageObj->$m_place .= "\n$m_textBefore";
6675
6776 # 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">';
6979 foreach( $m_allCats as $m_cat => $m_depth ) {
7080 $checked = '';
7181 # See if the category was already added, so check it
@@ -74,38 +84,35 @@
7585 # Clean HTML Output:
7686 $category = htmlspecialchars( $m_cat );
7787
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 ) {
8290 # 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;';
8593 } else {
86 - $display = '';
 94+ $m_class = 'display:block;';
8795 }
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++;
9698 }
 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+ }
97104 # Clean names for text output
98105 $title = str_replace( '_', ' ', $category );
99106 $m_title = $wgTitle->newFromText( $category, NS_CATEGORY );
100107 # 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;
107111 } # 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+ }
110117
111118 # Print localised help string:
112119 $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 @@
1515 padding: .1em;
1616 }
1717
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;
2120 }
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
2421 + 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
2522 + application/octet-stream
Index: trunk/extensions/SelectCategory/CHANGELOG
@@ -1,3 +1,6 @@
 2+* v0.8
 3+ - using JQuery Treeview to collapse / expand branches
 4+
25 * v0.7dev
36 - Update to comply to the current MediaWiki core (Patch by Lambert Lum)
47 - 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

Follow-up revisions

RevisionCommit summaryAuthorDate
r82174Followup r82172...reedy18:33, 15 February 2011

Status & tagging log