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 |
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, |