Diff: STRATO-apps/wordpress_03/app/wp-includes/js/comment-reply.js
Keine Baseline-Datei – Diff nur gegen leer.
1
-
1
+
/**
2
+
* Handles the addition of the comment form.
3
+
*
4
+
* @since 2.7.0
5
+
* @output wp-includes/js/comment-reply.js
6
+
*
7
+
* @namespace addComment
8
+
*
9
+
* @type {Object}
10
+
*/
11
+
window.addComment = ( function( window ) {
12
+
// Avoid scope lookups on commonly used variables.
13
+
var document = window.document;
14
+
15
+
// Settings.
16
+
var config = {
17
+
commentReplyClass : 'comment-reply-link',
18
+
commentReplyTitleId : 'reply-title',
19
+
cancelReplyId : 'cancel-comment-reply-link',
20
+
commentFormId : 'commentform',
21
+
temporaryFormId : 'wp-temp-form-div',
22
+
parentIdFieldId : 'comment_parent',
23
+
postIdFieldId : 'comment_post_ID'
24
+
};
25
+
26
+
// Cross browser MutationObserver.
27
+
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
28
+
29
+
// Check browser cuts the mustard.
30
+
var cutsTheMustard = 'querySelector' in document && 'addEventListener' in window;
31
+
32
+
/*
33
+
* Check browser supports dataset.
34
+
* !! sets the variable to true if the property exists.
35
+
*/
36
+
var supportsDataset = !! document.documentElement.dataset;
37
+
38
+
// For holding the cancel element.
39
+
var cancelElement;
40
+
41
+
// For holding the comment form element.
42
+
var commentFormElement;
43
+
44
+
// The respond element.
45
+
var respondElement;
46
+
47
+
// The mutation observer.
48
+
var observer;
49
+
50
+
if ( cutsTheMustard && document.readyState !== 'loading' ) {
51
+
ready();
52
+
} else if ( cutsTheMustard ) {
53
+
window.addEventListener( 'DOMContentLoaded', ready, false );
54
+
}
55
+
56
+
/**
57
+
* Sets up object variables after the DOM is ready.
58
+
*
59
+
* @since 5.1.1
60
+
*/
61
+
function ready() {
62
+
// Initialize the events.
63
+
init();
64
+
65
+
// Set up a MutationObserver to check for comments loaded late.
66
+
observeChanges();
67
+
}
68
+
69
+
/**
70
+
* Add events to links classed .comment-reply-link.
71
+
*
72
+
* Searches the context for reply links and adds the JavaScript events
73
+
* required to move the comment form. To allow for lazy loading of
74
+
* comments this method is exposed as window.commentReply.init().
75
+
*
76
+
* @since 5.1.0
77
+
*
78
+
* @memberOf addComment
79
+
*
80
+
* @param {HTMLElement} context The parent DOM element to search for links.
81
+
*/
82
+
function init( context ) {
83
+
if ( ! cutsTheMustard ) {
84
+
return;
85
+
}
86
+
87
+
// Get required elements.
88
+
cancelElement = getElementById( config.cancelReplyId );
89
+
commentFormElement = getElementById( config.commentFormId );
90
+
91
+
// No cancel element, no replies.
92
+
if ( ! cancelElement ) {
93
+
return;
94
+
}
95
+
96
+
cancelElement.addEventListener( 'touchstart', cancelEvent );
97
+
cancelElement.addEventListener( 'click', cancelEvent );
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 && document.activeElement.tagName.toLowerCase() !== 'a' ) {
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
+
114
+
var links = replyLinks( context );
115
+
var element;
116
+
117
+
for ( var i = 0, l = links.length; i < l; i++ ) {
118
+
element = links[i];
119
+
120
+
element.addEventListener( 'touchstart', clickEvent );
121
+
element.addEventListener( 'click', clickEvent );
122
+
}
123
+
}
124
+
125
+
/**
126
+
* Return all links classed .comment-reply-link.
127
+
*
128
+
* @since 5.1.0
129
+
*
130
+
* @param {HTMLElement} context The parent DOM element to search for links.
131
+
*
132
+
* @return {HTMLCollection|NodeList|Array}
133
+
*/
134
+
function replyLinks( context ) {
135
+
var selectorClass = config.commentReplyClass;
136
+
var allReplyLinks;
137
+
138
+
// childNodes is a handy check to ensure the context is a HTMLElement.
139
+
if ( ! context || ! context.childNodes ) {
140
+
context = document;
141
+
}
142
+
143
+
if ( document.getElementsByClassName ) {
144
+
// Fastest.
145
+
allReplyLinks = context.getElementsByClassName( selectorClass );
146
+
}
147
+
else {
148
+
// Fast.
149
+
allReplyLinks = context.querySelectorAll( '.' + selectorClass );
150
+
}
151
+
152
+
return allReplyLinks;
153
+
}
154
+
155
+
/**
156
+
* Cancel event handler.
157
+
*
158
+
* @since 5.1.0
159
+
*
160
+
* @param {Event} event The calling event.
161
+
*/
162
+
function cancelEvent( event ) {
163
+
var cancelLink = this;
164
+
var temporaryFormId = config.temporaryFormId;
165
+
var temporaryElement = getElementById( temporaryFormId );
166
+
167
+
if ( ! temporaryElement || ! respondElement ) {
168
+
// Conditions for cancel link fail.
169
+
return;
170
+
}
171
+
172
+
getElementById( config.parentIdFieldId ).value = '0';
173
+
174
+
// Move the respond form back in place of the temporary element.
175
+
var headingText = temporaryElement.textContent;
176
+
temporaryElement.parentNode.replaceChild( respondElement, temporaryElement );
177
+
cancelLink.style.display = 'none';
178
+
179
+
var replyHeadingElement = getElementById( config.commentReplyTitleId );
180
+
var replyHeadingTextNode = replyHeadingElement && replyHeadingElement.firstChild;
181
+
var replyLinkToParent = replyHeadingTextNode && replyHeadingTextNode.nextSibling;
182
+
183
+
if ( replyHeadingTextNode && replyHeadingTextNode.nodeType === Node.TEXT_NODE && headingText ) {
184
+
if ( replyLinkToParent && 'A' === replyLinkToParent.nodeName && replyLinkToParent.id !== config.cancelReplyId ) {
185
+
replyLinkToParent.style.display = '';
186
+
}
187
+
188
+
replyHeadingTextNode.textContent = headingText;
189
+
}
190
+
191
+
event.preventDefault();
192
+
}
193
+
194
+
/**
195
+
* Click event handler.
196
+
*
197
+
* @since 5.1.0
198
+
*
199
+
* @param {Event} event The calling event.
200
+
*/
201
+
function clickEvent( event ) {
202
+
var replyNode = getElementById( config.commentReplyTitleId );
203
+
var defaultReplyHeading = replyNode && replyNode.firstChild.textContent;
204
+
var replyLink = this,
205
+
commId = getDataAttribute( replyLink, 'belowelement' ),
206
+
parentId = getDataAttribute( replyLink, 'commentid' ),
207
+
respondId = getDataAttribute( replyLink, 'respondelement' ),
208
+
postId = getDataAttribute( replyLink, 'postid' ),
209
+
replyTo = getDataAttribute( replyLink, 'replyto' ) || defaultReplyHeading,
210
+
follow;
211
+
212
+
if ( ! commId || ! parentId || ! respondId || ! postId ) {
213
+
/*
214
+
* Theme or plugin defines own link via custom `wp_list_comments()` callback
215
+
* and calls `moveForm()` either directly or via a custom event hook.
216
+
*/
217
+
return;
218
+
}
219
+
220
+
/*
221
+
* Third party comments systems can hook into this function via the global scope,
222
+
* therefore the click event needs to reference the global scope.
223
+
*/
224
+
follow = window.addComment.moveForm( commId, parentId, respondId, postId, replyTo );
225
+
if ( false === follow ) {
226
+
event.preventDefault();
227
+
}
228
+
}
229
+
230
+
/**
231
+
* Creates a mutation observer to check for newly inserted comments.
232
+
*
233
+
* @since 5.1.0
234
+
*/
235
+
function observeChanges() {
236
+
if ( ! MutationObserver ) {
237
+
return;
238
+
}
239
+
240
+
var observerOptions = {
241
+
childList: true,
242
+
subtree: true
243
+
};
244
+
245
+
observer = new MutationObserver( handleChanges );
246
+
observer.observe( document.body, observerOptions );
247
+
}
248
+
249
+
/**
250
+
* Handles DOM changes, calling init() if any new nodes are added.
251
+
*
252
+
* @since 5.1.0
253
+
*
254
+
* @param {Array} mutationRecords Array of MutationRecord objects.
255
+
*/
256
+
function handleChanges( mutationRecords ) {
257
+
var i = mutationRecords.length;
258
+
259
+
while ( i-- ) {
260
+
// Call init() once if any record in this set adds nodes.
261
+
if ( mutationRecords[ i ].addedNodes.length ) {
262
+
init();
263
+
return;
264
+
}
265
+
}
266
+
}
267
+
268
+
/**
269
+
* Backward compatible getter of data-* attribute.
270
+
*
271
+
* Uses element.dataset if it exists, otherwise uses getAttribute.
272
+
*
273
+
* @since 5.1.0
274
+
*
275
+
* @param {HTMLElement} Element DOM element with the attribute.
276
+
* @param {string} Attribute the attribute to get.
277
+
*
278
+
* @return {string}
279
+
*/
280
+
function getDataAttribute( element, attribute ) {
281
+
if ( supportsDataset ) {
282
+
return element.dataset[attribute];
283
+
}
284
+
else {
285
+
return element.getAttribute( 'data-' + attribute );
286
+
}
287
+
}
288
+
289
+
/**
290
+
* Get element by ID.
291
+
*
292
+
* Local alias for document.getElementById.
293
+
*
294
+
* @since 5.1.0
295
+
*
296
+
* @param {HTMLElement} The requested element.
297
+
*/
298
+
function getElementById( elementId ) {
299
+
return document.getElementById( elementId );
300
+
}
301
+
302
+
/**
303
+
* Moves the reply form from its current position to the reply location.
304
+
*
305
+
* @since 2.7.0
306
+
*
307
+
* @memberOf addComment
308
+
*
309
+
* @param {string} addBelowId HTML ID of element the form follows.
310
+
* @param {string} commentId Database ID of comment being replied to.
311
+
* @param {string} respondId HTML ID of 'respond' element.
312
+
* @param {string} postId Database ID of the post.
313
+
* @param {string} replyTo Form heading content.
314
+
*/
315
+
function moveForm( addBelowId, commentId, respondId, postId, replyTo ) {
316
+
// Get elements based on their IDs.
317
+
var addBelowElement = getElementById( addBelowId );
318
+
respondElement = getElementById( respondId );
319
+
320
+
// Get the hidden fields.
321
+
var parentIdField = getElementById( config.parentIdFieldId );
322
+
var postIdField = getElementById( config.postIdFieldId );
323
+
var element, cssHidden, style;
324
+
325
+
var replyHeading = getElementById( config.commentReplyTitleId );
326
+
var replyHeadingTextNode = replyHeading && replyHeading.firstChild;
327
+
var replyLinkToParent = replyHeadingTextNode && replyHeadingTextNode.nextSibling;
328
+
329
+
if ( ! addBelowElement || ! respondElement || ! parentIdField ) {
330
+
// Missing key elements, fail.
331
+
return;
332
+
}
333
+
334
+
if ( 'undefined' === typeof replyTo ) {
335
+
replyTo = replyHeadingTextNode && replyHeadingTextNode.textContent;
336
+
}
337
+
338
+
addPlaceHolder( respondElement );
339
+
340
+
// Set the value of the post.
341
+
if ( postId && postIdField ) {
342
+
postIdField.value = postId;
343
+
}
344
+
345
+
parentIdField.value = commentId;
346
+
347
+
cancelElement.style.display = '';
348
+
addBelowElement.parentNode.insertBefore( respondElement, addBelowElement.nextSibling );
349
+
350
+
if ( replyHeadingTextNode && replyHeadingTextNode.nodeType === Node.TEXT_NODE ) {
351
+
if ( replyLinkToParent && 'A' === replyLinkToParent.nodeName && replyLinkToParent.id !== config.cancelReplyId ) {
352
+
replyLinkToParent.style.display = 'none';
353
+
}
354
+
355
+
replyHeadingTextNode.textContent = replyTo;
356
+
}
357
+
358
+
/*
359
+
* This is for backward compatibility with third party commenting systems
360
+
* hooking into the event using older techniques.
361
+
*/
362
+
cancelElement.onclick = function() {
363
+
return false;
364
+
};
365
+
366
+
// Focus on the first field in the comment form.
367
+
try {
368
+
for ( var i = 0; i < commentFormElement.elements.length; i++ ) {
369
+
element = commentFormElement.elements[i];
370
+
cssHidden = false;
371
+
372
+
// Get elements computed style.
373
+
if ( 'getComputedStyle' in window ) {
374
+
// Modern browsers.
375
+
style = window.getComputedStyle( element );
376
+
} else if ( document.documentElement.currentStyle ) {
377
+
// IE 8.
378
+
style = element.currentStyle;
379
+
}
380
+
381
+
/*
382
+
* For display none, do the same thing jQuery does. For visibility,
383
+
* check the element computed style since browsers are already doing
384
+
* the job for us. In fact, the visibility computed style is the actual
385
+
* computed value and already takes into account the element ancestors.
386
+
*/
387
+
if ( ( element.offsetWidth <= 0 && element.offsetHeight <= 0 ) || style.visibility === 'hidden' ) {
388
+
cssHidden = true;
389
+
}
390
+
391
+
// Skip form elements that are hidden or disabled.
392
+
if ( 'hidden' === element.type || element.disabled || cssHidden ) {
393
+
continue;
394
+
}
395
+
396
+
element.focus();
397
+
// Stop after the first focusable element.
398
+
break;
399
+
}
400
+
}
401
+
catch(e) {
402
+
403
+
}
404
+
405
+
/*
406
+
* false is returned for backward compatibility with third party commenting systems
407
+
* hooking into this function.
408
+
*/
409
+
return false;
410
+
}
411
+
412
+
/**
413
+
* Add placeholder element.
414
+
*
415
+
* Places a place holder element above the #respond element for
416
+
* the form to be returned to if needs be.
417
+
*
418
+
* @since 2.7.0
419
+
*
420
+
* @param {HTMLelement} respondElement the #respond element holding comment form.
421
+
*/
422
+
function addPlaceHolder( respondElement ) {
423
+
var temporaryFormId = config.temporaryFormId;
424
+
var temporaryElement = getElementById( temporaryFormId );
425
+
var replyElement = getElementById( config.commentReplyTitleId );
426
+
var initialHeadingText = replyElement ? replyElement.firstChild.textContent : '';
427
+
428
+
if ( temporaryElement ) {
429
+
// The element already exists, no need to recreate.
430
+
return;
431
+
}
432
+
433
+
temporaryElement = document.createElement( 'div' );
434
+
temporaryElement.id = temporaryFormId;
435
+
temporaryElement.style.display = 'none';
436
+
temporaryElement.textContent = initialHeadingText;
437
+
respondElement.parentNode.insertBefore( temporaryElement, respondElement );
438
+
}
439
+
440
+
return {
441
+
init: init,
442
+
moveForm: moveForm
443
+
};
444
+
})( window );
445
+