Make WordPress Core

Changeset 38599


Ignore:
Timestamp:
09/13/2016 10:23:30 PM (8 years ago)
Author:
obenland
Message:

Make wpList easier to contribute to.

Uses more semantic variable names and adds function and inline documentation.

Props rommelxcastro for parallel work in #34917.
Fixes #36264.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/js/wp-lists.js

    r38050 r38599  
    11/* global ajaxurl, wpAjax */
    2 (function($) {
    3 var fs = {add:'ajaxAdd',del:'ajaxDel',dim:'ajaxDim',process:'process',recolor:'recolor'}, wpList;
    4 
     2
     3/**
     4 * @param {jQuery} $ jQuery object.
     5 */
     6( function( $ ) {
     7var functions = {
     8    add:     'ajaxAdd',
     9    del:     'ajaxDel',
     10    dim:     'ajaxDim',
     11    process: 'process',
     12    recolor: 'recolor'
     13}, wpList;
     14
     15/**
     16 * @namespace
     17 */
    518wpList = {
     19
     20    /**
     21     * @member {object}
     22     */
    623    settings: {
    7         url: ajaxurl, type: 'POST',
     24
     25        /**
     26         * URL for Ajax requests.
     27         *
     28         * @member {string}
     29         */
     30        url: ajaxurl,
     31
     32        /**
     33         * The HTTP method to use for Ajax requests.
     34         *
     35         * @member {string}
     36         */
     37        type: 'POST',
     38
     39        /**
     40         * ID of the element the parsed Ajax response will be stored in.
     41         *
     42         * @member {string}
     43         */
    844        response: 'ajax-response',
    945
     46        /**
     47         * The type of list.
     48         *
     49         * @member {string}
     50         */
    1051        what: '',
    11         alt: 'alternate', altOffset: 0,
    12         addColor: null, delColor: null, dimAddColor: null, dimDelColor: null,
    13 
     52
     53        /**
     54         * CSS class name for alternate styling.
     55         *
     56         * @member {string}
     57         */
     58        alt: 'alternate',
     59
     60        /**
     61         * Offset to start alternate styling from.
     62         *
     63         * @member {number}
     64         */
     65        altOffset: 0,
     66
     67        /**
     68         * Color used in animation when adding an element.
     69         *
     70         * Can be 'none' to disable the animation.
     71         *
     72         * @member {string}
     73         */
     74        addColor: '#ffff33',
     75
     76        /**
     77         * Color used in animation when deleting an element.
     78         *
     79         * Can be 'none' to disable the animation.
     80         *
     81         * @member {string}
     82         */
     83        delColor: '#faafaa',
     84
     85        /**
     86         * Color used in dim add animation.
     87         *
     88         * Can be 'none' to disable the animation.
     89         *
     90         * @member {string}
     91         */
     92        dimAddColor: '#ffff33',
     93
     94        /**
     95         * Color used in dim delete animation.
     96         *
     97         * Can be 'none' to disable the animation.
     98         *
     99         * @member {string}
     100         */
     101        dimDelColor: '#ff3333',
     102
     103        /**
     104         * Callback that's run before a request is made.
     105         *
     106         * @callback wpList~confirm
     107         * @param {object}      this
     108         * @param {HTMLElement} list            The list DOM element.
     109         * @param {object}      settings        Settings for the current list.
     110         * @param {string}      action          The type of action to perform: 'add', 'delete', or 'dim'.
     111         * @param {string}      backgroundColor Background color of the list's DOM element.
     112         * @returns {boolean} Whether to proceed with the action or not.
     113         */
    14114        confirm: null,
    15         addBefore: null, addAfter: null,
    16         delBefore: null, delAfter: null,
    17         dimBefore: null, dimAfter: null
    18     },
    19 
    20     nonce: function(e,s) {
    21         var url = wpAjax.unserialize(e.attr('href'));
    22         return s.nonce || url._ajax_nonce || $('#' + s.element + ' input[name="_ajax_nonce"]').val() || url._wpnonce || $('#' + s.element + ' input[name="_wpnonce"]').val() || 0;
     115
     116        /**
     117         * Callback that's run before an item gets added to the list.
     118         *
     119         * Allows to cancel the request.
     120         *
     121         * @callback wpList~addBefore
     122         * @param {object} settings Settings for the Ajax request.
     123         * @returns {object|boolean} Settings for the Ajax request or false to abort.
     124         */
     125        addBefore: null,
     126
     127        /**
     128         * Callback that's run after an item got added to the list.
     129         *
     130         * @callback wpList~addAfter
     131         * @param {XML}    returnedResponse Raw response returned from the server.
     132         * @param {object} settings         Settings for the Ajax request.
     133         * @param {jqXHR}  settings.xml     jQuery XMLHttpRequest object.
     134         * @param {string} settings.status  Status of the request: 'success', 'notmodified', 'nocontent', 'error',
     135         *                                  'timeout', 'abort', or 'parsererror'.
     136         * @param {object} settings.parsed  Parsed response object.
     137         */
     138        addAfter: null,
     139
     140        /**
     141         * Callback that's run before an item gets deleted from the list.
     142         *
     143         * Allows to cancel the request.
     144         *
     145         * @callback wpList~delBefore
     146         * @param {object}      settings Settings for the Ajax request.
     147         * @param {HTMLElement} list     The list DOM element.
     148         * @returns {object|boolean} Settings for the Ajax request or false to abort.
     149         */
     150        delBefore: null,
     151
     152        /**
     153         * Callback that's run after an item got deleted from the list.
     154         *
     155         * @callback wpList~delAfter
     156         * @param {XML}    returnedResponse Raw response returned from the server.
     157         * @param {object} settings         Settings for the Ajax request.
     158         * @param {jqXHR}  settings.xml     jQuery XMLHttpRequest object.
     159         * @param {string} settings.status  Status of the request: 'success', 'notmodified', 'nocontent', 'error',
     160         *                                  'timeout', 'abort', or 'parsererror'.
     161         * @param {object} settings.parsed  Parsed response object.
     162         */
     163        delAfter: null,
     164
     165        /**
     166         * Callback that's run before an item gets dim'd.
     167         *
     168         * Allows to cancel the request.
     169         *
     170         * @callback wpList~dimBefore
     171         * @param {object} settings Settings for the Ajax request.
     172         * @returns {object|boolean} Settings for the Ajax request or false to abort.
     173         */
     174        dimBefore: null,
     175
     176        /**
     177         * Callback that's run after an item got dim'd.
     178         *
     179         * @callback wpList~dimAfter
     180         * @param {XML}    returnedResponse Raw response returned from the server.
     181         * @param {object} settings         Settings for the Ajax request.
     182         * @param {jqXHR}  settings.xml     jQuery XMLHttpRequest object.
     183         * @param {string} settings.status  Status of the request: 'success', 'notmodified', 'nocontent', 'error',
     184         *                                  'timeout', 'abort', or 'parsererror'.
     185         * @param {object} settings.parsed  Parsed response object.
     186         */
     187        dimAfter: null
     188    },
     189
     190    /**
     191     * Finds a nonce.
     192     *
     193     * 1. Nonce in settings.
     194     * 2. `_ajax_nonce` value in element's href attribute.
     195     * 3. `_ajax_nonce` input field that is a descendant of element.
     196     * 4. `_wpnonce` value in element's href attribute.
     197     * 5. `_wpnonce` input field that is a descendant of element.
     198     * 6. 0 if none can be found.
     199     *
     200     * @param {jQuery} element  Element that triggered the request.
     201     * @param {object} settings Settings for the Ajax request.
     202     * @returns {string|number} Nonce
     203     */
     204    nonce: function( element, settings ) {
     205        var url      = wpAjax.unserialize( element.attr( 'href' ) ),
     206            $element = $( '#' + settings.element );
     207
     208        return settings.nonce || url._ajax_nonce || $element.find( 'input[name="_ajax_nonce"]' ).val() || url._wpnonce || $element.find( 'input[name="_wpnonce"]' ).val() || 0;
    23209    },
    24210
     
    26212     * Extract list item data from a DOM element.
    27213     *
    28      * @param  {HTMLElement} e The DOM element.
    29      * @param  {string}      t
    30      * @return {array}
    31      */
    32     parseData: function(e,t) {
    33         var d = [], wpListsData;
     214     * Example 1: data-wp-lists="delete:the-comment-list:comment-{comment_ID}:66cc66:unspam=1"
     215     * Example 2: data-wp-lists="dim:the-comment-list:comment-{comment_ID}:unapproved:e7e7d3:e7e7d3:new=approved"
     216     *
     217     * Returns an unassociated array with the following data:
     218     * data[0] - Data identifier: 'list', 'add', 'delete', or 'dim'.
     219     * data[1] - ID of the corresponding list. If data[0] is 'list', the type of list ('comment', 'category', etc).
     220     * data[2] - ID of the parent element of all inputs necessary for the request.
     221     * data[3] - Hex color to be used in this request. If data[0] is 'dim', dim class.
     222     * data[4] - Additional arguments in query syntax that are added to the request. Example: 'post_id=1234'.
     223     *           If data[0] is 'dim', dim add color.
     224     * data[5] - Only available if data[0] is 'dim', dim delete color.
     225     * data[6] - Only available if data[0] is 'dim', additional arguments in query syntax that are added to the request.
     226     *
     227     * Result for Example 1:
     228     * data[0] - delete
     229     * data[1] - the-comment-list
     230     * data[2] - comment-{comment_ID}
     231     * data[3] - 66cc66
     232     * data[4] - unspam=1
     233     *
     234     * @param  {HTMLElement} element The DOM element.
     235     * @param  {string}      type    The type of data to look for: 'list', 'add', 'delete', or 'dim'.
     236     * @returns {Array} Extracted list item data.
     237     */
     238    parseData: function( element, type ) {
     239        var data = [], wpListsData;
    34240
    35241        try {
    36             wpListsData = $(e).attr('data-wp-lists') || '';
    37             wpListsData = wpListsData.match(new RegExp(t+':[\\S]+'));
    38 
    39             if ( wpListsData )
    40                 d = wpListsData[0].split(':');
    41         } catch(r) {}
    42 
    43         return d;
    44     },
    45 
    46     pre: function(e,s,a) {
    47         var bg, r;
    48 
    49         s = $.extend( {}, this.wpList.settings, {
     242            wpListsData = $( element ).data( 'wp-lists' ) || '';
     243            wpListsData = wpListsData.match( new RegExp( type + ':[\\S]+' ) );
     244
     245            if ( wpListsData ) {
     246                data = wpListsData[0].split( ':' );
     247            }
     248        } catch ( error ) {}
     249
     250        return data;
     251    },
     252
     253    /**
     254     * Calls a confirm callback to verify the action that is about to be performed.
     255     *
     256     * @param {HTMLElement} list     The DOM element.
     257     * @param {object}      settings Settings for this list.
     258     * @param {string}      action   The type of action to perform: 'add', 'delete', or 'dim'.
     259     * @returns {object|boolean} Settings if confirmed, false if not.
     260     */
     261    pre: function( list, settings, action ) {
     262        var $element, backgroundColor, confirmed;
     263
     264        settings = $.extend( {}, this.wpList.settings, {
    50265            element: null,
    51             nonce: 0,
    52             target: e.get(0)
    53         }, s || {} );
    54 
    55         if ( $.isFunction( s.confirm ) ) {
    56             if ( 'add' != a ) {
    57                 bg = $('#' + s.element).css('backgroundColor');
    58                 $('#' + s.element).css('backgroundColor', '#FF9966');
    59             }
    60             r = s.confirm.call(this, e, s, a, bg);
    61 
    62             if ( 'add' != a )
    63                 $('#' + s.element).css('backgroundColor', bg );
    64 
    65             if ( !r )
     266            nonce:   0,
     267            target:  list.get( 0 )
     268        }, settings || {} );
     269
     270        if ( $.isFunction( settings.confirm ) ) {
     271            $element = $( '#' + settings.element );
     272
     273            if ( 'add' !== action ) {
     274                backgroundColor = $element.css( 'backgroundColor' );
     275                $element.css( 'backgroundColor', '#ff9966' );
     276            }
     277
     278            confirmed = settings.confirm.call( this, list, settings, action, backgroundColor );
     279
     280            if ( 'add' !== action ) {
     281                $element.css( 'backgroundColor', backgroundColor );
     282            }
     283
     284            if ( ! confirmed ) {
    66285                return false;
    67         }
    68 
    69         return s;
    70     },
    71 
    72     ajaxAdd: function( e, s ) {
    73         e = $(e);
    74         s = s || {};
    75         var list = this, data = wpList.parseData(e,'add'), es, valid, formData, res, rres;
    76 
    77         s = wpList.pre.call( list, e, s, 'add' );
    78 
    79         s.element = data[2] || e.attr( 'id' ) || s.element || null;
    80 
    81         if ( data[3] )
    82             s.addColor = '#' + data[3];
    83         else
    84             s.addColor = s.addColor || '#FFFF33';
    85 
    86         if ( !s )
     286            }
     287        }
     288
     289        return settings;
     290    },
     291
     292    /**
     293     * Adds an item to the list via AJAX.
     294     *
     295     * @param {HTMLElement} element  The DOM element.
     296     * @param {object}      settings Settings for this list.
     297     * @returns {boolean} Whether the item was added.
     298     */
     299    ajaxAdd: function( element, settings ) {
     300        var list     = this,
     301            $element = $( element ),
     302            data     = wpList.parseData( $element, 'add' ),
     303            formValues, formData, parsedResponse, returnedResponse;
     304
     305        settings = settings || {};
     306        settings = wpList.pre.call( list, $element, settings, 'add' );
     307
     308        settings.element  = data[2] || $element.prop( 'id' ) || settings.element || null;
     309        settings.addColor = data[3] ? '#' + data[3] : settings.addColor;
     310
     311        if ( ! settings ) {
    87312            return false;
    88 
    89         if ( !e.is('[id="' + s.element + '-submit"]') )
    90             return !wpList.add.call( list, e, s );
    91 
    92         if ( !s.element )
     313        }
     314
     315        if ( ! $element.is( '[id="' + settings.element + '-submit"]' ) ) {
     316            return ! wpList.add.call( list, $element, settings );
     317        }
     318
     319        if ( ! settings.element ) {
    93320            return true;
    94 
    95         s.action = 'add-' + s.what;
    96 
    97         s.nonce = wpList.nonce(e,s);
    98 
    99         es = $('#' + s.element + ' :input').not('[name="_ajax_nonce"], [name="_wpnonce"], [name="action"]');
    100         valid = wpAjax.validateForm( '#' + s.element );
    101 
    102         if ( !valid )
     321        }
     322
     323        settings.action = 'add-' + settings.what;
     324        settings.nonce  = wpList.nonce( $element, settings );
     325
     326        if ( ! wpAjax.validateForm( '#' + settings.element ) ) {
    103327            return false;
    104 
    105         s.data = $.param( $.extend( { _ajax_nonce: s.nonce, action: s.action }, wpAjax.unserialize( data[4] || '' ) ) );
    106         formData = $.isFunction(es.fieldSerialize) ? es.fieldSerialize() : es.serialize();
    107 
    108         if ( formData )
    109             s.data += '&' + formData;
    110 
    111         if ( $.isFunction(s.addBefore) ) {
    112             s = s.addBefore( s );
    113             if ( !s )
     328        }
     329
     330        settings.data = $.param( $.extend( {
     331            _ajax_nonce: settings.nonce,
     332            action:      settings.action
     333        }, wpAjax.unserialize( data[4] || '' ) ) );
     334
     335        formValues = $( '#' + settings.element + ' :input' ).not( '[name="_ajax_nonce"], [name="_wpnonce"], [name="action"]' );
     336        formData   = $.isFunction( formValues.fieldSerialize ) ? formValues.fieldSerialize() : formValues.serialize();
     337
     338        if ( formData ) {
     339            settings.data += '&' + formData;
     340        }
     341
     342        if ( $.isFunction( settings.addBefore ) ) {
     343            settings = settings.addBefore( settings );
     344
     345            if ( ! settings ) {
    114346                return true;
    115         }
    116 
    117         if ( !s.data.match(/_ajax_nonce=[a-f0-9]+/) )
     347            }
     348        }
     349
     350        if ( ! settings.data.match( /_ajax_nonce=[a-f0-9]+/ ) ) {
    118351            return true;
    119 
    120         s.success = function(r) {
    121             res = wpAjax.parseAjaxResponse(r, s.response, s.element);
    122 
    123             rres = r;
    124 
    125             if ( !res || res.errors )
     352        }
     353
     354        settings.success = function( response ) {
     355            parsedResponse   = wpAjax.parseAjaxResponse( response, settings.response, settings.element );
     356            returnedResponse = response;
     357
     358            if ( ! parsedResponse || parsedResponse.errors ) {
    126359                return false;
    127 
    128             if ( true === res )
     360            }
     361
     362            if ( true === parsedResponse ) {
    129363                return true;
    130 
    131             jQuery.each( res.responses, function() {
    132                 wpList.add.call( list, this.data, $.extend( {}, s, { // this.firstChild.nodevalue
    133                     pos: this.position || 0,
    134                     id: this.id || 0,
    135                     oldId: this.oldId || null
     364            }
     365
     366            $.each( parsedResponse.responses, function() {
     367                wpList.add.call( list, this.data, $.extend( {}, settings, { // this.firstChild.nodevalue
     368                    position: this.position || 0,
     369                    id:       this.id || 0,
     370                    oldId:    this.oldId || null
    136371                } ) );
    137372            } );
    138373
    139374            list.wpList.recolor();
    140             $(list).trigger( 'wpListAddEnd', [ s, list.wpList ] );
    141             wpList.clear.call(list,'#' + s.element);
     375            $( list ).trigger( 'wpListAddEnd', [ settings, list.wpList ] );
     376            wpList.clear.call( list, '#' + settings.element );
    142377        };
    143378
    144         s.complete = function(x, st) {
    145             if ( $.isFunction(s.addAfter) ) {
    146                 var _s = $.extend( { xml: x, status: st, parsed: res }, s );
    147                 s.addAfter( rres, _s );
     379        settings.complete = function( jqXHR, status ) {
     380            if ( $.isFunction( settings.addAfter ) ) {
     381                settings.addAfter( returnedResponse, $.extend( {
     382                    xml:    jqXHR,
     383                    status: status,
     384                    parsed: parsedResponse
     385                }, settings ) );
    148386            }
    149387        };
    150388
    151         $.ajax( s );
     389        $.ajax( settings );
     390
    152391        return false;
    153392    },
     
    156395     * Delete an item in the list via AJAX.
    157396     *
    158      * @param  {HTMLElement} e A DOM element containing item data.
    159      * @param  {Object}      s
    160      * @return {boolean}
    161      */
    162     ajaxDel: function( e, s ) {
    163         e = $(e);
    164         s = s || {};
    165         var list = this, data = wpList.parseData(e,'delete'), element, res, rres;
    166 
    167         s = wpList.pre.call( list, e, s, 'delete' );
    168 
    169         s.element = data[2] || s.element || null;
    170 
    171         if ( data[3] )
    172             s.delColor = '#' + data[3];
    173         else
    174             s.delColor = s.delColor || '#faa';
    175 
    176         if ( !s || !s.element )
     397     * @param {HTMLElement} element  A DOM element containing item data.
     398     * @param {object}      settings Settings for this list.
     399     * @returns {boolean} Whether the item was deleted.
     400     */
     401    ajaxDel: function( element, settings ) {
     402        var list     = this,
     403            $element = $( element ),
     404            data     = wpList.parseData( $element, 'delete' ),
     405            $eventTarget, parsedResponse, returnedResponse;
     406
     407        settings = settings || {};
     408        settings = wpList.pre.call( list, $element, settings, 'delete' );
     409
     410        settings.element  = data[2] || settings.element || null;
     411        settings.delColor = data[3] ? '#' + data[3] : settings.delColor;
     412
     413        if ( ! settings || ! settings.element ) {
    177414            return false;
    178 
    179         s.action = 'delete-' + s.what;
    180 
    181         s.nonce = wpList.nonce(e,s);
    182 
    183         s.data = $.extend(
    184             { action: s.action, id: s.element.split('-').pop(), _ajax_nonce: s.nonce },
    185             wpAjax.unserialize( data[4] || '' )
    186         );
    187 
    188         if ( $.isFunction(s.delBefore) ) {
    189             s = s.delBefore( s, list );
    190             if ( !s )
     415        }
     416
     417        settings.action = 'delete-' + settings.what;
     418        settings.nonce  = wpList.nonce( $element, settings );
     419
     420        settings.data = $.extend( {
     421            _ajax_nonce: settings.nonce,
     422            action:      settings.action,
     423            id:          settings.element.split( '-' ).pop()
     424        }, wpAjax.unserialize( data[4] || '' ) );
     425
     426        if ( $.isFunction( settings.delBefore ) ) {
     427            settings = settings.delBefore( settings, list );
     428
     429            if ( ! settings ) {
    191430                return true;
    192         }
    193 
    194         if ( !s.data._ajax_nonce )
     431            }
     432        }
     433
     434        if ( ! settings.data._ajax_nonce ) {
    195435            return true;
    196 
    197         element = $('#' + s.element);
    198 
    199         if ( 'none' != s.delColor ) {
    200             element.css( 'backgroundColor', s.delColor ).fadeOut( 350, function(){
     436        }
     437
     438        $eventTarget = $( '#' + settings.element );
     439
     440        if ( 'none' !== settings.delColor ) {
     441            $eventTarget.css( 'backgroundColor', settings.delColor ).fadeOut( 350, function() {
    201442                list.wpList.recolor();
    202                 $(list).trigger( 'wpListDelEnd', [ s, list.wpList ] );
    203             });
     443                $( list ).trigger( 'wpListDelEnd', [ settings, list.wpList ] );
     444            } );
    204445        } else {
    205446            list.wpList.recolor();
    206             $(list).trigger( 'wpListDelEnd', [ s, list.wpList ] );
    207         }
    208 
    209         s.success = function(r) {
    210             res = wpAjax.parseAjaxResponse(r, s.response, s.element);
    211             rres = r;
    212 
    213             if ( !res || res.errors ) {
    214                 element.stop().stop().css( 'backgroundColor', '#faa' ).show().queue( function() { list.wpList.recolor(); $(this).dequeue(); } );
     447            $( list ).trigger( 'wpListDelEnd', [ settings, list.wpList ] );
     448        }
     449
     450        settings.success = function( response ) {
     451            parsedResponse   = wpAjax.parseAjaxResponse( response, settings.response, settings.element );
     452            returnedResponse = response;
     453
     454            if ( ! parsedResponse || parsedResponse.errors ) {
     455                $eventTarget.stop().stop().css( 'backgroundColor', '#faa' ).show().queue( function() {
     456                    list.wpList.recolor();
     457                    $( this ).dequeue();
     458                } );
     459
    215460                return false;
    216461            }
    217462        };
    218463
    219         s.complete = function(x, st) {
    220             if ( $.isFunction(s.delAfter) ) {
    221                 element.queue( function() {
    222                     var _s = $.extend( { xml: x, status: st, parsed: res }, s );
    223                     s.delAfter( rres, _s );
    224                 }).dequeue();
     464        settings.complete = function( jqXHR, status ) {
     465            if ( $.isFunction( settings.delAfter ) ) {
     466                $eventTarget.queue( function() {
     467                    settings.delAfter( returnedResponse, $.extend( {
     468                        xml:    jqXHR,
     469                        status: status,
     470                        parsed: parsedResponse
     471                    }, settings ) );
     472                } ).dequeue();
    225473            }
    226474        };
    227475
    228         $.ajax( s );
     476        $.ajax( settings );
     477
    229478        return false;
    230479    },
    231480
    232     ajaxDim: function( e, s ) {
    233         if ( $(e).parent().css('display') == 'none' ) // Prevent hidden links from being clicked by hotkeys
     481    /**
     482     * Dim an item in the list via AJAX.
     483     *
     484     * @param {HTMLElement} element  A DOM element containing item data.
     485     * @param {object}      settings Settings for this list.
     486     * @returns {boolean} Whether the item was dim'ed.
     487     */
     488    ajaxDim: function( element, settings ) {
     489        var list     = this,
     490            $element = $( element ),
     491            data     = wpList.parseData( $element, 'dim' ),
     492            $eventTarget, isClass, color, dimColor, parsedResponse, returnedResponse;
     493
     494        // Prevent hidden links from being clicked by hotkeys.
     495        if ( 'none' === $element.parent().css( 'display' ) ) {
    234496            return false;
    235 
    236         e = $(e);
    237         s = s || {};
    238 
    239         var list = this, data = wpList.parseData(e,'dim'), element, isClass, color, dimColor, res, rres;
    240 
    241         s = wpList.pre.call( list, e, s, 'dim' );
    242 
    243         s.element = data[2] || s.element || null;
    244         s.dimClass =  data[3] || s.dimClass || null;
    245 
    246         if ( data[4] )
    247             s.dimAddColor = '#' + data[4];
    248         else
    249             s.dimAddColor = s.dimAddColor || '#FFFF33';
    250 
    251         if ( data[5] )
    252             s.dimDelColor = '#' + data[5];
    253         else
    254             s.dimDelColor = s.dimDelColor || '#FF3333';
    255 
    256         if ( !s || !s.element || !s.dimClass )
     497        }
     498
     499        settings = settings || {};
     500        settings = wpList.pre.call( list, $element, settings, 'dim' );
     501
     502        settings.element     = data[2] || settings.element || null;
     503        settings.dimClass    = data[3] || settings.dimClass || null;
     504        settings.dimAddColor = data[4] ? '#' + data[4] : settings.dimAddColor;
     505        settings.dimDelColor = data[5] ? '#' + data[5] : settings.dimDelColor;
     506
     507        if ( ! settings || ! settings.element || ! settings.dimClass ) {
    257508            return true;
    258 
    259         s.action = 'dim-' + s.what;
    260 
    261         s.nonce = wpList.nonce(e,s);
    262 
    263         s.data = $.extend(
    264             { action: s.action, id: s.element.split('-').pop(), dimClass: s.dimClass, _ajax_nonce : s.nonce },
    265             wpAjax.unserialize( data[6] || '' )
    266         );
    267 
    268         if ( $.isFunction(s.dimBefore) ) {
    269             s = s.dimBefore( s );
    270             if ( !s )
     509        }
     510
     511        settings.action = 'dim-' + settings.what;
     512        settings.nonce  = wpList.nonce( $element, settings );
     513
     514        settings.data = $.extend( {
     515            _ajax_nonce: settings.nonce,
     516            action:      settings.action,
     517            id:          settings.element.split( '-' ).pop(),
     518            dimClass:    settings.dimClass
     519        }, wpAjax.unserialize( data[6] || '' ) );
     520
     521        if ( $.isFunction( settings.dimBefore ) ) {
     522            settings = settings.dimBefore( settings );
     523
     524            if ( ! settings ) {
    271525                return true;
    272         }
    273 
    274         element = $('#' + s.element);
    275         isClass = element.toggleClass(s.dimClass).is('.' + s.dimClass);
    276         color = wpList.getColor( element );
    277         element.toggleClass( s.dimClass );
    278         dimColor = isClass ? s.dimAddColor : s.dimDelColor;
    279 
    280         if ( 'none' != dimColor ) {
    281             element
     526            }
     527        }
     528
     529        $eventTarget = $( '#' + settings.element );
     530        isClass      = $eventTarget.toggleClass( settings.dimClass ).is( '.' + settings.dimClass );
     531        color        = wpList.getColor( $eventTarget );
     532        dimColor     = isClass ? settings.dimAddColor : settings.dimDelColor;
     533        $eventTarget.toggleClass( settings.dimClass );
     534
     535        if ( 'none' !== dimColor ) {
     536            $eventTarget
    282537                .animate( { backgroundColor: dimColor }, 'fast' )
    283                 .queue( function() { element.toggleClass(s.dimClass); $(this).dequeue(); } )
    284                 .animate( { backgroundColor: color }, { complete: function() {
    285                         $(this).css( 'backgroundColor', '' );
    286                         $(list).trigger( 'wpListDimEnd', [ s, list.wpList ] );
     538                .queue( function() {
     539                    $eventTarget.toggleClass( settings.dimClass );
     540                    $( this ).dequeue();
     541                } )
     542                .animate( { backgroundColor: color }, {
     543                    complete: function() {
     544                        $( this ).css( 'backgroundColor', '' );
     545                        $( list ).trigger( 'wpListDimEnd', [ settings, list.wpList ] );
    287546                    }
    288                 });
     547                } );
    289548        } else {
    290             $(list).trigger( 'wpListDimEnd', [ s, list.wpList ] );
    291         }
    292 
    293         if ( !s.data._ajax_nonce )
     549            $( list ).trigger( 'wpListDimEnd', [ settings, list.wpList ] );
     550        }
     551
     552        if ( ! settings.data._ajax_nonce ) {
    294553            return true;
    295 
    296         s.success = function(r) {
    297             res = wpAjax.parseAjaxResponse(r, s.response, s.element);
    298             rres = r;
    299 
    300             if ( true === res ) {
     554        }
     555
     556        settings.success = function( response ) {
     557            parsedResponse   = wpAjax.parseAjaxResponse( response, settings.response, settings.element );
     558            returnedResponse = response;
     559
     560            if ( true === parsedResponse ) {
    301561                return true;
    302562            }
    303563
    304             if ( ! res || res.errors ) {
    305                 element.stop().stop().css( 'backgroundColor', '#FF3333' )[isClass?'removeClass':'addClass'](s.dimClass).show().queue( function() { list.wpList.recolor(); $(this).dequeue(); } );
     564            if ( ! parsedResponse || parsedResponse.errors ) {
     565                $eventTarget.stop().stop().css( 'backgroundColor', '#ff3333' )[isClass ? 'removeClass' : 'addClass']( settings.dimClass ).show().queue( function() {
     566                    list.wpList.recolor();
     567                    $( this ).dequeue();
     568                } );
     569
    306570                return false;
    307571            }
    308572
    309             if ( 'undefined' !== typeof res.responses[0].supplemental.comment_link ) {
    310                 var submittedOn = element.find( '.submitted-on' ),
    311                     commentLink = submittedOn.find( 'a' );
     573            /** @property {string} comment_link Link of the comment to be dimmed. */
     574            if ( 'undefined' !== typeof parsedResponse.responses[0].supplemental.comment_link ) {
     575                var $submittedOn = $element.find( '.submitted-on' ),
     576                    $commentLink = $submittedOn.find( 'a' );
    312577
    313578                // Comment is approved; link the date field.
    314                 if ( '' !== res.responses[0].supplemental.comment_link ) {
    315                     submittedOn.html( $('<a></a>').text( submittedOn.text() ).prop( 'href', res.responses[0].supplemental.comment_link ) );
     579                if ( '' !== parsedResponse.responses[0].supplemental.comment_link ) {
     580                    $submittedOn.html( $('<a></a>').text( $submittedOn.text() ).prop( 'href', parsedResponse.responses[0].supplemental.comment_link ) );
    316581
    317582                // Comment is not approved; unlink the date field.
    318                 } else if ( commentLink.length ) {
    319                     submittedOn.text( commentLink.text() );
     583                } else if ( $commentLink.length ) {
     584                    $submittedOn.text( $commentLink.text() );
    320585                }
    321586            }
    322587        };
    323588
    324         s.complete = function(x, st) {
    325             if ( $.isFunction(s.dimAfter) ) {
    326                 element.queue( function() {
    327                     var _s = $.extend( { xml: x, status: st, parsed: res }, s );
    328                     s.dimAfter( rres, _s );
    329                 }).dequeue();
     589        settings.complete = function( jqXHR, status ) {
     590            if ( $.isFunction( settings.dimAfter ) ) {
     591                $eventTarget.queue( function() {
     592                    settings.dimAfter( returnedResponse, $.extend( {
     593                        xml:    jqXHR,
     594                        status: status,
     595                        parsed: parsedResponse
     596                    }, settings ) );
     597                } ).dequeue();
    330598            }
    331599        };
    332600
    333         $.ajax( s );
     601        $.ajax( settings );
     602
    334603        return false;
    335604    },
    336605
    337     getColor: function( el ) {
    338         var color = jQuery(el).css('backgroundColor');
    339 
    340         return color || '#ffffff';
    341     },
    342 
    343     add: function( e, s ) {
    344         if ( 'string' == typeof e ) {
    345             e = $( $.trim( e ) ); // Trim leading whitespaces
    346         } else {
    347             e = $( e );
    348         }
    349 
    350         var list = $(this), old = false, _s = { pos: 0, id: 0, oldId: null }, ba, ref, color;
    351 
    352         if ( 'string' == typeof s )
    353             s = { what: s };
    354 
    355         s = $.extend(_s, this.wpList.settings, s);
    356 
    357         if ( !e.length || !s.what )
     606    /**
     607     * Returns the background color of the passed element.
     608     *
     609     * @param {jQuery|string} element Element to check.
     610     * @returns {string} Background color value in HEX. Default: '#ffffff'.
     611     */
     612    getColor: function( element ) {
     613        return $( element ).css( 'backgroundColor' ) || '#ffffff';
     614    },
     615
     616    /**
     617     * Adds something.
     618     *
     619     * @param {HTMLElement} element  A DOM element containing item data.
     620     * @param {object}      settings Settings for this list.
     621     * @returns {boolean} Whether the item was added.
     622     */
     623    add: function( element, settings ) {
     624        var $list    = $( this ),
     625            $element = $( element ),
     626            old      = false,
     627            position, reference;
     628
     629        if ( 'string' === typeof settings ) {
     630            settings = { what: settings };
     631        }
     632
     633        settings = $.extend( { position: 0, id: 0, oldId: null }, this.wpList.settings, settings );
     634
     635        if ( ! $element.length || ! settings.what ) {
    358636            return false;
    359 
    360         if ( s.oldId )
    361             old = $('#' + s.what + '-' + s.oldId);
    362 
    363         if ( s.id && ( s.id != s.oldId || !old || !old.length ) )
    364             $('#' + s.what + '-' + s.id).remove();
     637        }
     638
     639        if ( settings.oldId ) {
     640            old = $( '#' + settings.what + '-' + settings.oldId );
     641        }
     642
     643        if ( settings.id && ( settings.id !== settings.oldId || ! old || ! old.length ) ) {
     644            $( '#' + settings.what + '-' + settings.id ).remove();
     645        }
    365646
    366647        if ( old && old.length ) {
    367             old.before(e);
     648            old.before( $element );
    368649            old.remove();
    369         } else if ( isNaN(s.pos) ) {
    370             ba = 'after';
    371 
    372             if ( '-' == s.pos.substr(0,1) ) {
    373                 s.pos = s.pos.substr(1);
    374                 ba = 'before';
    375             }
    376 
    377             ref = list.find( '#' + s.pos );
    378 
    379             if ( 1 === ref.length )
    380                 ref[ba](e);
    381             else
    382                 list.append(e);
    383 
    384         } else if ( 'comment' != s.what || 0 === $('#' + s.element).length ) {
    385             if ( s.pos < 0 ) {
    386                 list.prepend(e);
     650
     651        } else if ( isNaN( settings.position ) ) {
     652            position = 'after';
     653
     654            if ( '-' === settings.position.substr( 0, 1 ) ) {
     655                settings.position = settings.position.substr( 1 );
     656                position = 'before';
     657            }
     658
     659            reference = $list.find( '#' + settings.position );
     660
     661            if ( 1 === reference.length ) {
     662                reference[position]( $element );
    387663            } else {
    388                 list.append(e);
    389             }
    390         }
    391 
    392         if ( s.alt ) {
    393             if ( ( list.children(':visible').index( e[0] ) + s.altOffset ) % 2 ) { e.removeClass( s.alt ); }
    394             else { e.addClass( s.alt ); }
    395         }
    396 
    397         if ( 'none' != s.addColor ) {
    398             color = wpList.getColor( e );
    399             e.css( 'backgroundColor', s.addColor ).animate( { backgroundColor: color }, { complete: function() { $(this).css( 'backgroundColor', '' ); } } );
    400         }
    401         list.each( function() { this.wpList.process( e ); } );
    402         return e;
    403     },
    404 
    405     clear: function(e) {
    406         var list = this, t, tag;
    407 
    408         e = $(e);
    409 
    410         if ( list.wpList && e.parents( '#' + list.id ).length )
     664                $list.append( $element );
     665            }
     666
     667        } else if ( 'comment' !== settings.what || 0 === $( '#' + settings.element ).length ) {
     668            if ( settings.position < 0 ) {
     669                $list.prepend( $element );
     670            } else {
     671                $list.append( $element );
     672            }
     673        }
     674
     675        if ( settings.alt ) {
     676            $element.toggleClass( settings.alt, ( $list.children( ':visible' ).index( $element[0] ) + settings.altOffset ) % 2 );
     677        }
     678
     679        if ( 'none' !== settings.addColor ) {
     680            $element.css( 'backgroundColor', settings.addColor ).animate( { backgroundColor: wpList.getColor( $element ) }, {
     681                complete: function() {
     682                    $( this ).css( 'backgroundColor', '' );
     683                }
     684            } );
     685        }
     686
     687        // Add event handlers.
     688        $list.each( function( index, list ) {
     689            list.wpList.process( $element );
     690        } );
     691
     692        return $element;
     693    },
     694
     695    /**
     696     * Clears all input fields within the element passed.
     697     *
     698     * @param {string} elementId ID of the element to check, including leading #.
     699     */
     700    clear: function( elementId ) {
     701        var list     = this,
     702            $element = $( elementId ),
     703            type, tagName;
     704
     705        // Bail if we're within the list.
     706        if ( list.wpList && $element.parents( '#' + list.id ).length ) {
    411707            return;
    412 
    413         e.find(':input').each( function() {
    414             if ( $(this).parents('.form-no-clear').length )
     708        }
     709
     710        // Check each input field.
     711        $element.find( ':input' ).each( function( index, input ) {
     712
     713            // Bail if the form was marked to not to be cleared.
     714            if ( $( input ).parents( '.form-no-clear' ).length ) {
    415715                return;
    416 
    417             t = this.type.toLowerCase();
    418             tag = this.tagName.toLowerCase();
    419 
    420             if ( 'text' == t || 'password' == t || 'textarea' == tag )
    421                 this.value = '';
    422             else if ( 'checkbox' == t || 'radio' == t )
    423                 this.checked = false;
    424             else if ( 'select' == tag )
    425                 this.selectedIndex = null;
    426         });
    427     },
    428 
    429     process: function(el) {
    430         var list = this,
    431             $el = $(el || document);
    432 
    433         $el.delegate( 'form[data-wp-lists^="add:' + list.id + ':"]', 'submit', function(){
    434             return list.wpList.add(this);
    435         });
    436 
    437         $el.delegate( 'a[data-wp-lists^="add:' + list.id + ':"], input[data-wp-lists^="add:' + list.id + ':"]', 'click', function(){
    438             return list.wpList.add(this);
    439         });
    440 
    441         $el.delegate( '[data-wp-lists^="delete:' + list.id + ':"]', 'click', function(){
    442             return list.wpList.del(this);
    443         });
    444 
    445         $el.delegate( '[data-wp-lists^="dim:' + list.id + ':"]', 'click', function(){
    446             return list.wpList.dim(this);
    447         });
    448     },
    449 
     716            }
     717
     718            type    = input.type.toLowerCase();
     719            tagName = input.tagName.toLowerCase();
     720
     721            if ( 'text' === type || 'password' === type || 'textarea' === tagName ) {
     722                input.value = '';
     723
     724            } else if ( 'checkbox' === type || 'radio' === type ) {
     725                input.checked = false;
     726
     727            } else if ( 'select' === tagName ) {
     728                input.selectedIndex = null;
     729            }
     730        } );
     731    },
     732
     733    /**
     734     * Registers event handlers to add, delete, and dim items.
     735     *
     736     * @param {string} elementId
     737     */
     738    process: function( elementId ) {
     739        var list     = this,
     740            $element = $( elementId || document );
     741
     742        $element.on( 'submit', 'form[data-wp-lists^="add:' + list.id + ':"]', function() {
     743            return list.wpList.add( this );
     744        } );
     745
     746        $element.on( 'click', 'a[data-wp-lists^="add:' + list.id + ':"], input[data-wp-lists^="add:' + list.id + ':"]', function() {
     747            return list.wpList.add( this );
     748        } );
     749
     750        $element.on( 'click', '[data-wp-lists^="delete:' + list.id + ':"]', function() {
     751            return list.wpList.del( this );
     752        } );
     753
     754        $element.on( 'click', '[data-wp-lists^="dim:' + list.id + ':"]', function() {
     755            return list.wpList.dim( this );
     756        } );
     757    },
     758
     759    /**
     760     * Updates list item background colors.
     761     */
    450762    recolor: function() {
    451         var list = this, items, eo;
    452 
    453         if ( !list.wpList.settings.alt )
     763        var list    = this,
     764            evenOdd = [':even', ':odd'],
     765            items;
     766
     767        // Bail if there is no alternate class name specified.
     768        if ( ! list.wpList.settings.alt ) {
    454769            return;
    455 
    456         items = $('.list-item:visible', list);
    457 
    458         if ( !items.length )
    459             items = $(list).children(':visible');
    460 
    461         eo = [':even',':odd'];
    462 
    463         if ( list.wpList.settings.altOffset % 2 )
    464             eo.reverse();
    465 
    466         items.filter(eo[0]).addClass(list.wpList.settings.alt).end().filter(eo[1]).removeClass(list.wpList.settings.alt);
    467     },
    468 
     770        }
     771
     772        items = $( '.list-item:visible', list );
     773
     774        if ( ! items.length ) {
     775            items = $( list ).children( ':visible' );
     776        }
     777
     778        if ( list.wpList.settings.altOffset % 2 ) {
     779            evenOdd.reverse();
     780        }
     781
     782        items.filter( evenOdd[0] ).addClass( list.wpList.settings.alt ).end();
     783        items.filter( evenOdd[1] ).removeClass( list.wpList.settings.alt );
     784    },
     785
     786    /**
     787     * Sets up `process()` and `recolor()` functions.
     788     */
    469789    init: function() {
    470         var lists = this;
    471 
    472         lists.wpList.process = function(a) {
    473             lists.each( function() {
    474                 this.wpList.process(a);
     790        var $list = this;
     791
     792        $list.wpList.process = function() {
     793            $list.each( function( index, element ) {
     794                this.wpList.process( element );
    475795            } );
    476796        };
    477797
    478         lists.wpList.recolor = function() {
    479             lists.each( function() {
     798        $list.wpList.recolor = function() {
     799            $list.each( function() {
    480800                this.wpList.recolor();
    481801            } );
     
    484804};
    485805
     806/**
     807 * Initializes wpList object.
     808 *
     809 * @param {Object}           settings
     810 * @param {string}           settings.url         URL for ajax calls. Default: ajaxurl.
     811 * @param {string}           settings.type        The HTTP method to use for Ajax requests. Default: 'POST'.
     812 * @param {string}           settings.response    ID of the element the parsed ajax response will be stored in.
     813 *                                                Default: 'ajax-response'.
     814 *
     815 * @param {string}           settings.what        Default: ''.
     816 * @param {string}           settings.alt         CSS class name for alternate styling. Default: 'alternate'.
     817 * @param {number}           settings.altOffset   Offset to start alternate styling from. Default: 0.
     818 * @param {string}           settings.addColor    Hex code or 'none' to disable animation. Default: '#ffff33'.
     819 * @param {string}           settings.delColor    Hex code or 'none' to disable animation. Default: '#faafaa'.
     820 * @param {string}           settings.dimAddColor Hex code or 'none' to disable animation. Default: '#ffff33'.
     821 * @param {string}           settings.dimDelColor Hex code or 'none' to disable animation. Default: '#ff3333'.
     822 *
     823 * @param {wpList~confirm}   settings.confirm     Callback that's run before a request is made. Default: null.
     824 * @param {wpList~addBefore} settings.addBefore   Callback that's run before an item gets added to the list.
     825 *                                                Default: null.
     826 * @param {wpList~addAfter}  settings.addAfter    Callback that's run after an item got added to the list.
     827 *                                                Default: null.
     828 * @param {wpList~delBefore} settings.delBefore   Callback that's run before an item gets deleted from the list.
     829 *                                                Default: null.
     830 * @param {wpList~delAfter}  settings.delAfter    Callback that's run after an item got deleted from the list.
     831 *                                                Default: null.
     832 * @param {wpList~dimBefore} settings.dimBefore   Callback that's run before an item gets dim'd. Default: null.
     833 * @param {wpList~dimAfter}  settings.dimAfter    Callback that's run after an item got dim'd. Default: null.
     834 * @returns {$.fn} wpList API function.
     835 */
    486836$.fn.wpList = function( settings ) {
    487     this.each( function() {
    488         var _this = this;
    489 
    490         this.wpList = { settings: $.extend( {}, wpList.settings, { what: wpList.parseData(this,'list')[1] || '' }, settings ) };
    491         $.each( fs, function(i,f) { _this.wpList[i] = function( e, s ) { return wpList[f].call( _this, e, s ); }; } );
     837    this.each( function( index, list ) {
     838        list.wpList = {
     839            settings: $.extend( {}, wpList.settings, { what: wpList.parseData( list, 'list' )[1] || '' }, settings )
     840        };
     841
     842        $.each( functions, function( func, callback ) {
     843            list.wpList[func] = function( element, setting ) {
     844                return wpList[callback].call( list, element, setting );
     845            };
     846        } );
    492847    } );
    493848
    494     wpList.init.call(this);
    495 
     849    wpList.init.call( this );
    496850    this.wpList.process();
    497851
    498852    return this;
    499853};
    500 
    501 })(jQuery);
     854} ) ( jQuery );
Note: See TracChangeset for help on using the changeset viewer.