wp/wp-includes/js/comment-reply.js
changeset 16 a86126ab1dd4
parent 9 177826044cd9
child 18 be944660c56a
equal deleted inserted replaced
15:3d4e9c994f10 16:a86126ab1dd4
    12 	// Avoid scope lookups on commonly used variables.
    12 	// Avoid scope lookups on commonly used variables.
    13 	var document = window.document;
    13 	var document = window.document;
    14 
    14 
    15 	// Settings.
    15 	// Settings.
    16 	var config = {
    16 	var config = {
    17 		commentReplyClass : 'comment-reply-link',
    17 		commentReplyClass   : 'comment-reply-link',
    18 		cancelReplyId     : 'cancel-comment-reply-link',
    18 		commentReplyTitleId : 'reply-title',
    19 		commentFormId     : 'commentform',
    19 		cancelReplyId       : 'cancel-comment-reply-link',
    20 		temporaryFormId   : 'wp-temp-form-div',
    20 		commentFormId       : 'commentform',
    21 		parentIdFieldId   : 'comment_parent',
    21 		temporaryFormId     : 'wp-temp-form-div',
    22 		postIdFieldId     : 'comment_post_ID'
    22 		parentIdFieldId     : 'comment_parent',
       
    23 		postIdFieldId       : 'comment_post_ID'
    23 	};
    24 	};
    24 
    25 
    25 	// Cross browser MutationObserver.
    26 	// Cross browser MutationObserver.
    26 	var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
    27 	var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
    27 
    28 
    93 		}
    94 		}
    94 
    95 
    95 		cancelElement.addEventListener( 'touchstart', cancelEvent );
    96 		cancelElement.addEventListener( 'touchstart', cancelEvent );
    96 		cancelElement.addEventListener( 'click',      cancelEvent );
    97 		cancelElement.addEventListener( 'click',      cancelEvent );
    97 
    98 
       
    99 		// Submit the comment form when the user types [Ctrl] or [Cmd] + [Enter].
       
   100 		var submitFormHandler = function( e ) {
       
   101 			if ( ( e.metaKey || e.ctrlKey ) && e.keyCode === 13 ) {
       
   102 				commentFormElement.removeEventListener( 'keydown', submitFormHandler );
       
   103 				e.preventDefault();
       
   104 				// The submit button ID is 'submit' so we can't call commentFormElement.submit(). Click it instead.
       
   105 				commentFormElement.submit.click();
       
   106 				return false;
       
   107 			}
       
   108 		};
       
   109 
       
   110 		if ( commentFormElement ) {
       
   111 			commentFormElement.addEventListener( 'keydown', submitFormHandler );
       
   112 		}
       
   113 
    98 		var links = replyLinks( context );
   114 		var links = replyLinks( context );
    99 		var element;
   115 		var element;
   100 
   116 
   101 		for ( var i = 0, l = links.length; i < l; i++ ) {
   117 		for ( var i = 0, l = links.length; i < l; i++ ) {
   102 			element = links[i];
   118 			element = links[i];
   154 		}
   170 		}
   155 
   171 
   156 		getElementById( config.parentIdFieldId ).value = '0';
   172 		getElementById( config.parentIdFieldId ).value = '0';
   157 
   173 
   158 		// Move the respond form back in place of the temporary element.
   174 		// Move the respond form back in place of the temporary element.
   159 		temporaryElement.parentNode.replaceChild( respondElement ,temporaryElement );
   175 		var headingText = temporaryElement.textContent;
       
   176 		temporaryElement.parentNode.replaceChild( respondElement, temporaryElement );
   160 		cancelLink.style.display = 'none';
   177 		cancelLink.style.display = 'none';
       
   178 
       
   179 		var replyHeadingElement  = getElementById( config.commentReplyTitleId );
       
   180 		var replyHeadingTextNode = replyHeadingElement && replyHeadingElement.firstChild;
       
   181 
       
   182 		if ( replyHeadingTextNode && replyHeadingTextNode.nodeType === Node.TEXT_NODE && headingText ) {
       
   183 			replyHeadingTextNode.textContent = headingText;
       
   184 		}
       
   185 
   161 		event.preventDefault();
   186 		event.preventDefault();
   162 	}
   187 	}
   163 
   188 
   164 	/**
   189 	/**
   165 	 * Click event handler.
   190 	 * Click event handler.
   167 	 * @since 5.1.0
   192 	 * @since 5.1.0
   168 	 *
   193 	 *
   169 	 * @param {Event} event The calling event.
   194 	 * @param {Event} event The calling event.
   170 	 */
   195 	 */
   171 	function clickEvent( event ) {
   196 	function clickEvent( event ) {
       
   197 		var replyNode = getElementById( config.commentReplyTitleId );
       
   198 		var defaultReplyHeading = replyNode && replyNode.firstChild.textContent;
   172 		var replyLink = this,
   199 		var replyLink = this,
   173 			commId    = getDataAttribute( replyLink, 'belowelement'),
   200 			commId    = getDataAttribute( replyLink, 'belowelement'),
   174 			parentId  = getDataAttribute( replyLink, 'commentid' ),
   201 			parentId  = getDataAttribute( replyLink, 'commentid' ),
   175 			respondId = getDataAttribute( replyLink, 'respondelement'),
   202 			respondId = getDataAttribute( replyLink, 'respondelement' ),
   176 			postId    = getDataAttribute( replyLink, 'postid'),
   203 			postId    = getDataAttribute( replyLink, 'postid' ),
       
   204 			replyTo   = getDataAttribute( replyLink, 'replyto' ) || defaultReplyHeading,
   177 			follow;
   205 			follow;
   178 
   206 
   179 		if ( ! commId || ! parentId || ! respondId || ! postId ) {
   207 		if ( ! commId || ! parentId || ! respondId || ! postId ) {
   180 			/*
   208 			/*
   181 			 * Theme or plugin defines own link via custom `wp_list_comments()` callback
   209 			 * Theme or plugin defines own link via custom `wp_list_comments()` callback
   186 
   214 
   187 		/*
   215 		/*
   188 		 * Third party comments systems can hook into this function via the global scope,
   216 		 * Third party comments systems can hook into this function via the global scope,
   189 		 * therefore the click event needs to reference the global scope.
   217 		 * therefore the click event needs to reference the global scope.
   190 		 */
   218 		 */
   191 		follow = window.addComment.moveForm(commId, parentId, respondId, postId);
   219 		follow = window.addComment.moveForm( commId, parentId, respondId, postId, replyTo );
   192 		if ( false === follow ) {
   220 		if ( false === follow ) {
   193 			event.preventDefault();
   221 			event.preventDefault();
   194 		}
   222 		}
   195 	}
   223 	}
   196 
   224 
   204 			return;
   232 			return;
   205 		}
   233 		}
   206 
   234 
   207 		var observerOptions = {
   235 		var observerOptions = {
   208 			childList: true,
   236 			childList: true,
   209 			subTree: true
   237 			subtree: true
   210 		};
   238 		};
   211 
   239 
   212 		observer = new MutationObserver( handleChanges );
   240 		observer = new MutationObserver( handleChanges );
   213 		observer.observe( document.body, observerOptions );
   241 		observer.observe( document.body, observerOptions );
   214 	}
   242 	}
   238 	 * Uses element.dataset if it exists, otherwise uses getAttribute.
   266 	 * Uses element.dataset if it exists, otherwise uses getAttribute.
   239 	 *
   267 	 *
   240 	 * @since 5.1.0
   268 	 * @since 5.1.0
   241 	 *
   269 	 *
   242 	 * @param {HTMLElement} Element DOM element with the attribute.
   270 	 * @param {HTMLElement} Element DOM element with the attribute.
   243 	 * @param {String}      Attribute the attribute to get.
   271 	 * @param {string}      Attribute the attribute to get.
   244 	 *
   272 	 *
   245 	 * @return {String}
   273 	 * @return {string}
   246 	 */
   274 	 */
   247 	function getDataAttribute( element, attribute ) {
   275 	function getDataAttribute( element, attribute ) {
   248 		if ( supportsDataset ) {
   276 		if ( supportsDataset ) {
   249 			return element.dataset[attribute];
   277 			return element.dataset[attribute];
   250 		}
   278 		}
   271 	 *
   299 	 *
   272 	 * @since 2.7.0
   300 	 * @since 2.7.0
   273 	 *
   301 	 *
   274 	 * @memberOf addComment
   302 	 * @memberOf addComment
   275 	 *
   303 	 *
   276 	 * @param {String} addBelowId HTML ID of element the form follows.
   304 	 * @param {string} addBelowId HTML ID of element the form follows.
   277 	 * @param {String} commentId  Database ID of comment being replied to.
   305 	 * @param {string} commentId  Database ID of comment being replied to.
   278 	 * @param {String} respondId  HTML ID of 'respond' element.
   306 	 * @param {string} respondId  HTML ID of 'respond' element.
   279 	 * @param {String} postId     Database ID of the post.
   307 	 * @param {string} postId     Database ID of the post.
   280 	 */
   308 	 * @param {string} replyTo    Form heading content.
   281 	function moveForm( addBelowId, commentId, respondId, postId ) {
   309 	 */
       
   310 	function moveForm( addBelowId, commentId, respondId, postId, replyTo ) {
   282 		// Get elements based on their IDs.
   311 		// Get elements based on their IDs.
   283 		var addBelowElement = getElementById( addBelowId );
   312 		var addBelowElement = getElementById( addBelowId );
   284 		respondElement  = getElementById( respondId );
   313 		respondElement  = getElementById( respondId );
   285 
   314 
   286 		// Get the hidden fields.
   315 		// Get the hidden fields.
   287 		var parentIdField   = getElementById( config.parentIdFieldId );
   316 		var parentIdField   = getElementById( config.parentIdFieldId );
   288 		var postIdField     = getElementById( config.postIdFieldId );
   317 		var postIdField     = getElementById( config.postIdFieldId );
   289 		var element, cssHidden, style;
   318 		var element, cssHidden, style;
   290 
   319 
       
   320 		var replyHeading         = getElementById( config.commentReplyTitleId );
       
   321 		var replyHeadingTextNode = replyHeading && replyHeading.firstChild;
       
   322 
   291 		if ( ! addBelowElement || ! respondElement || ! parentIdField ) {
   323 		if ( ! addBelowElement || ! respondElement || ! parentIdField ) {
   292 			// Missing key elements, fail.
   324 			// Missing key elements, fail.
   293 			return;
   325 			return;
       
   326 		}
       
   327 
       
   328 		if ( 'undefined' === typeof replyTo ) {
       
   329 			replyTo = replyHeadingTextNode && replyHeadingTextNode.textContent;
   294 		}
   330 		}
   295 
   331 
   296 		addPlaceHolder( respondElement );
   332 		addPlaceHolder( respondElement );
   297 
   333 
   298 		// Set the value of the post.
   334 		// Set the value of the post.
   302 
   338 
   303 		parentIdField.value = commentId;
   339 		parentIdField.value = commentId;
   304 
   340 
   305 		cancelElement.style.display = '';
   341 		cancelElement.style.display = '';
   306 		addBelowElement.parentNode.insertBefore( respondElement, addBelowElement.nextSibling );
   342 		addBelowElement.parentNode.insertBefore( respondElement, addBelowElement.nextSibling );
       
   343 
       
   344 		if ( replyHeadingTextNode && replyHeadingTextNode.nodeType === Node.TEXT_NODE ) {
       
   345 			replyHeadingTextNode.textContent = replyTo;
       
   346 		}
   307 
   347 
   308 		/*
   348 		/*
   309 		 * This is for backward compatibility with third party commenting systems
   349 		 * This is for backward compatibility with third party commenting systems
   310 		 * hooking into the event using older techniques.
   350 		 * hooking into the event using older techniques.
   311 		 */
   351 		 */
   312 		cancelElement.onclick = function(){
   352 		cancelElement.onclick = function() {
   313 			return false;
   353 			return false;
   314 		};
   354 		};
   315 
   355 
   316 		// Focus on the first field in the comment form.
   356 		// Focus on the first field in the comment form.
   317 		try {
   357 		try {
   370 	 * @param {HTMLelement} respondElement the #respond element holding comment form.
   410 	 * @param {HTMLelement} respondElement the #respond element holding comment form.
   371 	 */
   411 	 */
   372 	function addPlaceHolder( respondElement ) {
   412 	function addPlaceHolder( respondElement ) {
   373 		var temporaryFormId  = config.temporaryFormId;
   413 		var temporaryFormId  = config.temporaryFormId;
   374 		var temporaryElement = getElementById( temporaryFormId );
   414 		var temporaryElement = getElementById( temporaryFormId );
       
   415 		var replyElement = getElementById( config.commentReplyTitleId );
       
   416 		var initialHeadingText = replyElement ? replyElement.firstChild.textContent : '';
   375 
   417 
   376 		if ( temporaryElement ) {
   418 		if ( temporaryElement ) {
   377 			// The element already exists, no need to recreate.
   419 			// The element already exists, no need to recreate.
   378 			return;
   420 			return;
   379 		}
   421 		}
   380 
   422 
   381 		temporaryElement = document.createElement( 'div' );
   423 		temporaryElement = document.createElement( 'div' );
   382 		temporaryElement.id = temporaryFormId;
   424 		temporaryElement.id = temporaryFormId;
   383 		temporaryElement.style.display = 'none';
   425 		temporaryElement.style.display = 'none';
       
   426 		temporaryElement.textContent = initialHeadingText;
   384 		respondElement.parentNode.insertBefore( temporaryElement, respondElement );
   427 		respondElement.parentNode.insertBefore( temporaryElement, respondElement );
   385 	}
   428 	}
   386 
   429 
   387 	return {
   430 	return {
   388 		init: init,
   431 		init: init,