balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

wp-lists.js (25315B)


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