WordPress.org

Make WordPress Core

Ticket #36264: 36264.diff

File 36264.diff, 34.8 KB (added by obenland, 4 years ago)
  • src/wp-includes/js/wp-lists.js

     
    11/* global ajaxurl, wpAjax */
    2 (function($) {
    3 var fs = {add:'ajaxAdd',del:'ajaxDel',dim:'ajaxDim',process:'process',recolor:'recolor'}, wpList;
    4 
     2( function( $ ) {
     3var functions = {
     4                add:     'ajaxAdd',
     5                del:     'ajaxDel',
     6                dim:     'ajaxDim',
     7                process: 'process',
     8                recolor: 'recolor'
     9        }, wpList;
     10
     11/**
     12 * @namespace
     13 */
    514wpList = {
     15
     16        /**
     17         * @member {object}
     18         */
    619        settings: {
    7                 url: ajaxurl, type: 'POST',
     20
     21                /**
     22                 * URL for Ajax requests.
     23                 *
     24                 * @member {string}
     25                 */
     26                url: ajaxurl,
     27
     28                /**
     29                 * The HTTP method to use for Ajax requests.
     30                 *
     31                 * @member {string}
     32                 */
     33                type: 'POST',
     34
     35                /**
     36                 * ID of the element the parsed Ajax response will be stored in.
     37                 *
     38                 * @member {string}
     39                 */
    840                response: 'ajax-response',
    941
     42                /**
     43                 * The type of list.
     44                 *
     45                 * @member {string}
     46                 */
    1047                what: '',
    11                 alt: 'alternate', altOffset: 0,
    12                 addColor: null, delColor: null, dimAddColor: null, dimDelColor: null,
    1348
     49                /**
     50                 * CSS class name for alternate styling.
     51                 *
     52                 * @member {string}
     53                 */
     54                alt: 'alternate',
     55
     56                /**
     57                 * Offset to start alternate styling from.
     58                 *
     59                 * @member {number}
     60                 */
     61                altOffset: 0,
     62
     63                /**
     64                 * Color used in animation when adding an element.
     65                 *
     66                 * Can be 'none' to disable the animation.
     67                 *
     68                 * @member {string}
     69                 */
     70                addColor: '#ffff33',
     71
     72                /**
     73                 * Color used in animation when deleting an element.
     74                 *
     75                 * Can be 'none' to disable the animation.
     76                 *
     77                 * @member {string}
     78                 */
     79                delColor: '#faafaa',
     80
     81                /**
     82                 * Color used in dim add animation.
     83                 *
     84                 * Can be 'none' to disable the animation.
     85                 *
     86                 * @member {string}
     87                 */
     88                dimAddColor: '#ffff33',
     89
     90                /**
     91                 * Color used in dim delete animation.
     92                 *
     93                 * Can be 'none' to disable the animation.
     94                 *
     95                 * @member {string}
     96                 */
     97                dimDelColor: '#ff3333',
     98
     99                /**
     100                 * Callback that's run before a request is made.
     101                 *
     102                 * @callback wpList~confirm
     103                 * @param {object}      this
     104                 * @param {HTMLElement} list            The list DOM element.
     105                 * @param {object}      settings        Settings for the current list.
     106                 * @param {string}      action          The type of action to perform: 'add', 'delete', or 'dim'.
     107                 * @param {string}      backgroundColor Background color of the list's DOM element.
     108                 * @returns {boolean} Whether to proceed with the action or not.
     109                 */
    14110                confirm: null,
    15                 addBefore: null, addAfter: null,
    16                 delBefore: null, delAfter: null,
    17                 dimBefore: null, dimAfter: null
     111
     112                /**
     113                 * Callback that's run before an item gets added to the list.
     114                 *
     115                 * Allows to cancel the request.
     116                 *
     117                 * @callback wpList~addBefore
     118                 * @param {object} settings Settings for the Ajax request.
     119                 * @returns {object|boolean} Settings for the Ajax request or false to abort.
     120                 */
     121                addBefore: null,
     122
     123                /**
     124                 * Callback that's run after an item got added to the list.
     125                 *
     126                 * @callback wpList~addAfter
     127                 * @param {XML}    returnedResponse Raw response returned from the server.
     128                 * @param {object} settings         Settings for the Ajax request.
     129                 * @param {jqXHR}  settings.xml     jQuery XMLHttpRequest object.
     130                 * @param {string} settings.status  Status of the request: 'success', 'notmodified', 'nocontent', 'error',
     131                 *                                  'timeout', 'abort', or 'parsererror'.
     132                 * @param {object} settings.parsed  Parsed response object.
     133                 */
     134                addAfter: null,
     135
     136                /**
     137                 * Callback that's run before an item gets deleted from the list.
     138                 *
     139                 * Allows to cancel the request.
     140                 *
     141                 * @callback wpList~delBefore
     142                 * @param {object}      settings Settings for the Ajax request.
     143                 * @param {HTMLElement} list     The list DOM element.
     144                 * @returns {object|boolean} Settings for the Ajax request or false to abort.
     145                 */
     146                delBefore: null,
     147
     148                /**
     149                 * Callback that's run after an item got deleted from the list.
     150                 *
     151                 * @callback wpList~delAfter
     152                 * @param {XML}    returnedResponse Raw response returned from the server.
     153                 * @param {object} settings         Settings for the Ajax request.
     154                 * @param {jqXHR}  settings.xml     jQuery XMLHttpRequest object.
     155                 * @param {string} settings.status  Status of the request: 'success', 'notmodified', 'nocontent', 'error',
     156                 *                                  'timeout', 'abort', or 'parsererror'.
     157                 * @param {object} settings.parsed  Parsed response object.
     158                 */
     159                delAfter: null,
     160
     161                /**
     162                 * Callback that's run before an item gets dim'd.
     163                 *
     164                 * Allows to cancel the request.
     165                 *
     166                 * @callback wpList~dimBefore
     167                 * @param {object} settings Settings for the Ajax request.
     168                 * @returns {object|boolean} Settings for the Ajax request or false to abort.
     169                 */
     170                dimBefore: null,
     171
     172                /**
     173                 * Callback that's run after an item got dim'd.
     174                 *
     175                 * @callback wpList~dimAfter
     176                 * @param {XML}    returnedResponse Raw response returned from the server.
     177                 * @param {object} settings         Settings for the Ajax request.
     178                 * @param {jqXHR}  settings.xml     jQuery XMLHttpRequest object.
     179                 * @param {string} settings.status  Status of the request: 'success', 'notmodified', 'nocontent', 'error',
     180                 *                                  'timeout', 'abort', or 'parsererror'.
     181                 * @param {object} settings.parsed  Parsed response object.
     182                 */
     183                dimAfter: null
    18184        },
    19185
    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;
     186        /**
     187         * Finds a nonce.
     188         *
     189         * 1. Nonce in settings.
     190         * 2. `_ajax_nonce` value in element's href attribute.
     191         * 3. `_ajax_nonce` input field that is a descendant of element.
     192         * 4. `_wpnonce` value in element's href attribute.
     193         * 5. `_wpnonce` input field that is a descendant of element.
     194         * 6. 0 if none can be found.
     195         *
     196         * @param {jQuery} element  Element that triggered the request.
     197         * @param {object} settings Settings for the Ajax request.
     198         * @returns {string|number} Nonce
     199         */
     200        nonce: function( element, settings ) {
     201                var url      = wpAjax.unserialize( element.attr( 'href' ) ),
     202                        $element = $( '#' + settings.element );
     203
     204                return settings.nonce || url._ajax_nonce || $element.find( 'input[name="_ajax_nonce"]' ).val() || url._wpnonce || $element.find( 'input[name="_wpnonce"]' ).val() || 0;
    23205        },
    24206
    25207        /**
    26208         * Extract list item data from a DOM element.
    27209         *
    28          * @param  {HTMLElement} e The DOM element.
    29          * @param  {string}      t
    30          * @return {array}
     210         * Example 1: data-wp-lists="delete:the-comment-list:comment-{comment_ID}:66cc66:unspam=1"
     211         * Example 2: data-wp-lists="dim:the-comment-list:comment-{comment_ID}:unapproved:e7e7d3:e7e7d3:new=approved"
     212         *
     213         * Returns an unassociated array with the following data:
     214         * data[0] - Data identifier: 'list', 'add', 'delete', or 'dim'.
     215         * data[1] - ID of the corresponding list. If data[0] is 'list', the type of list ('comment', 'category', etc).
     216         * data[2] - ID of the parent element of all inputs necessary for the request.
     217         * data[3] - Hex color to be used in this request. If data[0] is 'dim', dim class.
     218         * data[4] - Additional arguments in query syntax that are added to the request. Example: 'post_id=1234'.
     219         *           If data[0] is 'dim', dim add color.
     220         * data[5] - Only available if data[0] is 'dim', dim delete color.
     221         * data[6] - Only available if data[0] is 'dim', additional arguments in query syntax that are added to the request.
     222         *
     223         * Result for Example 1:
     224         * data[0] - delete
     225         * data[1] - the-comment-list
     226         * data[2] - comment-{comment_ID}
     227         * data[3] - 66cc66
     228         * data[4] - unspam=1
     229         *
     230         * @param  {HTMLElement} element The DOM element.
     231         * @param  {string}      type    The type of data to look for: 'list', 'add', 'delete', or 'dim'.
     232         * @returns {Array}
    31233         */
    32         parseData: function(e,t) {
    33                 var d = [], wpListsData;
     234        parseData: function( element, type ) {
     235                var data = [], wpListsData;
    34236
    35237                try {
    36                         wpListsData = $(e).attr('data-wp-lists') || '';
    37                         wpListsData = wpListsData.match(new RegExp(t+':[\\S]+'));
     238                        wpListsData = $( element ).data( 'wp-lists' ) || '';
     239                        wpListsData = wpListsData.match( new RegExp( type + ':[\\S]+' ) );
    38240
    39                         if ( wpListsData )
    40                                 d = wpListsData[0].split(':');
    41                 } catch(r) {}
     241                        if ( wpListsData ) {
     242                                data = wpListsData[0].split( ':' );
     243                        }
     244                } catch( error ) {}
    42245
    43                 return d;
     246                return data;
    44247        },
    45248
    46         pre: function(e,s,a) {
    47                 var bg, r;
     249        /**
     250         * Calls a confirm callback to verify the action that is about to be performed.
     251         *
     252         * @param {HTMLElement} list     The DOM element.
     253         * @param {object}      settings Settings for this list.
     254         * @param {string}      action   The type of action to perform: 'add', 'delete', or 'dim'.
     255         * @returns {object|boolean} Settings if confirmed, false if not.
     256         */
     257        pre: function( list, settings, action ) {
     258                var $element, backgroundColor, confirmed;
    48259
    49                 s = $.extend( {}, this.wpList.settings, {
     260                settings = $.extend( {}, this.wpList.settings, {
    50261                        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');
     262                        nonce:   0,
     263                        target:  list.get( 0 )
     264                }, settings || {} );
     265
     266                if ( $.isFunction( settings.confirm ) ) {
     267                        $element = $( '#' + settings.element );
     268
     269                        if ( 'add' !== action ) {
     270                                backgroundColor = $element.css( 'backgroundColor' );
     271                                $element.css( 'backgroundColor', '#ff9966' );
    59272                        }
    60                         r = s.confirm.call(this, e, s, a, bg);
    61273
    62                         if ( 'add' != a )
    63                                 $('#' + s.element).css('backgroundColor', bg );
     274                        confirmed = settings.confirm.call( this, list, settings, action, backgroundColor );
    64275
    65                         if ( !r )
     276                        if ( 'add' !== action ) {
     277                                $element.css( 'backgroundColor', backgroundColor );
     278                        }
     279
     280                        if ( ! confirmed ) {
    66281                                return false;
     282                        }
    67283                }
    68284
    69                 return s;
     285                return settings;
    70286        },
    71287
    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' );
     288        /**
     289         * Adds an item to the list via AJAX.
     290         *
     291         * @param {HTMLElement} element  The DOM element.
     292         * @param {object}      settings Settings for this list.
     293         * @returns {boolean}
     294         */
     295        ajaxAdd: function( element, settings ) {
     296                var list     = this,
     297                        $element = $( element ),
     298                        data     = wpList.parseData( $element, 'add' ),
     299                        formValues, formData, parsedResponse, returnedResponse;
    78300
    79                 s.element = data[2] || e.attr( 'id' ) || s.element || null;
     301                settings = settings || {};
     302                settings = wpList.pre.call( list, $element, settings, 'add' );
    80303
    81                 if ( data[3] )
    82                         s.addColor = '#' + data[3];
    83                 else
    84                         s.addColor = s.addColor || '#FFFF33';
     304                settings.element  = data[2] || $element.prop( 'id' ) || settings.element || null;
     305                settings.addColor = data[3] ? '#' + data[3] : settings.addColor;
    85306
    86                 if ( !s )
     307                if ( ! settings )
    87308                        return false;
    88309
    89                 if ( !e.is('[id="' + s.element + '-submit"]') )
    90                         return !wpList.add.call( list, e, s );
     310                if ( ! $element.is( '[id="' + settings.element + '-submit"]' ) ) {
     311                        return ! wpList.add.call( list, $element, settings );
     312                }
    91313
    92                 if ( !s.element )
     314                if ( ! settings.element ) {
    93315                        return true;
     316                }
    94317
    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 );
     318                settings.action = 'add-' + settings.what;
     319                settings.nonce  = wpList.nonce( $element, settings );
    101320
    102                 if ( !valid )
     321                if ( ! wpAjax.validateForm( '#' + settings.element ) ) {
    103322                        return false;
     323                }
     324
     325                settings.data = $.param( $.extend( {
     326                        _ajax_nonce: settings.nonce,
     327                        action:      settings.action
     328                }, wpAjax.unserialize( data[4] || '' ) ) );
    104329
    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();
     330                formValues = $( '#' + settings.element + ' :input' ).not( '[name="_ajax_nonce"], [name="_wpnonce"], [name="action"]' );
     331                formData   = $.isFunction( formValues.fieldSerialize ) ? formValues.fieldSerialize() : formValues.serialize();
    107332
    108                 if ( formData )
    109                         s.data += '&' + formData;
     333                if ( formData ) {
     334                        settings.data += '&' + formData;
     335                }
    110336
    111                 if ( $.isFunction(s.addBefore) ) {
    112                         s = s.addBefore( s );
    113                         if ( !s )
     337                if ( $.isFunction( settings.addBefore ) ) {
     338                        settings = settings.addBefore( settings );
     339                        if ( ! settings ) {
    114340                                return true;
     341                        }
    115342                }
    116343
    117                 if ( !s.data.match(/_ajax_nonce=[a-f0-9]+/) )
     344                if ( ! settings.data.match( /_ajax_nonce=[a-f0-9]+/ ) ) {
    118345                        return true;
     346                }
    119347
    120                 s.success = function(r) {
    121                         res = wpAjax.parseAjaxResponse(r, s.response, s.element);
    122 
    123                         rres = r;
     348                settings.success = function( response ) {
     349                        parsedResponse   = wpAjax.parseAjaxResponse( response, settings.response, settings.element );
     350                        returnedResponse = response;
    124351
    125                         if ( !res || res.errors )
     352                        if ( ! parsedResponse || parsedResponse.errors ) {
    126353                                return false;
     354                        }
    127355
    128                         if ( true === res )
     356                        if ( true === parsedResponse ) {
    129357                                return true;
     358                        }
    130359
    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
     360                        $.each( parsedResponse.responses, function() {
     361                                wpList.add.call( list, this.data, $.extend( {}, settings, { // this.firstChild.nodevalue
     362                                        position: this.position || 0,
     363                                        id:       this.id || 0,
     364                                        oldId:    this.oldId || null
    136365                                } ) );
    137366                        } );
    138367
    139368                        list.wpList.recolor();
    140                         $(list).trigger( 'wpListAddEnd', [ s, list.wpList ] );
    141                         wpList.clear.call(list,'#' + s.element);
     369                        $( list ).trigger( 'wpListAddEnd', [ settings, list.wpList ] );
     370                        wpList.clear.call( list, '#' + settings.element );
    142371                };
    143372
    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 );
     373                settings.complete = function( jqXHR, status ) {
     374                        if ( $.isFunction( settings.addAfter ) ) {
     375                                settings.addAfter( returnedResponse, $.extend( { xml: jqXHR, status: status, parsed: parsedResponse }, settings ) );
    148376                        }
    149377                };
    150378
    151                 $.ajax( s );
     379                $.ajax( settings );
    152380                return false;
    153381        },
    154382
    155383        /**
    156384         * Delete an item in the list via AJAX.
    157385         *
    158          * @param  {HTMLElement} e A DOM element containing item data.
    159          * @param  {Object}      s
    160          * @return {boolean}
     386         * @param {HTMLElement} element A DOM element containing item data.
     387         * @param {object}      settings Settings for this list.
     388         * @returns {boolean}
    161389         */
    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' );
     390        ajaxDel: function( element, settings ) {
     391                var list     = this,
     392                        $element = $( element ),
     393                        data     = wpList.parseData( $element, 'delete' ),
     394                        $eventTarget, parsedResponse, returnedResponse;
    168395
    169                 s.element = data[2] || s.element || null;
     396                settings = settings || {};
     397                settings = wpList.pre.call( list, $element, settings, 'delete' );
    170398
    171                 if ( data[3] )
    172                         s.delColor = '#' + data[3];
    173                 else
    174                         s.delColor = s.delColor || '#faa';
     399                settings.element  = data[2] || settings.element || null;
     400                settings.delColor = data[3] ? '#' + data[3] : settings.delColor;
    175401
    176                 if ( !s || !s.element )
     402                if ( ! settings || ! settings.element ) {
    177403                        return false;
     404                }
    178405
    179                 s.action = 'delete-' + s.what;
    180 
    181                 s.nonce = wpList.nonce(e,s);
     406                settings.action = 'delete-' + settings.what;
     407                settings.nonce  = wpList.nonce( $element, settings );
    182408
    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 )
     409                settings.data = $.extend( {
     410                        _ajax_nonce: settings.nonce,
     411                        action:      settings.action,
     412                        id:          settings.element.split( '-' ).pop()
     413                }, wpAjax.unserialize( data[4] || '' ) );
     414
     415                if ( $.isFunction( settings.delBefore) ) {
     416                        settings = settings.delBefore( settings, list );
     417                        if ( ! settings ) {
    191418                                return true;
     419                        }
    192420                }
    193421
    194                 if ( !s.data._ajax_nonce )
     422                if ( ! settings.data._ajax_nonce ) {
    195423                        return true;
     424                }
    196425
    197                 element = $('#' + s.element);
     426                $eventTarget = $( '#' + settings.element );
    198427
    199                 if ( 'none' != s.delColor ) {
    200                         element.css( 'backgroundColor', s.delColor ).fadeOut( 350, function(){
     428                if ( 'none' !== settings.delColor ) {
     429                        $eventTarget.css( 'backgroundColor', settings.delColor ).fadeOut( 350, function(){
    201430                                list.wpList.recolor();
    202                                 $(list).trigger( 'wpListDelEnd', [ s, list.wpList ] );
     431                                $( list ).trigger( 'wpListDelEnd', [ settings, list.wpList ] );
    203432                        });
    204433                } else {
    205434                        list.wpList.recolor();
    206                         $(list).trigger( 'wpListDelEnd', [ s, list.wpList ] );
     435                        $( list ).trigger( 'wpListDelEnd', [ settings, list.wpList ] );
    207436                }
    208437
    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(); } );
     438                settings.success = function( response ) {
     439                        parsedResponse   = wpAjax.parseAjaxResponse( response, settings.response, settings.element );
     440                        returnedResponse = response;
     441                        wpList.clear.call( list, '#' + settings.element );
     442
     443                        if ( ! parsedResponse || parsedResponse.errors ) {
     444                                $eventTarget.stop().stop().css( 'backgroundColor', '#faa' ).show().queue( function() {
     445                                        list.wpList.recolor();
     446                                        $( this ).dequeue();
     447                                } );
    215448                                return false;
    216449                        }
    217450                };
    218451
    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 );
     452                settings.complete = function( jqXHR, status ) {
     453                        if ( $.isFunction( settings.delAfter ) ) {
     454                                $eventTarget.queue( function() {
     455                                        settings.delAfter( returnedResponse, $.extend( { xml: jqXHR, status: status, parsed: parsedResponse }, settings ) );
    224456                                }).dequeue();
    225457                        }
    226458                };
    227459
    228                 $.ajax( s );
     460                $.ajax( settings );
    229461                return false;
    230462        },
    231463
    232         ajaxDim: function( e, s ) {
    233                 if ( $(e).parent().css('display') == 'none' ) // Prevent hidden links from being clicked by hotkeys
    234                         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' );
     464        /**
     465         * Dim an item in the list via AJAX.
     466         *
     467         * @param {HTMLElement} element  A DOM element containing item data.
     468         * @param {object}      settings Settings for this list.
     469         * @returns {boolean}
     470         */
     471        ajaxDim: function( element, settings ) {
     472                var list     = this,
     473                        $element = $( element ),
     474                        data     = wpList.parseData( $element, 'dim' ),
     475                        $eventTarget, isClass, color, dimColor, parsedResponse, returnedResponse;
    242476
    243                 s.element = data[2] || s.element || null;
    244                 s.dimClass =  data[3] || s.dimClass || null;
     477                // Prevent hidden links from being clicked by hotkeys.
     478                if ( 'none' === $element.parent().css( 'display' ) ) {
     479                        return false;
     480                }
    245481
    246                 if ( data[4] )
    247                         s.dimAddColor = '#' + data[4];
    248                 else
    249                         s.dimAddColor = s.dimAddColor || '#FFFF33';
     482                settings = settings || {};
     483                settings = wpList.pre.call( list, $element, settings, 'dim' );
    250484
    251                 if ( data[5] )
    252                         s.dimDelColor = '#' + data[5];
    253                 else
    254                         s.dimDelColor = s.dimDelColor || '#FF3333';
     485                settings.element     = data[2] || settings.element  || null;
     486                settings.dimClass    = data[3] || settings.dimClass || null;
     487                settings.dimAddColor = data[4] ? '#' + data[4] : settings.dimAddColor;
     488                settings.dimDelColor = data[5] ? '#' + data[5] : settings.dimDelColor;
    255489
    256                 if ( !s || !s.element || !s.dimClass )
     490                if ( ! settings || ! settings.element || ! settings.dimClass ) {
    257491                        return true;
     492                }
    258493
    259                 s.action = 'dim-' + s.what;
    260 
    261                 s.nonce = wpList.nonce(e,s);
     494                settings.action = 'dim-' + settings.what;
     495                settings.nonce  = wpList.nonce( $element, settings );
    262496
    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 )
     497                settings.data = $.extend( {
     498                        _ajax_nonce : settings.nonce,
     499                        action:       settings.action,
     500                        id:           settings.element.split( '-' ).pop(),
     501                        dimClass:     settings.dimClass
     502                }, wpAjax.unserialize( data[6] || '' ) );
     503
     504                if ( $.isFunction( settings.dimBefore ) ) {
     505                        settings = settings.dimBefore( settings );
     506                        if ( ! settings ) {
    271507                                return true;
     508                        }
    272509                }
    273510
    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;
     511                $eventTarget = $( '#' + settings.element );
     512                isClass      = $eventTarget.toggleClass( settings.dimClass ).is( '.' + settings.dimClass );
     513                color        = wpList.getColor( $eventTarget );
     514                dimColor     = isClass ? settings.dimAddColor : settings.dimDelColor;
     515                $eventTarget.toggleClass( settings.dimClass );
    279516
    280                 if ( 'none' != dimColor ) {
    281                         element
     517                if ( 'none' !== dimColor ) {
     518                        $eventTarget
    282519                                .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 ] );
     520                                .queue( function() { $eventTarget.toggleClass( settings.dimClass); $( this ).dequeue(); } )
     521                                .animate( { backgroundColor: color }, {
     522                                        complete: function() {
     523                                                $( this ).css( 'backgroundColor', '' );
     524                                                $( list ).trigger( 'wpListDimEnd', [ settings, list.wpList ] );
    287525                                        }
    288526                                });
    289527                } else {
    290                         $(list).trigger( 'wpListDimEnd', [ s, list.wpList ] );
     528                        $( list ).trigger( 'wpListDimEnd', [ settings, list.wpList ] );
    291529                }
    292530
    293                 if ( !s.data._ajax_nonce )
     531                if ( ! settings.data._ajax_nonce ) {
    294532                        return true;
     533                }
    295534
    296                 s.success = function(r) {
    297                         res = wpAjax.parseAjaxResponse(r, s.response, s.element);
    298                         rres = r;
    299 
    300                         if ( !res || res.errors ) {
    301                                 element.stop().stop().css( 'backgroundColor', '#FF3333' )[isClass?'removeClass':'addClass'](s.dimClass).show().queue( function() { list.wpList.recolor(); $(this).dequeue(); } );
     535                settings.success = function( response ) {
     536                        parsedResponse   = wpAjax.parseAjaxResponse( response, settings.response, settings.element);
     537                        returnedResponse = response;
     538
     539                        if ( ! parsedResponse || parsedResponse.errors ) {
     540                                $eventTarget.stop().stop().css( 'backgroundColor', '#ff3333' )[ isClass ? 'removeClass' : 'addClass' ]( settings.dimClass ).show().queue( function() {
     541                                        list.wpList.recolor();
     542                                        $( this ).dequeue();
     543                                } );
    302544                                return false;
    303545                        }
    304546                };
    305547
    306                 s.complete = function(x, st) {
    307                         if ( $.isFunction(s.dimAfter) ) {
    308                                 element.queue( function() {
    309                                         var _s = $.extend( { xml: x, status: st, parsed: res }, s );
    310                                         s.dimAfter( rres, _s );
    311                                 }).dequeue();
     548                settings.complete = function( jqXHR, status ) {
     549                        if ( $.isFunction( settings.dimAfter ) ) {
     550                                $eventTarget.queue( function() {
     551                                        settings.dimAfter( returnedResponse, $.extend( { xml: jqXHR, status: status, parsed: parsedResponse }, settings ) );
     552                                } ).dequeue();
    312553                        }
    313554                };
    314555
    315                 $.ajax( s );
     556                $.ajax( settings );
    316557                return false;
    317558        },
    318559
    319         getColor: function( el ) {
    320                 var color = jQuery(el).css('backgroundColor');
    321 
    322                 return color || '#ffffff';
     560        /**
     561         * Returns the background color of the passed element.
     562         *
     563         * @param {jQuery|string} element Element to check.
     564         * @returns {string} Background color value in HEX. Default: '#ffffff'.
     565         */
     566        getColor: function( element ) {
     567                return $( element ).css( 'backgroundColor' ) || '#ffffff';
    323568        },
    324569
    325         add: function( e, s ) {
    326                 if ( 'string' == typeof e ) {
    327                         e = $( $.trim( e ) ); // Trim leading whitespaces
    328                 } else {
    329                         e = $( e );
    330                 }
    331 
    332                 var list = $(this), old = false, _s = { pos: 0, id: 0, oldId: null }, ba, ref, color;
     570        /**
     571         * Adds something.
     572         *
     573         * @param {HTMLElement} element  A DOM element containing item data.
     574         * @param {object}      settings Settings for this list.
     575         * @returns {boolean}
     576         */
     577        add: function( element, settings ) {
     578                var $list    = $( this ),
     579                        $element = $( element ),
     580                        old      = false,
     581                        position, reference;
    333582
    334                 if ( 'string' == typeof s )
    335                         s = { what: s };
     583                if ( 'string' === typeof settings ) {
     584                        settings = { what: settings };
     585                }
    336586
    337                 s = $.extend(_s, this.wpList.settings, s);
     587                settings = $.extend( { position: 0, id: 0, oldId: null }, this.wpList.settings, settings );
    338588
    339                 if ( !e.length || !s.what )
     589                if ( ! $element.length || ! settings.what ) {
    340590                        return false;
     591                }
    341592
    342                 if ( s.oldId )
    343                         old = $('#' + s.what + '-' + s.oldId);
     593                if ( settings.oldId ) {
     594                        old = $( '#' + settings.what + '-' + settings.oldId );
     595                }
    344596
    345                 if ( s.id && ( s.id != s.oldId || !old || !old.length ) )
    346                         $('#' + s.what + '-' + s.id).remove();
     597                if ( settings.id && ( settings.id !== settings.oldId || ! old || ! old.length ) ) {
     598                        $( '#' + settings.what + '-' + settings.id ).remove();
     599                }
    347600
    348601                if ( old && old.length ) {
    349                         old.before(e);
     602                        old.before( $element );
    350603                        old.remove();
    351                 } else if ( isNaN(s.pos) ) {
    352                         ba = 'after';
    353604
    354                         if ( '-' == s.pos.substr(0,1) ) {
    355                                 s.pos = s.pos.substr(1);
    356                                 ba = 'before';
     605                } else if ( isNaN( settings.position ) ) {
     606                        position = 'after';
     607
     608                        if ( '-' === settings.position.substr( 0, 1 ) ) {
     609                                settings.position = settings.position.substr( 1 );
     610                                position          = 'before';
    357611                        }
    358612
    359                         ref = list.find( '#' + s.pos );
     613                        reference = $list.find( '#' + settings.position );
    360614
    361                         if ( 1 === ref.length )
    362                                 ref[ba](e);
    363                         else
    364                                 list.append(e);
     615                        if ( 1 === reference.length ) {
     616                                reference[ position ]( $element );
     617                        } else {
     618                                $list.append( $element );
     619                        }
    365620
    366                 } else if ( 'comment' != s.what || 0 === $('#' + s.element).length ) {
    367                         if ( s.pos < 0 ) {
    368                                 list.prepend(e);
     621                } else if ( 'comment' != settings.what || 0 === $( '#' + settings.element ).length ) {
     622                        if ( settings.position < 0 ) {
     623                                $list.prepend( $element );
    369624                        } else {
    370                                 list.append(e);
     625                                $list.append( $element );
    371626                        }
    372627                }
    373628
    374                 if ( s.alt ) {
    375                         if ( ( list.children(':visible').index( e[0] ) + s.altOffset ) % 2 ) { e.removeClass( s.alt ); }
    376                         else { e.addClass( s.alt ); }
     629                if ( settings.alt ) {
     630                        $element.toggleClass( settings.alt, ( $list.children(':visible').index( $element[0] ) + settings.altOffset ) % 2 );
    377631                }
    378632
    379                 if ( 'none' != s.addColor ) {
    380                         color = wpList.getColor( e );
    381                         e.css( 'backgroundColor', s.addColor ).animate( { backgroundColor: color }, { complete: function() { $(this).css( 'backgroundColor', '' ); } } );
     633                if ( 'none' !== settings.addColor ) {
     634                        $element.css( 'backgroundColor', settings.addColor ).animate( { backgroundColor: wpList.getColor( $element ) }, { complete: function() {
     635                                $( this ).css( 'backgroundColor', '' );
     636                        } } );
    382637                }
    383                 list.each( function() { this.wpList.process( e ); } );
    384                 return e;
    385         },
    386638
    387         clear: function(e) {
    388                 var list = this, t, tag;
     639                // Add event handlers.
     640                $list.each( function( index, list ) {
     641                        list.wpList.process( $element );
     642                } );
    389643
    390                 e = $(e);
     644                return $element;
     645        },
    391646
    392                 if ( list.wpList && e.parents( '#' + list.id ).length )
     647        /**
     648         * Clears all input fields within the element passed.
     649         *
     650         * @param {string} elementId ID of the element to check, including leading #.
     651         */
     652        clear: function( elementId ) {
     653                var list     = this,
     654                        $element = $( elementId ),
     655                        type, tagName;
     656
     657                // Bail if we're within the list.
     658                if ( list.wpList && $element.parents( '#' + list.id ).length ) {
    393659                        return;
     660                }
    394661
    395                 e.find(':input').each( function() {
    396                         if ( $(this).parents('.form-no-clear').length )
     662                // Check each input field.
     663                $element.find( ':input' ).each( function( index, input ) {
     664
     665                        // Bail if the form was marked to not to be cleared.
     666                        if ( $( input ).parents( '.form-no-clear' ).length ) {
    397667                                return;
     668                        }
     669
     670                        type    = input.type.toLowerCase();
     671                        tagName = input.tagName.toLowerCase();
    398672
    399                         t = this.type.toLowerCase();
    400                         tag = this.tagName.toLowerCase();
     673                        if ( 'text' === type || 'password' === type || 'textarea' === tagName ) {
     674                                input.value = '';
    401675
    402                         if ( 'text' == t || 'password' == t || 'textarea' == tag )
    403                                 this.value = '';
    404                         else if ( 'checkbox' == t || 'radio' == t )
    405                                 this.checked = false;
    406                         else if ( 'select' == tag )
    407                                 this.selectedIndex = null;
     676                        } else if ( 'checkbox' === type || 'radio' === type ) {
     677                                input.checked = false;
     678
     679                        } else if ( 'select' === tagName ) {
     680                                input.selectedIndex = null;
     681                        }
    408682                });
    409683        },
    410684
    411         process: function(el) {
    412                 var list = this,
    413                         $el = $(el || document);
     685        /**
     686         * Registers event handlers to add, delete, and dim items.
     687         *
     688         * @param {string} elementId
     689         */
     690        process: function( elementId ) {
     691                var list     = this,
     692                        $element = $( elementId || document );
    414693
    415                 $el.delegate( 'form[data-wp-lists^="add:' + list.id + ':"]', 'submit', function(){
    416                         return list.wpList.add(this);
     694                $element.on( 'submit', 'form[data-wp-lists^="add:' + list.id + ':"]', function() {
     695                        return list.wpList.add( this );
    417696                });
    418697
    419                 $el.delegate( 'a[data-wp-lists^="add:' + list.id + ':"], input[data-wp-lists^="add:' + list.id + ':"]', 'click', function(){
    420                         return list.wpList.add(this);
     698                $element.on( 'click', 'a[data-wp-lists^="add:' + list.id + ':"], input[data-wp-lists^="add:' + list.id + ':"]', function() {
     699                        return list.wpList.add( this );
    421700                });
    422701
    423                 $el.delegate( '[data-wp-lists^="delete:' + list.id + ':"]', 'click', function(){
    424                         return list.wpList.del(this);
     702                $element.on( 'click', '[data-wp-lists^="delete:' + list.id + ':"]', function() {
     703                        return list.wpList.del( this );
    425704                });
    426705
    427                 $el.delegate( '[data-wp-lists^="dim:' + list.id + ':"]', 'click', function(){
    428                         return list.wpList.dim(this);
     706                $element.on( 'click', '[data-wp-lists^="dim:' + list.id + ':"]', function() {
     707                        return list.wpList.dim( this );
    429708                });
    430709        },
    431710
     711        /**
     712         * Updates list item background colors.
     713         */
    432714        recolor: function() {
    433                 var list = this, items, eo;
     715                var list    = this,
     716                        evenOdd = [':even',':odd'],
     717                        items;
    434718
    435                 if ( !list.wpList.settings.alt )
     719                // Bail if there is no alternate class name specified.
     720                if ( ! list.wpList.settings.alt ) {
    436721                        return;
     722                }
    437723
    438                 items = $('.list-item:visible', list);
    439 
    440                 if ( !items.length )
    441                         items = $(list).children(':visible');
     724                items = $( '.list-item:visible', list );
    442725
    443                 eo = [':even',':odd'];
     726                if ( ! items.length ) {
     727                        items = $( list ).children( ':visible' );
     728                }
    444729
    445                 if ( list.wpList.settings.altOffset % 2 )
    446                         eo.reverse();
     730                if ( list.wpList.settings.altOffset % 2 ) {
     731                        evenOdd.reverse();
     732                }
    447733
    448                 items.filter(eo[0]).addClass(list.wpList.settings.alt).end().filter(eo[1]).removeClass(list.wpList.settings.alt);
     734                items.filter( evenOdd[0] ).addClass( list.wpList.settings.alt ).end();
     735                items.filter( evenOdd[1] ).removeClass( list.wpList.settings.alt );
    449736        },
    450737
     738        /**
     739         * Sets up `process()` and `recolor()` functions.
     740         */
    451741        init: function() {
    452                 var lists = this;
     742                var $list = this;
    453743
    454                 lists.wpList.process = function(a) {
    455                         lists.each( function() {
    456                                 this.wpList.process(a);
     744                $list.wpList.process = function() {
     745                        $list.each( function( index, element ) {
     746                                this.wpList.process( element );
    457747                        } );
    458748                };
    459749
    460                 lists.wpList.recolor = function() {
    461                         lists.each( function() {
     750                $list.wpList.recolor = function() {
     751                        $list.each( function() {
    462752                                this.wpList.recolor();
    463753                        } );
    464754                };
    465755        }
    466756};
    467757
     758/**
     759 * Initializes wpList object.
     760 *
     761 * @param {Object}           settings
     762 * @param {string}           settings.url         URL for ajax calls. Default: ajaxurl.
     763 * @param {string}           settings.type        The HTTP method to use for Ajax requests. Default: 'POST'.
     764 * @param {string}           settings.response    ID of the element the parsed ajax response will be stored in.
     765 *                                                Default: 'ajax-response'.
     766 *
     767 * @param {string}           settings.what        Default: ''.
     768 * @param {string}           settings.alt         CSS class name for alternate styling. Default: 'alternate'.
     769 * @param {number}           settings.altOffset   Offset to start alternate styling from. Default: 0.
     770 * @param {string}           settings.addColor    Hex code or 'none' to disable animation. Default: '#ffff33'.
     771 * @param {string}           settings.delColor    Hex code or 'none' to disable animation. Default: '#faafaa'.
     772 * @param {string}           settings.dimAddColor Hex code or 'none' to disable animation. Default: '#ffff33'.
     773 * @param {string}           settings.dimDelColor Hex code or 'none' to disable animation. Default: '#ff3333'.
     774 *
     775 * @param {wpList~confirm}   settings.confirm     Callback that's run before a request is made. Default: null.
     776 * @param {wpList~addBefore} settings.addBefore   Callback that's run before an item gets added to the list.
     777 *                                                Default: null.
     778 * @param {wpList~addAfter}  settings.addAfter    Callback that's run after an item got added to the list.
     779 *                                                Default: null.
     780 * @param {wpList~delBefore} settings.delBefore   Callback that's run before an item gets deleted from the list.
     781 *                                                Default: null.
     782 * @param {wpList~delAfter}  settings.delAfter    Callback that's run after an item got deleted from the list.
     783 *                                                Default: null.
     784 * @param {wpList~dimBefore} settings.dimBefore   Callback that's run before an item gets dim'd. Default: null.
     785 * @param {wpList~dimAfter}  settings.dimAfter    Callback that's run after an item got dim'd. Default: null.
     786 * @returns {$.fn}
     787 */
    468788$.fn.wpList = function( settings ) {
    469         this.each( function() {
    470                 var _this = this;
     789        this.each( function( index, list ) {
     790                list.wpList = {
     791                        settings: $.extend( {}, wpList.settings, { what: wpList.parseData( list, 'list' )[1] || '' }, settings )
     792                };
    471793
    472                 this.wpList = { settings: $.extend( {}, wpList.settings, { what: wpList.parseData(this,'list')[1] || '' }, settings ) };
    473                 $.each( fs, function(i,f) { _this.wpList[i] = function( e, s ) { return wpList[f].call( _this, e, s ); }; } );
     794                $.each( functions, function( func, callback ) {
     795                        list.wpList[ func ] = function( element, setting ) {
     796                                return wpList[ callback ].call( list, element, setting );
     797                        };
     798                } );
    474799        } );
    475800
    476         wpList.init.call(this);
    477 
     801        wpList.init.call( this );
    478802        this.wpList.process();
    479803
    480804        return this;