home *** CD-ROM | disk | FTP | other *** search
/ HTML Examples / WP.iso / wordpress2 / wp-includes / js / wp-lists.js < prev    next >
Encoding:
Text File  |  2016-10-03  |  24.6 KB  |  855 lines

  1. /* global ajaxurl, wpAjax */
  2.  
  3. /**
  4.  * @param {jQuery} $ jQuery object.
  5.  */
  6. ( function( $ ) {
  7. var functions = {
  8.     add:     'ajaxAdd',
  9.     del:     'ajaxDel',
  10.     dim:     'ajaxDim',
  11.     process: 'process',
  12.     recolor: 'recolor'
  13. }, wpList;
  14.  
  15. /**
  16.  * @namespace
  17.  */
  18. wpList = {
  19.  
  20.     /**
  21.      * @member {object}
  22.      */
  23.     settings: {
  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.          */
  44.         response: 'ajax-response',
  45.  
  46.         /**
  47.          * The type of list.
  48.          *
  49.          * @member {string}
  50.          */
  51.         what: '',
  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.          */
  114.         confirm: null,
  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;
  209.     },
  210.  
  211.     /**
  212.      * Extract list item data from a DOM element.
  213.      *
  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;
  240.  
  241.         try {
  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, {
  265.             element: null,
  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 ) {
  285.                 return false;
  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 ) {
  312.             return false;
  313.         }
  314.  
  315.         if ( ! $element.is( '[id="' + settings.element + '-submit"]' ) ) {
  316.             return ! wpList.add.call( list, $element, settings );
  317.         }
  318.  
  319.         if ( ! settings.element ) {
  320.             return true;
  321.         }
  322.  
  323.         settings.action = 'add-' + settings.what;
  324.         settings.nonce  = wpList.nonce( $element, settings );
  325.  
  326.         if ( ! wpAjax.validateForm( '#' + settings.element ) ) {
  327.             return false;
  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 ) {
  346.                 return true;
  347.             }
  348.         }
  349.  
  350.         if ( ! settings.data.match( /_ajax_nonce=[a-f0-9]+/ ) ) {
  351.             return true;
  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 ) {
  359.                 return false;
  360.             }
  361.  
  362.             if ( true === parsedResponse ) {
  363.                 return true;
  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
  371.                 } ) );
  372.             } );
  373.  
  374.             list.wpList.recolor();
  375.             $( list ).trigger( 'wpListAddEnd', [ settings, list.wpList ] );
  376.             wpList.clear.call( list, '#' + settings.element );
  377.         };
  378.  
  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 ) );
  386.             }
  387.         };
  388.  
  389.         $.ajax( settings );
  390.  
  391.         return false;
  392.     },
  393.  
  394.     /**
  395.      * Delete an item in the list via AJAX.
  396.      *
  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 ) {
  414.             return false;
  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 ) {
  430.                 return true;
  431.             }
  432.         }
  433.  
  434.         if ( ! settings.data._ajax_nonce ) {
  435.             return true;
  436.         }
  437.  
  438.         $eventTarget = $( '#' + settings.element );
  439.  
  440.         if ( 'none' !== settings.delColor ) {
  441.             $eventTarget.css( 'backgroundColor', settings.delColor ).fadeOut( 350, function() {
  442.                 list.wpList.recolor();
  443.                 $( list ).trigger( 'wpListDelEnd', [ settings, list.wpList ] );
  444.             } );
  445.         } else {
  446.             list.wpList.recolor();
  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.  
  460.                 return false;
  461.             }
  462.         };
  463.  
  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();
  473.             }
  474.         };
  475.  
  476.         $.ajax( settings );
  477.  
  478.         return false;
  479.     },
  480.  
  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' ) ) {
  496.             return false;
  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 ) {
  508.             return true;
  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 ) {
  525.                 return true;
  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
  537.                 .animate( { backgroundColor: dimColor }, 'fast' )
  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 ] );
  546.                     }
  547.                 } );
  548.         } else {
  549.             $( list ).trigger( 'wpListDimEnd', [ settings, list.wpList ] );
  550.         }
  551.  
  552.         if ( ! settings.data._ajax_nonce ) {
  553.             return true;
  554.         }
  555.  
  556.         settings.success = function( response ) {
  557.             parsedResponse   = wpAjax.parseAjaxResponse( response, settings.response, settings.element );
  558.             returnedResponse = response;
  559.  
  560.             if ( true === parsedResponse ) {
  561.                 return true;
  562.             }
  563.  
  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.  
  570.                 return false;
  571.             }
  572.  
  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' );
  577.  
  578.                 // Comment is approved; link the date field.
  579.                 if ( '' !== parsedResponse.responses[0].supplemental.comment_link ) {
  580.                     $submittedOn.html( $('<a></a>').text( $submittedOn.text() ).prop( 'href', parsedResponse.responses[0].supplemental.comment_link ) );
  581.  
  582.                 // Comment is not approved; unlink the date field.
  583.                 } else if ( $commentLink.length ) {
  584.                     $submittedOn.text( $commentLink.text() );
  585.                 }
  586.             }
  587.         };
  588.  
  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();
  598.             }
  599.         };
  600.  
  601.         $.ajax( settings );
  602.  
  603.         return false;
  604.     },
  605.  
  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 ) {
  636.             return false;
  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.         }
  646.  
  647.         if ( old && old.length ) {
  648.             old.before( $element );
  649.             old.remove();
  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 );
  663.             } else {
  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 ) {
  707.             return;
  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 ) {
  715.                 return;
  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.      */
  762.     recolor: function() {
  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 ) {
  769.             return;
  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.      */
  789.     init: function() {
  790.         var $list = this;
  791.  
  792.         $list.wpList.process = function( element ) {
  793.             $list.each( function() {
  794.                 this.wpList.process( element );
  795.             } );
  796.         };
  797.  
  798.         $list.wpList.recolor = function() {
  799.             $list.each( function() {
  800.                 this.wpList.recolor();
  801.             } );
  802.         };
  803.     }
  804. };
  805.  
  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.  */
  836. $.fn.wpList = function( settings ) {
  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.         } );
  847.     } );
  848.  
  849.     wpList.init.call( this );
  850.     this.wpList.process();
  851.  
  852.     return this;
  853. };
  854. } ) ( jQuery );
  855.