1 | | var addComment = { |
2 | | moveForm : function(commId, parentId, respondId, postId) { |
3 | | var t = this, div, comm = t.I(commId), respond = t.I(respondId), cancel = t.I('cancel-comment-reply-link'), parent = t.I('comment_parent'), post = t.I('comment_post_ID'); |
| 1 | var addComment; |
| 2 | addComment = (function( window, undefined ){ |
| 3 | // Avoid scope lookups on commonly used variables |
| 4 | var document = window.document; |
5 | | if ( ! comm || ! respond || ! cancel || ! parent ) |
| 6 | // settings |
| 7 | var config = { |
| 8 | commentReplyClass : 'comment-reply-link', |
| 9 | cancelReplyId : 'cancel-comment-reply-link', |
| 10 | commentFieldId : 'comment', |
| 11 | temporaryFormId : 'wp-temp-form-div', |
| 12 | parentIdFieldId : 'comment_parent', |
| 13 | postIdFieldId : 'comment_post_ID' |
| 14 | }; |
| 15 | |
| 16 | // check browser cuts the mustard |
| 17 | var cutsTheMustard = 'querySelector' in document && 'addEventListener' in window; |
| 18 | |
| 19 | // check browser supports dataset |
| 20 | // !! sets the variable to truthy if the property exists. |
| 21 | var supportsDataset = !!document.body.dataset; |
| 22 | |
| 23 | // for holding the cancel element |
| 24 | var cancelElement; |
| 25 | |
| 26 | // for holding the comment field element |
| 27 | var commentFieldElement; |
| 28 | |
| 29 | // the respond element |
| 30 | var respondElement; |
| 31 | |
| 32 | // initialise the events |
| 33 | init(); |
| 34 | |
| 35 | /** |
| 36 | * Add events to links classed .comment-reply-link. |
| 37 | * |
| 38 | * Searches the context for reply links and adds the JavaScript events |
| 39 | * required to move the comment form. To allow for lazy loading of |
| 40 | * comments this method is exposed as PWCC.commentReply.init() |
| 41 | * |
| 42 | * @ticket 31590 |
| 43 | * |
| 44 | * @param {HTMLElement} context The parent DOM element to search for links. |
| 45 | */ |
| 46 | function init( context ) { |
| 47 | if ( true !== cutsTheMustard ) { |
| 49 | } |
| 50 | |
| 51 | // get required elements |
| 52 | cancelElement = getElementById( config.cancelReplyId ); |
| 53 | commentFieldElement = getElementById( config.commentFieldId ); |
| 54 | |
| 55 | // no cancel element, no replies |
| 56 | if ( ! cancelElement ) { |
| 57 | return; |
| 58 | } |
| 59 | |
| 60 | cancelElement.addEventListener( 'touchstart', cancelEvent ); |
| 61 | cancelElement.addEventListener( 'click', cancelEvent ); |
| 62 | |
| 63 | var links = replyLinks( context ); |
| 64 | var i,l; |
| 65 | var element; |
| 66 | |
| 67 | for ( i=0, l=links.length; i<l; i++ ) { |
| 68 | element = links[i]; |
| 69 | |
| 70 | element.addEventListener( 'touchstart', clickEvent ); |
| 71 | element.addEventListener( 'click', clickEvent ); |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | |
| 76 | /** |
| 77 | * Return all links classed .comment-reply-link |
| 78 | * |
| 79 | * @ticket 31590 |
| 80 | * |
| 81 | * @param {HTMLElement} context The parent DOM element to search for links. |
| 82 | * |
| 83 | * @return {HTMLCollection|NodeList|Array} |
| 84 | */ |
| 85 | function replyLinks( context ) { |
| 86 | var selectorClass = config.commentReplyClass; |
| 87 | var allReplyLinks; |
| 88 | |
| 89 | // childNodes is a handy check to ensure the context is a HTMLElement |
| 90 | if ( !context || !context.childNodes ) { |
| 91 | context = document; |
| 92 | } |
| 93 | |
| 94 | if ( document.getElementsByClassName ) { |
| 95 | // fastest |
| 96 | allReplyLinks = context.getElementsByClassName( selectorClass ); |
| 97 | } |
| 98 | else { |
| 99 | // fast |
| 100 | allReplyLinks = context.querySelectorAll( '.' + selectorClass ); |
| 101 | } |
| 102 | |
| 103 | return allReplyLinks; |
| 104 | } |
| 105 | |
| 106 | |
| 107 | /** |
| 108 | * Cance event handler |
| 109 | * |
| 110 | * @ticket 31590 |
| 111 | * |
| 112 | * @param {Event} event The calling event |
| 113 | */ |
| 114 | function cancelEvent( event ) { |
| 115 | var cancelLink = this; |
| 116 | var temporaryFormId = config.temporaryFormId; |
| 117 | var temporaryElement = getElementById( temporaryFormId ); |
| 118 | |
| 119 | if ( ! temporaryElement || ! respondElement ) { |
| 120 | // conditions for cancel link fail |
| 121 | return; |
| 122 | } |
| 123 | |
| 124 | getElementById( config.parentIdFieldId ).value = '0'; |
8 | | t.respondId = respondId; |
9 | | postId = postId || false; |
| 126 | // move the respond form back in place of the tempory element |
| 127 | temporaryElement.parentNode.replaceChild( respondElement ,temporaryElement ); |
| 128 | cancelLink.style.display = 'none'; |
| 129 | event.preventDefault(); |
| 130 | } |
| 131 | |
| 132 | |
| 133 | /** |
| 134 | * Click event handler |
| 135 | * |
| 136 | * @ticket 31590 |
| 137 | * |
| 138 | * @param {Event} event The calling event |
| 139 | */ |
| 140 | function clickEvent( event ) { |
| 141 | var replyLink = this, |
| 142 | commId = getDataAttribute( replyLink, 'belowelement'), |
| 143 | parentId = getDataAttribute( replyLink, 'commentid' ), |
| 144 | respondId = getDataAttribute( replyLink, 'respondelement'), |
| 145 | postId = getDataAttribute( replyLink, 'postid'), |
| 146 | follow = true; |
11 | | if ( ! t.I('wp-temp-form-div') ) { |
12 | | div = document.createElement('div'); |
13 | | div.id = 'wp-temp-form-div'; |
14 | | div.style.display = 'none'; |
15 | | respond.parentNode.insertBefore(div, respond); |
| 148 | // third party comments systems can hook into this function via the gloabl scope. |
| 149 | // therefore the click event needs to reference the gloabl scope. |
| 150 | follow = window.addComment.moveForm(commId, parentId, respondId, postId); |
| 151 | if ( false === follow ) { |
| 152 | event.preventDefault(); |
24 | | cancel.onclick = function() { |
25 | | var t = addComment, temp = t.I('wp-temp-form-div'), respond = t.I(t.respondId); |
| 157 | /** |
| 158 | * Backward compatible getter of data-* attribute |
| 159 | * |
| 160 | * Uses element.dataset if it exists, otherwise uses getAttribute |
| 161 | * |
| 162 | * @ticket 31590 |
| 163 | * |
| 164 | * @param {HTMLElement} element DOM element with the attribute |
| 165 | * @param {String} attribute the attribute to get |
| 166 | * |
| 167 | * @return {String} |
| 168 | */ |
| 169 | function getDataAttribute( element, attribute ) { |
| 170 | if ( supportsDataset ) { |
| 171 | return element.dataset[attribute]; |
| 172 | } |
| 173 | else { |
| 174 | return element.getAttribute( 'data-' + attribute ); |
| 175 | } |
| 176 | } |
| 177 | |
| 178 | /** |
| 179 | * Get element by Id |
| 180 | * |
| 181 | * local alias for document.getElementById |
| 182 | * |
| 183 | * @ticket 31590 |
| 184 | * |
| 185 | * @param {HTMLElement} The requested element |
| 186 | */ |
| 187 | function getElementById( elementId ) { |
| 188 | return document.getElementById( elementId ); |
| 189 | } |
30 | | t.I('comment_parent').value = '0'; |
31 | | temp.parentNode.insertBefore(respond, temp); |
32 | | temp.parentNode.removeChild(temp); |
33 | | this.style.display = 'none'; |
34 | | this.onclick = null; |
| 192 | /** |
| 193 | * moveForm |
| 194 | * |
| 195 | * Moves the reply form from it's current position to the reply location |
| 196 | * |
| 197 | * @ticket 31590 |
| 198 | * |
| 199 | * @param {String} addBelowId HTML ID of element the form follows |
| 200 | * @param {String} commentId Database ID of comment being replied to |
| 201 | * @param {String} respondId HTML ID of 'respond' element |
| 202 | * @param {String} postId Database ID of the post |
| 203 | */ |
| 204 | |
| 205 | function moveForm( addBelowId, commentId, respondId, postId ) { |
| 206 | // get elements based on their IDs |
| 207 | var addBelowElement = getElementById( addBelowId ); |
| 208 | respondElement = getElementById( respondId ); |
| 209 | |
| 210 | // get the hidden fields |
| 211 | var parentIdField = getElementById( config.parentIdFieldId ); |
| 212 | var postIdField = getElementById( config.postIdFieldId ); |
| 213 | |
| 214 | if ( ! addBelowElement || ! respondElement || ! parentIdField ) { |
| 215 | // missing key elements, fail |
| 216 | return; |
| 217 | } |
| 218 | |
| 219 | addPlaceHolder( respondElement ); |
| 220 | |
| 221 | // set the value of the post |
| 222 | if ( postId && postIdField ) { |
| 223 | postIdField.value = postId; |
| 224 | } |
| 225 | |
| 226 | parentIdField.value = commentId; |
| 227 | |
| 228 | cancelElement.style.display = ''; |
| 229 | addBelowElement.parentNode.insertBefore( respondElement, addBelowElement.nextSibling ); |
| 230 | |
| 231 | // this uglyness is for backward compatibility with third party commenting systems |
| 232 | // hooking into the event using older techniques. |
| 233 | cancelElement.onclick = function(){ |
44 | | I : function(e) { |
45 | | return document.getElementById(e); |
| 251 | /** |
| 252 | * add placeholder element |
| 253 | * |
| 254 | * Places a place holder element above the #respond element for |
| 255 | * the form to be returned to if needs be. |
| 256 | * |
| 257 | * @param {HTMLelement} respondElement the #respond element holding comment form |
| 258 | * |
| 259 | * @ticket 31590 |
| 260 | */ |
| 261 | function addPlaceHolder( respondElement ) { |
| 262 | var temporaryFormId = config.temporaryFormId; |
| 263 | var temporaryElement = getElementById( temporaryFormId ); |
| 264 | |
| 265 | if ( temporaryElement ) { |
| 266 | // the element already exists. |
| 267 | // no need to recreate |
| 268 | return; |
| 269 | } |
| 270 | |
| 271 | temporaryElement = document.createElement( 'div' ); |
| 272 | temporaryElement.id = temporaryFormId; |
| 273 | temporaryElement.style.display = 'none'; |
| 274 | respondElement.parentNode.insertBefore( temporaryElement, respondElement ); |
| 275 | |
| 276 | return; |