Ticket #5618: 5618.diff

File 5618.diff, 37.3 KB (added by mdawaffe, 4 years ago)
  • wp-includes/js/jquery/ui.tabs.js

     
     1/* 
     2 * Tabs 3 - New Wave Tabs 
     3 * 
     4 * Copyright (c) 2007 Klaus Hartl (stilbuero.de) 
     5 * Dual licensed under the MIT (MIT-LICENSE.txt) 
     6 * and GPL (GPL-LICENSE.txt) licenses. 
     7 */ 
     8 
     9(function($) { 
     10 
     11    // if the UI scope is not availalable, add it 
     12    $.ui = $.ui || {}; 
     13 
     14    // tabs initialization 
     15    $.fn.tabs = function(initial, options) { 
     16        if (initial && initial.constructor == Object) { // shift arguments 
     17            options = initial; 
     18            initial = null; 
     19        } 
     20        options = options || {}; 
     21 
     22        initial = initial && initial.constructor == Number && --initial || 0; 
     23 
     24        return this.each(function() { 
     25            new $.ui.tabs(this, $.extend(options, { initial: initial })); 
     26        }); 
     27    }; 
     28 
     29    // other chainable tabs methods 
     30    $.each(['Add', 'Remove', 'Enable', 'Disable', 'Click', 'Load', 'Href'], function(i, method) { 
     31        $.fn['tabs' + method] = function() { 
     32            var args = arguments; 
     33            return this.each(function() { 
     34                var instance = $.ui.tabs.getInstance(this); 
     35                instance[method.toLowerCase()].apply(instance, args); 
     36            }); 
     37        }; 
     38    }); 
     39    $.fn.tabsSelected = function() { 
     40        var selected = -1; 
     41        if (this[0]) { 
     42            var instance = $.ui.tabs.getInstance(this[0]), 
     43                $lis = $('li', this); 
     44            selected = $lis.index( $lis.filter('.' + instance.options.selectedClass)[0] ); 
     45        } 
     46        return selected >= 0 ? ++selected : -1; 
     47    }; 
     48 
     49    // tabs class 
     50    $.ui.tabs = function(el, options) { 
     51 
     52        this.source = el; 
     53 
     54        this.options = $.extend({ 
     55 
     56            // basic setup 
     57            initial: 0, 
     58            event: 'click', 
     59            disabled: [], 
     60            cookie: null, // pass options object as expected by cookie plugin: { expires: 7, path: '/', domain: 'jquery.com', secure: true } 
     61            // TODO bookmarkable: $.ajaxHistory ? true : false, 
     62            unselected: false, 
     63            unselect: options.unselected ? true : false, 
     64 
     65            // Ajax 
     66            spinner: 'Loading…', 
     67            cache: false, 
     68            idPrefix: 'ui-tabs-', 
     69            ajaxOptions: {}, 
     70 
     71            // animations 
     72            /*fxFade: null, 
     73            fxSlide: null, 
     74            fxShow: null, 
     75            fxHide: null,*/ 
     76            fxSpeed: 'normal', 
     77            /*fxShowSpeed: null, 
     78            fxHideSpeed: null,*/ 
     79 
     80            // callbacks 
     81            add: function() {}, 
     82            remove: function() {}, 
     83            enable: function() {}, 
     84            disable: function() {}, 
     85            click: function() {}, 
     86            hide: function() {}, 
     87            show: function() {}, 
     88            load: function() {}, 
     89             
     90            // templates 
     91            tabTemplate: '<li><a href="#{href}"><span>#{text}</span></a></li>', 
     92            panelTemplate: '<div></div>', 
     93 
     94            // CSS classes 
     95            navClass: 'ui-tabs-nav', 
     96            selectedClass: 'ui-tabs-selected', 
     97            unselectClass: 'ui-tabs-unselect', 
     98            disabledClass: 'ui-tabs-disabled', 
     99            panelClass: 'ui-tabs-panel', 
     100            hideClass: 'ui-tabs-hide', 
     101            loadingClass: 'ui-tabs-loading' 
     102 
     103        }, options); 
     104 
     105        this.options.event += '.ui-tabs'; // namespace event 
     106        this.options.cookie = $.cookie && $.cookie.constructor == Function && this.options.cookie; 
     107 
     108        // save instance for later 
     109        $.data(el, $.ui.tabs.INSTANCE_KEY, this); 
     110         
     111        // create tabs 
     112        this.tabify(true); 
     113    }; 
     114 
     115    // static 
     116    $.ui.tabs.INSTANCE_KEY = 'ui_tabs_instance'; 
     117    $.ui.tabs.getInstance = function(el) { 
     118        return $.data(el, $.ui.tabs.INSTANCE_KEY); 
     119    }; 
     120 
     121    // instance methods 
     122    $.extend($.ui.tabs.prototype, { 
     123        tabId: function(a) { 
     124            return a.title ? a.title.replace(/\s/g, '_') 
     125                : this.options.idPrefix + $.data(a); 
     126        }, 
     127        tabify: function(init) { 
     128 
     129            this.$lis = $('li:has(a[href])', this.source); 
     130            this.$tabs = this.$lis.map(function() { return $('a', this)[0] }); 
     131            this.$panels = $([]); 
     132             
     133            var self = this, o = this.options; 
     134             
     135            this.$tabs.each(function(i, a) { 
     136                // inline tab 
     137                if (a.hash && a.hash.replace('#', '')) { // Safari 2 reports '#' for an empty hash 
     138                    self.$panels = self.$panels.add(a.hash); 
     139                } 
     140                // remote tab 
     141                else if ($(a).attr('href') != '#') { // prevent loading the page itself if href is just "#" 
     142                    $.data(a, 'href', a.href); 
     143                    var id = self.tabId(a); 
     144                    a.href = '#' + id; 
     145                    self.$panels = self.$panels.add( 
     146                        $('#' + id)[0] || $(o.panelTemplate).attr('id', id).addClass(o.panelClass) 
     147                            .insertAfter( self.$panels[i - 1] || self.source ) 
     148                    ); 
     149                } 
     150                // invalid tab href 
     151                else { 
     152                    o.disabled.push(i + 1); 
     153                } 
     154            }); 
     155 
     156            if (init) { 
     157 
     158                // attach necessary classes for styling if not present 
     159                $(this.source).hasClass(o.navClass) || $(this.source).addClass(o.navClass); 
     160                this.$panels.each(function() { 
     161                    var $this = $(this); 
     162                    $this.hasClass(o.panelClass) || $this.addClass(o.panelClass); 
     163                }); 
     164                 
     165                // disabled tabs 
     166                for (var i = 0, position; position = o.disabled[i]; i++) { 
     167                    this.disable(position); 
     168                } 
     169                 
     170                // Try to retrieve initial tab: 
     171                // 1. from fragment identifier in url if present 
     172                // 2. from cookie 
     173                // 3. from selected class attribute on <li> 
     174                // 4. otherwise use given initial argument 
     175                // 5. check if tab is disabled 
     176                this.$tabs.each(function(i, a) { 
     177                    if (location.hash) { 
     178                        if (a.hash == location.hash) { 
     179                            o.initial = i; 
     180                            // prevent page scroll to fragment 
     181                            //if (($.browser.msie || $.browser.opera) && !o.remote) { 
     182                            if ($.browser.msie || $.browser.opera) { 
     183                                var $toShow = $(location.hash), toShowId = $toShow.attr('id'); 
     184                                $toShow.attr('id', ''); 
     185                                setTimeout(function() { 
     186                                    $toShow.attr('id', toShowId); // restore id 
     187                                }, 500); 
     188                            } 
     189                            scrollTo(0, 0); 
     190                            return false; // break 
     191                        } 
     192                    } else if (o.cookie) { 
     193                        o.initial = parseInt($.cookie( $.ui.tabs.INSTANCE_KEY + $.data(self.source) )) || 0; 
     194                        return false; // break 
     195                    } else if ( self.$lis.eq(i).hasClass(o.selectedClass) ) { 
     196                        o.initial = i; 
     197                        return false; // break 
     198                    } 
     199                }); 
     200                var n = this.$lis.length; 
     201                while (this.$lis.eq(o.initial).hasClass(o.disabledClass) && n) { 
     202                    o.initial = ++o.initial < this.$lis.length ? o.initial : 0; 
     203                    n--; 
     204                } 
     205                if (!n) { // all tabs disabled, set option unselected to true 
     206                    o.unselected = o.unselect = true; 
     207                } 
     208 
     209                // highlight selected tab 
     210                this.$panels.addClass(o.hideClass); 
     211                this.$lis.removeClass(o.selectedClass); 
     212                if (!o.unselected) { 
     213                    this.$panels.eq(o.initial).show().removeClass(o.hideClass); // use show and remove class to show in any case no matter how it has been hidden before 
     214                    this.$lis.eq(o.initial).addClass(o.selectedClass); 
     215                } 
     216 
     217                // load if remote tab 
     218                var href = !o.unselected && $.data(this.$tabs[o.initial], 'href'); 
     219                if (href) { 
     220                    this.load(o.initial + 1, href); 
     221                } 
     222                 
     223                // disable click if event is configured to something else 
     224                if (!/^click/.test(o.event)) { 
     225                    this.$tabs.bind('click', function(e) { e.preventDefault(); }); 
     226                } 
     227 
     228            } 
     229 
     230            // setup animations 
     231            var showAnim = {}, showSpeed = o.fxShowSpeed || o.fxSpeed, 
     232                hideAnim = {}, hideSpeed = o.fxHideSpeed || o.fxSpeed; 
     233            if (o.fxSlide || o.fxFade) { 
     234                if (o.fxSlide) { 
     235                    showAnim['height'] = 'show'; 
     236                    hideAnim['height'] = 'hide'; 
     237                } 
     238                if (o.fxFade) { 
     239                    showAnim['opacity'] = 'show'; 
     240                    hideAnim['opacity'] = 'hide'; 
     241                } 
     242            } else { 
     243                if (o.fxShow) { 
     244                    showAnim = o.fxShow; 
     245                } else { // use some kind of animation to prevent browser scrolling to the tab 
     246                    showAnim['min-width'] = 0; // avoid opacity, causes flicker in Firefox 
     247                    showSpeed = 1; // as little as 1 is sufficient 
     248                } 
     249                if (o.fxHide) { 
     250                    hideAnim = o.fxHide; 
     251                } else { // use some kind of animation to prevent browser scrolling to the tab 
     252                    hideAnim['min-width'] = 0; // avoid opacity, causes flicker in Firefox 
     253                    hideSpeed = 1; // as little as 1 is sufficient 
     254                } 
     255            } 
     256 
     257            // reset some styles to maintain print style sheets etc. 
     258            var resetCSS = { display: '', overflow: '', height: '' }; 
     259            if (!$.browser.msie) { // not in IE to prevent ClearType font issue 
     260                resetCSS['opacity'] = ''; 
     261            } 
     262 
     263            // Hide a tab, animation prevents browser scrolling to fragment, 
     264            // $show is optional. 
     265            function hideTab(clicked, $hide, $show) { 
     266                $hide.animate(hideAnim, hideSpeed, function() { // 
     267                    $hide.addClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc. 
     268                    if ($.browser.msie && hideAnim['opacity']) { 
     269                        $hide[0].style.filter = ''; 
     270                    } 
     271                    o.hide(clicked, $hide[0], $show && $show[0] || null); 
     272                    if ($show) { 
     273                        showTab(clicked, $show, $hide); 
     274                    } 
     275                }); 
     276            } 
     277 
     278            // Show a tab, animation prevents browser scrolling to fragment, 
     279            // $hide is optional 
     280            function showTab(clicked, $show, $hide) { 
     281                if (!(o.fxSlide || o.fxFade || o.fxShow)) { 
     282                    $show.css('display', 'block'); // prevent occasionally occuring flicker in Firefox cause by gap between showing and hiding the tab panels 
     283                } 
     284                $show.animate(showAnim, showSpeed, function() { 
     285                    $show.removeClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc. 
     286                    if ($.browser.msie && showAnim['opacity']) { 
     287                        $show[0].style.filter = ''; 
     288                    } 
     289                    o.show(clicked, $show[0], $hide && $hide[0] || null); 
     290                }); 
     291            } 
     292 
     293            // switch a tab 
     294            function switchTab(clicked, $li, $hide, $show) { 
     295                /*if (o.bookmarkable && trueClick) { // add to history only if true click occured, not a triggered click 
     296                    $.ajaxHistory.update(clicked.hash); 
     297                }*/ 
     298                $li.addClass(o.selectedClass) 
     299                    .siblings().removeClass(o.selectedClass); 
     300                hideTab(clicked, $hide, $show); 
     301            } 
     302 
     303            // attach tab event handler, unbind to avoid duplicates from former tabifying... 
     304            this.$tabs.unbind(o.event).bind(o.event, function() { 
     305 
     306                //var trueClick = e.clientX; // add to history only if true click occured, not a triggered click 
     307                var $li = $(this).parents('li:eq(0)'), 
     308                    $hide = self.$panels.filter(':visible'), 
     309                    $show = $(this.hash); 
     310 
     311                // If tab is already selected and not unselectable or tab disabled or click callback returns false stop here. 
     312                // Check if click handler returns false last so that it is not executed for a disabled tab! 
     313                if (($li.hasClass(o.selectedClass) && !o.unselect) || $li.hasClass(o.disabledClass) 
     314                    || o.click(this, $show[0], $hide[0]) === false) { 
     315                    this.blur(); 
     316                    return false; 
     317                } 
     318                 
     319                if (o.cookie) { 
     320                    $.cookie($.ui.tabs.INSTANCE_KEY + $.data(self.source), self.$tabs.index(this), o.cookie); 
     321                } 
     322                     
     323                // if tab may be closed 
     324                if (o.unselect) { 
     325                    if ($li.hasClass(o.selectedClass)) { 
     326                        $li.removeClass(o.selectedClass); 
     327                        self.$panels.stop(); 
     328                        hideTab(this, $hide); 
     329                        this.blur(); 
     330                        return false; 
     331                    } else if (!$hide.length) { 
     332                        self.$panels.stop(); 
     333                        if ($.data(this, 'href')) { // remote tab 
     334                            var a = this; 
     335                            self.load(self.$tabs.index(this) + 1, $.data(this, 'href'), function() { 
     336                                $li.addClass(o.selectedClass).addClass(o.unselectClass); 
     337                                showTab(a, $show); 
     338                            }); 
     339                        } else { 
     340                            $li.addClass(o.selectedClass).addClass(o.unselectClass); 
     341                            showTab(this, $show); 
     342                        } 
     343                        this.blur(); 
     344                        return false; 
     345                    } 
     346                } 
     347 
     348                // stop possibly running animations 
     349                self.$panels.stop(); 
     350 
     351                // show new tab 
     352                if ($show.length) { 
     353 
     354                    // prevent scrollbar scrolling to 0 and than back in IE7, happens only if bookmarking/history is enabled 
     355                    /*if ($.browser.msie && o.bookmarkable) { 
     356                        var showId = this.hash.replace('#', ''); 
     357                        $show.attr('id', ''); 
     358                        setTimeout(function() { 
     359                            $show.attr('id', showId); // restore id 
     360                        }, 0); 
     361                    }*/ 
     362 
     363                    if ($.data(this, 'href')) { // remote tab 
     364                        var a = this; 
     365                        self.load(self.$tabs.index(this) + 1, $.data(this, 'href'), function() { 
     366                            switchTab(a, $li, $hide, $show); 
     367                        }); 
     368                    } else { 
     369                        switchTab(this, $li, $hide, $show); 
     370                    } 
     371 
     372                    // Set scrollbar to saved position - need to use timeout with 0 to prevent browser scroll to target of hash 
     373                    /*var scrollX = window.pageXOffset || document.documentElement && document.documentElement.scrollLeft || document.body.scrollLeft || 0; 
     374                    var scrollY = window.pageYOffset || document.documentElement && document.documentElement.scrollTop || document.body.scrollTop || 0; 
     375                    setTimeout(function() { 
     376                        scrollTo(scrollX, scrollY); 
     377                    }, 0);*/ 
     378 
     379                } else { 
     380                    throw 'jQuery UI Tabs: Mismatching fragment identifier.'; 
     381                } 
     382 
     383                // Prevent IE from keeping other link focussed when using the back button 
     384                // and remove dotted border from clicked link. This is controlled in modern 
     385                // browsers via CSS, also blur removes focus from address bar in Firefox 
     386                // which can become a usability and annoying problem with tabsRotate. 
     387                if ($.browser.msie) { 
     388                    this.blur();  
     389                } 
     390 
     391                //return o.bookmarkable && !!trueClick; // convert trueClick == undefined to Boolean required in IE 
     392                return false; 
     393 
     394            }); 
     395 
     396        }, 
     397        add: function(url, text, position) { 
     398            if (url && text) { 
     399                position = position || this.$tabs.length; // append by default   
     400                 
     401                var o = this.options, 
     402                    $li = $(o.tabTemplate.replace(/#\{href\}/, url).replace(/#\{text\}/, text)); 
     403                 
     404                var id = url.indexOf('#') == 0 ? url.replace('#', '') : this.tabId( $('a:first-child', $li)[0] ); 
     405                 
     406                // try to find an existing element before creating a new one 
     407                var $panel = $('#' + id); 
     408                $panel = $panel.length && $panel 
     409                    || $(o.panelTemplate).attr('id', id).addClass(o.panelClass).addClass(o.hideClass); 
     410                if (position >= this.$lis.length) { 
     411                    $li.appendTo(this.source); 
     412                    $panel.appendTo(this.source.parentNode); 
     413                } else { 
     414                    $li.insertBefore(this.$lis[position - 1]); 
     415                    $panel.insertBefore(this.$panels[position - 1]); 
     416                } 
     417                 
     418                this.tabify(); 
     419                 
     420                if (this.$tabs.length == 1) { 
     421                     $li.addClass(o.selectedClass); 
     422                     $panel.removeClass(o.hideClass); 
     423                     var href = $.data(this.$tabs[0], 'href'); 
     424                     if (href) { 
     425                         this.load(position + 1, href); 
     426                     } 
     427                } 
     428                o.add(this.$tabs[position], this.$panels[position]); // callback 
     429            } else { 
     430                throw 'jQuery UI Tabs: Not enough arguments to add tab.'; 
     431            } 
     432        }, 
     433        remove: function(position) { 
     434            if (position && position.constructor == Number) {                 
     435                var o = this.options, $li = this.$lis.eq(position - 1).remove(), 
     436                    $panel = this.$panels.eq(position - 1).remove(); 
     437                     
     438                // If selected tab was removed focus tab to the right or 
     439                // tab to the left if last tab was removed. 
     440                if ($li.hasClass(o.selectedClass) && this.$tabs.length > 1) { 
     441                    this.click(position + (position < this.$tabs.length ? 1 : -1)); 
     442                } 
     443                this.tabify(); 
     444                o.remove($li.end()[0], $panel[0]); // callback 
     445            } 
     446        }, 
     447        enable: function(position) { 
     448            var o = this.options, $li = this.$lis.eq(position - 1); 
     449            $li.removeClass(o.disabledClass); 
     450            if ($.browser.safari) { // fix disappearing tab (that used opacity indicating disabling) after enabling in Safari 2... 
     451                $li.css('display', 'inline-block'); 
     452                setTimeout(function() { 
     453                    $li.css('display', 'block') 
     454                }, 0) 
     455            } 
     456            o.enable(this.$tabs[position - 1], this.$panels[position - 1]); // callback 
     457        }, 
     458        disable: function(position) { 
     459            var o = this.options;       
     460            this.$lis.eq(position - 1).addClass(o.disabledClass); 
     461            o.disable(this.$tabs[position - 1], this.$panels[position - 1]); // callback 
     462        }, 
     463        click: function(position) { 
     464            this.$tabs.eq(position - 1).trigger(this.options.event); 
     465        }, 
     466        load: function(position, url, callback) { 
     467            var self = this, o = this.options, 
     468                $a = this.$tabs.eq(position - 1), a = $a[0], $span = $('span', a); 
     469             
     470            // shift arguments 
     471            if (url && url.constructor == Function) { 
     472                callback = url; 
     473                url = null; 
     474            } 
     475 
     476            // set new URL or get existing 
     477            if (url) { 
     478                $.data(a, 'href', url); 
     479            } else { 
     480                url = $.data(a, 'href'); 
     481            } 
     482 
     483            // load 
     484            if (o.spinner) { 
     485                $.data(a, 'title', $span.html()); 
     486                $span.html('<em>' + o.spinner + '</em>'); 
     487            } 
     488            var finish = function() { 
     489                self.$tabs.filter('.' + o.loadingClass).each(function() { 
     490                    $(this).removeClass(o.loadingClass); 
     491                    if (o.spinner) { 
     492                        $('span', this).html( $.data(this, 'title') ); 
     493                    } 
     494                }); 
     495                self.xhr = null; 
     496            }; 
     497            var ajaxOptions = $.extend(o.ajaxOptions, { 
     498                url: url, 
     499                success: function(r) { 
     500                    $(a.hash).html(r); 
     501                    finish(); 
     502                    // This callback is required because the switch has to take  
     503                    // place after loading has completed. 
     504                    if (callback && callback.constructor == Function) { 
     505                        callback(); 
     506                    } 
     507                    if (o.cache) { 
     508                        $.removeData(a, 'href'); // if loaded once do not load them again 
     509                    } 
     510                    o.load(self.$tabs[position - 1], self.$panels[position - 1]); // callback 
     511                } 
     512            }); 
     513            if (this.xhr) { 
     514                // terminate pending requests from other tabs and restore title 
     515                this.xhr.abort(); 
     516                finish(); 
     517            } 
     518            $a.addClass(o.loadingClass); 
     519            setTimeout(function() { // timeout is again required in IE, "wait" for id being restored 
     520                self.xhr = $.ajax(ajaxOptions); 
     521            }, 0); 
     522             
     523        }, 
     524        href: function(position, href) { 
     525            $.data(this.$tabs.eq(position - 1)[0], 'href', href); 
     526        } 
     527    }); 
     528 
     529})(jQuery); 
  • wp-includes/js/wp-lists.js

     
    309309                if ( 'none' != s.addColor ) { 
    310310                        var b = e.css( 'background-color' ); 
    311311                        if ( b == 'transparent' ) { b = ''; } 
    312                          
    313                         $('#' + s.element).css('background-color', s.addColor).animate( { backgroundColor: '#fff' }, 300 ); 
     312                        e.css('background-color', s.addColor).animate( { backgroundColor: '#fff' }, 300 ); 
    314313                } 
    315314                list.each( function() { this.wpList.process( e ); } ); 
    316315                return e; 
     
    321320                e = $(e); 
    322321                if ( list.wpList && e.parents( '#' + list.id ).size() ) { return; } 
    323322                e.find(':input').each( function() { 
     323                        if ( $(this).parents('.form-no-clear').size() ) 
     324                                return; 
    324325                        var t = this.type.toLowerCase(); var tag = this.tagName.toLowerCase(); 
    325326                        if ( 'text' == t || 'password' == t || 'textarea' == tag ) { this.value = ''; } 
    326327                        else if ( 'checkbox' == t || 'radio' == t ) { this.checked = false; } 
  • wp-includes/script-loader.php

     
    6060                        'delText' => __('Are you sure you want to delete this %thing%?') 
    6161                ) ); 
    6262 
    63                 $this->add( 'wp-lists', '/wp-includes/js/wp-lists.js', array('jquery'), '20071101' ); 
     63                $this->add( 'wp-lists', '/wp-includes/js/wp-lists.js', array('jquery'), '20080109' ); 
    6464                $this->localize( 'wp-lists', 'wpListL10n', array( 
    6565                        'url' => get_option( 'siteurl' ) . '/wp-admin/admin-ajax.php' 
    6666                ) ); 
     
    8585                $this->add( 'schedule', '/wp-includes/js/jquery/jquery.schedule.js', array('jquery'), '20'); 
    8686                $this->add( 'thickbox', '/wp-includes/js/thickbox/thickbox.js', array('jquery'), '3.1'); 
    8787 
     88                $this->add( 'jquery-ui-tabs', '/wp-includes/js/jquery/ui.tabs.js', array('jquery'), '3' ); 
     89 
    8890                if ( is_admin() ) { 
    8991                        $this->add( 'ajaxcat', '/wp-admin/js/cat.js', array( 'wp-lists' ), '20071101' ); 
    9092                        $this->localize( 'ajaxcat', 'catL10n', array( 
     
    106108                        $this->add( 'admin-forms', '/wp-admin/js/forms.js', array('wp-lists'), '20080108' ); 
    107109                        $this->add( 'xfn', '/wp-admin/js/xfn.js', false, '3517' ); 
    108110                        $this->add( 'upload', '/wp-admin/js/upload.js', array('jquery'), '20070518' ); 
    109                         $this->add( 'post', '/wp-admin/js/post.js', array('suggest'), '20080102' ); 
     111                        $this->add( 'post', '/wp-admin/js/post.js', array('suggest', 'jquery-ui-tabs', 'wp-lists'), '20080109' ); 
    110112                        $this->localize( 'post', 'postL10n', array( 
    111113                                'tagsUsed' =>  __('Tags used on this post:'), 
    112114                                'add' => attribute_escape(__('Add')), 
     
    137139                                'saveText' => attribute_escape(__('Save &raquo;')), 
    138140                                'confirmText' => __("Are you sure you want to delete the file '%title%'?\nClick ok to delete or cancel to go back.") 
    139141                        ) ); 
    140                         $this->add( 'admin-widgets', '/wp-admin/js/widgets.js', array( 'interface' ), mt_rand() ); 
     142                        $this->add( 'admin-widgets', '/wp-admin/js/widgets.js', array( 'interface' ), '20080109' ); 
    141143                } 
    142144        } 
    143145 
  • wp-admin/admin-ajax.php

     
    157157        if ( !current_user_can( 'manage_categories' ) ) 
    158158                die('-1'); 
    159159        $names = explode(',', $_POST['newcat']); 
     160        if ( 0 > $parent = (int) $_POST['newcat_parent'] ) 
     161                $parent = 0; 
     162 
     163        $checked_categories = array_map( 'absint', (array) $_POST['post_category'] ); 
     164 
    160165        $x = new WP_Ajax_Response(); 
    161166        foreach ( $names as $cat_name ) { 
    162167                $cat_name = trim($cat_name); 
    163168                $category_nicename = sanitize_title($cat_name); 
    164169                if ( '' === $category_nicename ) 
    165170                        continue; 
    166                 $cat_id = wp_create_category( $cat_name ); 
    167                 $cat_name = wp_specialchars(stripslashes($cat_name)); 
     171                $cat_id = wp_create_category( $cat_name, $parent ); 
     172                $checked_categories[] = $cat_id; 
     173                if ( $parent ) // Do these all at once in a second 
     174                        continue; 
     175                $category = get_category( $cat_id ); 
     176                $category->_is_checked = true; 
     177                ob_start(); 
     178                        dropdown_categories( 0, $category ); 
     179                $data = ob_get_contents(); 
     180                ob_end_clean(); 
    168181                $x->add( array( 
    169182                        'what' => 'category', 
    170183                        'id' => $cat_id, 
    171                         'data' => "<li id='category-$cat_id'><label for='in-category-$cat_id' class='selectit'><input value='$cat_id' type='checkbox' checked='checked' name='post_category[]' id='in-category-$cat_id'/> $cat_name</label></li>", 
     184                        'data' => $data, 
    172185                        'position' => -1 
    173186                ) ); 
    174187        } 
     188        if ( $parent ) { // Foncy - replace the parent and all its children 
     189                $parent = get_category( $parent ); 
     190                ob_start(); 
     191                        dropdown_categories( 0, $parent ); 
     192                $data = ob_get_contents(); 
     193                ob_end_clean(); 
     194                $x->add( array( 
     195                        'what' => 'category', 
     196                        'id' => $parent->term_id, 
     197                        'old_id' => $parent->term_id, 
     198                        'data' => $data, 
     199                        'position' => -1 
     200                ) ); 
     201 
     202        } 
    175203        $x->send(); 
    176204        break; 
    177205case 'add-link-category' : // On the Fly 
  • wp-admin/wp-admin.css

     
    687687        height: 22px; 
    688688} 
    689689 
    690 #categorydiv ul { 
    691         list-style: none; 
    692         padding: 0; 
    693         margin-left: 10px; 
    694 } 
    695  
    696 #categorychecklist { 
    697         height: 12em; 
    698         overflow: auto; 
    699         margin-top: 8px; 
    700 } 
    701  
    702 #categorychecklist li { 
    703         margin: 0; 
    704         padding: 0; 
    705 } 
    706  
    707 #ajaxcat input { 
    708         border: 1px solid #ccc; 
    709 } 
    710  
    711690#your-profile #rich_editing { 
    712691        border: none; 
    713692        background: #fff; 
     
    737716        font-size: 22px; 
    738717} 
    739718 
    740  
    741  
    742 #newcat { 
    743         width: 120px; 
    744         margin-right: 5px; 
    745 } 
    746  
    747 input #catadd { 
    748         background: #a4a4a4; 
    749         border-bottom: 1px solid #898989; 
    750         border-left: 1px solid #bcbcbc; 
    751         border-right: 1px solid #898989; 
    752         border-top: 1px solid #bcbcbc; 
    753         color: #fff; 
    754         font-size: 10px; 
    755         padding: 0; 
    756         margin: 0; 
    757         font-weight: bold; 
    758         height: 20px; 
    759         margin-bottom: 2px; 
    760         text-align: center; 
    761         width: 37px; 
    762 } 
    763  
    764719#howto { 
    765720        font-size: 11px; 
    766721        margin: 0 5px; 
    767722        display: block; 
    768723} 
    769724 
    770 #jaxcat { 
    771         margin: 0; 
    772         padding: 0; 
    773 } 
    774  
    775725#ajax-response.alignleft { 
    776726        margin-left: 2em; 
    777727} 
     
    12791229        background-image:url(images/toggle-arrow.gif); 
    12801230        background-position: 4px 18px; 
    12811231} 
     1232 
     1233/* Categories */ 
     1234 
     1235#categorydiv #category-adder { 
     1236        margin-left: 120px; 
     1237        padding: 4px 0; 
     1238} 
     1239 
     1240#category-add input, #category-add select { 
     1241        width: 30%; 
     1242} 
     1243 
     1244#categorydiv ul#category-tabs { 
     1245        float: left; 
     1246        width: 120px; 
     1247        text-align: right; 
     1248        /* Negative margin for the sake of those without JS: all tabs display */ 
     1249        margin: 0 -120px 0 0; 
     1250        padding: 0; 
     1251} 
     1252 
     1253ul#category-tabs li { 
     1254        padding: 8px; 
     1255} 
     1256 
     1257ul#category-tabs li.ui-tabs-selected { 
     1258        background-color: #CEE1EF; 
     1259} 
     1260 
     1261div.ui-tabs-panel { 
     1262        margin: 0 0 0 120px; 
     1263        padding: .5em .9em; 
     1264        height: 12em; 
     1265        overflow: auto; 
     1266        border: 4px solid #CEE1EF; 
     1267} 
     1268 
     1269#categorydiv ul { 
     1270        list-style: none; 
     1271        padding: 0; 
     1272        margin: 0; 
     1273} 
     1274 
     1275#categorydiv ul.categorychecklist ul { 
     1276        margin-left: 18px; 
     1277} 
     1278 
     1279ul.categorychecklist li { 
     1280        margin: 0; 
     1281        padding: 0; 
     1282} 
     1283 
     1284/* Global classes */ 
     1285.wp-hidden-children .wp-hidden-child { display: none; } 
     1286.ui-tabs-hide { display: none; } 
  • wp-admin/includes/template.php

     
    118118                return strcasecmp( $cat1['cat_name'], $cat2['cat_name'] ); 
    119119} 
    120120 
    121 function get_nested_categories( $default = 0, $parent = 0 ) { 
     121function wp_set_checked_post_categories( $default = 0 ) { 
    122122        global $post_ID, $checked_categories; 
    123123 
    124124        if ( empty($checked_categories) ) { 
     
    134134                } 
    135135        } 
    136136 
    137         $cats = get_categories("parent=$parent&hide_empty=0&fields=ids"); 
     137} 
     138function get_nested_categories( $default = 0, $parent = 0 ) { 
     139        global $checked_categories; 
    138140 
    139         $result = array (); 
    140         if ( is_array( $cats ) ) { 
    141                 foreach ( $cats as $cat) { 
    142                         $result[$cat]['children'] = get_nested_categories( $default, $cat); 
    143                         $result[$cat]['cat_ID'] = $cat; 
    144                         $result[$cat]['checked'] = in_array( $cat, $checked_categories ); 
    145                         $result[$cat]['cat_name'] = get_the_category_by_ID( $cat); 
     141        wp_set_checked_post_categories( $default = 0 ); 
     142 
     143        if ( is_object($parent) ) { // Hack: if passed a category object, will return nested cats with parent as root 
     144                $root = array( 
     145                        'children' => get_nested_categories( $default, $parent->term_id ), 
     146                        'cat_ID' => $parent->term_id, 
     147                        'checked' => isset($parent->_is_checked) && $parent->_is_checked, 
     148                        'cat_name' => get_the_category_by_ID( $parent->term_id ) 
     149                ); 
     150                $result = array( $parent->term_id => $root ); 
     151        } else { 
     152                $parent = (int) $parent; 
     153 
     154                $cats = get_categories("parent=$parent&hide_empty=0&fields=ids"); 
     155 
     156                $result = array(); 
     157                if ( is_array( $cats ) ) { 
     158                        foreach ( $cats as $cat ) { 
     159                                $result[$cat]['children'] = get_nested_categories( $default, $cat ); 
     160                                $result[$cat]['cat_ID'] = $cat; 
     161                                $result[$cat]['checked'] = in_array( $cat, $checked_categories ); 
     162                                $result[$cat]['cat_name'] = get_the_category_by_ID( $cat ); 
     163                        } 
    146164                } 
    147165        } 
    148166 
     
    165183        } 
    166184} 
    167185 
    168 function dropdown_categories( $default = 0 ) { 
    169         write_nested_categories( get_nested_categories( $default) ); 
     186function dropdown_categories( $default = 0, $parent = 0 ) { 
     187        write_nested_categories( get_nested_categories( $default, $parent ) ); 
    170188} 
    171189 
     190function wp_popular_categories_checklist( $default = 0, $number = 10 ) { 
     191        global $checked_categories; 
     192 
     193        wp_set_checked_post_categories( $default ); 
     194 
     195        $categories = get_categories( array( 'orderby' => 'count', 'order' => 'DESC', 'number' => $number ) ); 
     196 
     197        foreach ( (array) $categories as $category ) { 
     198                $id = "popular-category-$category->term_id"; 
     199                $checked = in_array( $category->term_id, $checked_categories ) ? ' checked="checked"' : '';              
     200                ?> 
     201 
     202                <li id="<?php echo $id; ?>"> 
     203                        <label class="selectit" for="in-<?php echo $id; ?>"> 
     204                                <input id="in-<?php echo $id; ?>" type="checkbox" name="post_category[]" value="<?php echo (int) $category->term_id; ?>"<?php echo $checked; ?> /> 
     205                                <?php echo wp_specialchars( apply_filters( 'the_category', $category->name ) ); ?> 
     206                        </label> 
     207                </li> 
     208 
     209                <?php 
     210        } 
     211} 
     212 
    172213function dropdown_link_categories( $default = 0 ) { 
    173214        global $link_id; 
    174215 
  • wp-admin/includes/taxonomy.php

     
    1616        return $category; 
    1717} 
    1818 
    19 function wp_create_category($cat_name) { 
     19function wp_create_category( $cat_name, $parent = 0 ) { 
    2020        if ( $id = category_exists($cat_name) ) 
    2121                return $id; 
    2222 
    23         return wp_insert_category( array('cat_name' => $cat_name) ); 
     23        return wp_insert_category( array('cat_name' => $cat_name, 'category_parent' => $parent) ); 
    2424} 
    2525 
    2626function wp_create_categories($categories, $post_id = '') { 
  • wp-admin/js/post.js

     
    9090 
    9191        // postboxes 
    9292        add_postbox_toggles(); 
     93 
     94        // category tabs 
     95        var categoryTabs =jQuery('#category-tabs').tabs(); 
     96 
     97        // Ajax Cat 
     98        var newCat = jQuery('#newcat').one( 'focus', function() { jQuery(this).val( '' ) } ); 
     99        jQuery('#category-add-sumbit').click( function() { newCat.focus(); } ); 
     100        var catAddAfter = function( r, s ) { 
     101                jQuery(s.what + ' response_data', r).each( function() { 
     102                        var t = jQuery(jQuery(this).text()); 
     103                        var o = jQuery( '<option value="' +  parseInt( t.find(':input').val(), 10 ) + '"></option>' ); 
     104                        o.text( jQuery.trim( t.text() ) ); 
     105                        jQuery('#newcat_parent').prepend( o ); 
     106                } ); 
     107        }; 
     108        jQuery('#categorychecklist').wpList( { 
     109                alt: '', 
     110                response: 'category-ajax-response', 
     111                addAfter: catAddAfter 
     112        } ); 
     113        jQuery('#category-add-toggle').click( function() { 
     114                jQuery(this).parents('div:first').toggleClass( 'wp-hidden-children' ); 
     115                categoryTabs.tabsClick( 1 ); 
     116                return false; 
     117        } ); 
    93118}); 
  • wp-admin/edit-form-advanced.php

     
    121121<div id="categorydiv" class="postbox <?php echo postbox_classes('categorydiv'); ?>"> 
    122122<h3><?php _e('Categories') ?></h3> 
    123123<div class="inside"> 
    124 <p id="jaxcat"><?php wp_nonce_field( 'add-category', '_ajax_nonce', false ); ?></p> 
    125 <ul id="categorychecklist" class="list:category"><?php dropdown_categories(); ?></ul> 
     124 
     125<div id="category-adder" class="wp-hidden-children"> 
     126        <h4><a id="category-add-toggle" href="#category-add"><?php _e( '+ Add New Category' ); ?></a></h4> 
     127        <p id="category-add" class="wp-hidden-child"> 
     128                <input type="text" name="newcat" id="newcat" class="form-required" value="<?php _e( 'New category name' ); ?>" /> 
     129                <?php wp_dropdown_categories( array( 'hide_empty' => 0, 'name' => 'newcat_parent', 'orderby' => 'name', 'hierarchical' => 1, 'show_option_none' => __('Parent category') ) ); ?> 
     130                <a id="category-add-sumbit" class="add:categorychecklist:categorydiv button" href="<?php echo wp_nonce_url( '', 'add-category' ); ?>"><?php _e( 'Add' ); ?></a> 
     131                <span id="category-ajax-response"></span> 
     132        </p> 
    126133</div> 
     134 
     135<ul id="category-tabs"> 
     136        <li class="ui-tabs-selected"><a href="#categories-all"><?php _e( 'All Categories' ); ?></a></li> 
     137        <li><a href="#categories-pop"><?php _e( 'Most Used' ); ?></a></li> 
     138</ul> 
     139 
     140<div id="categories-all" class="ui-tabs-panel"> 
     141        <ul id="categorychecklist" class="list:category categorychecklist form-no-clear"> 
     142                <?php dropdown_categories(); ?> 
     143        </ul> 
    127144</div> 
    128145 
     146<div id="categories-pop" class="ui-tabs-panel"> 
     147        <ul id="categorychecklist-pop" class="categorychecklist form-no-clear"> 
     148                <?php wp_popular_categories_checklist(); ?> 
     149        </ul> 
     150</div> 
     151 
     152</div> 
     153</div> 
     154 
    129155<?php do_action('edit_form_advanced'); ?> 
    130156 
    131157<?php 
  • wp-admin/admin-header.php

     
    22@header('Content-Type: ' . get_option('html_type') . '; charset=' . get_option('blog_charset')); 
    33if (!isset($_GET["page"])) require_once('admin.php'); 
    44if ( $editing ) { 
    5         if ( current_user_can('manage_categories') ) 
    6                 wp_enqueue_script( 'ajaxcat' ); 
    75        if ( user_can_richedit() ) 
    86                wp_enqueue_script( 'wp_tiny_mce' ); 
    97}