[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 /** 2 * @provides differential-inline-comment-editor 3 * @requires javelin-dom 4 * javelin-util 5 * javelin-stratcom 6 * javelin-install 7 * javelin-request 8 * javelin-workflow 9 */ 10 11 JX.install('DifferentialInlineCommentEditor', { 12 13 construct : function(uri) { 14 this._uri = uri; 15 }, 16 17 events : ['done'], 18 19 members : { 20 _uri : null, 21 _undoText : null, 22 _skipOverInlineCommentRows : function(node) { 23 // TODO: Move this semantic information out of class names. 24 while (node && node.className.indexOf('inline') !== -1) { 25 node = node.nextSibling; 26 } 27 return node; 28 }, 29 _buildRequestData : function() { 30 return { 31 op : this.getOperation(), 32 on_right : this.getOnRight(), 33 id : this.getID(), 34 number : this.getLineNumber(), 35 is_new : this.getIsNew(), 36 length : this.getLength(), 37 changeset : this.getChangeset(), 38 text : this.getText() || '' 39 }; 40 }, 41 _draw : function(content, exact_row) { 42 var row = this.getRow(); 43 var table = this.getTable(); 44 var target = exact_row ? row : this._skipOverInlineCommentRows(row); 45 46 return copyRows(table, content, target); 47 }, 48 _removeUndoLink : function() { 49 var rows = JX.DifferentialInlineCommentEditor._undoRows; 50 if (rows) { 51 for (var ii = 0; ii < rows.length; ii++) { 52 JX.DOM.remove(rows[ii]); 53 } 54 } 55 }, 56 _undo : function() { 57 this._removeUndoLink(); 58 59 this.setText(this._undoText); 60 this.start(); 61 }, 62 _registerUndoListener : function() { 63 if (!JX.DifferentialInlineCommentEditor._activeEditor) { 64 JX.Stratcom.listen( 65 'click', 66 'differential-inline-comment-undo', 67 function(e) { 68 JX.DifferentialInlineCommentEditor._activeEditor._undo(); 69 e.kill(); 70 }); 71 } 72 JX.DifferentialInlineCommentEditor._activeEditor = this; 73 }, 74 _setRowState : function(state) { 75 var is_hidden = (state == 'hidden'); 76 var is_loading = (state == 'loading'); 77 var row = this.getRow(); 78 JX.DOM.alterClass(row, 'differential-inline-hidden', is_hidden); 79 JX.DOM.alterClass(row, 'differential-inline-loading', is_loading); 80 }, 81 _didContinueWorkflow : function(response) { 82 var drawn = this._draw(JX.$H(response).getNode()); 83 84 var op = this.getOperation(); 85 if (op == 'edit') { 86 this._setRowState('hidden'); 87 } 88 89 JX.DOM.find( 90 drawn[0], 91 'textarea', 92 'differential-inline-comment-edit-textarea').focus(); 93 94 var oncancel = JX.bind(this, function(e) { 95 e.kill(); 96 97 this._didCancelWorkflow(); 98 99 if (op == 'edit') { 100 this._setRowState('visible'); 101 } 102 103 JX.DOM.remove(drawn[0]); 104 }); 105 JX.DOM.listen(drawn[0], 'click', 'inline-edit-cancel', oncancel); 106 107 var onsubmit = JX.bind(this, function(e) { 108 e.kill(); 109 110 JX.Workflow.newFromForm(e.getTarget()) 111 .setHandler(JX.bind(this, function(response) { 112 JX.DOM.remove(drawn[0]); 113 if (op == 'edit') { 114 this._setRowState('visible'); 115 } 116 this._didCompleteWorkflow(response); 117 })) 118 .start(); 119 120 JX.DOM.alterClass(drawn[0], 'differential-inline-loading', true); 121 }); 122 JX.DOM.listen( 123 drawn[0], 124 ['submit', 'didSyntheticSubmit'], 125 'inline-edit-form', 126 onsubmit); 127 }, 128 _didCompleteWorkflow : function(response) { 129 var op = this.getOperation(); 130 131 // We don't get any markup back if the user deletes a comment, or saves 132 // an empty comment (which effects a delete). 133 if (response.markup) { 134 this._draw(JX.$H(response.markup).getNode()); 135 } 136 137 // These operations remove the old row (edit adds a new row first). 138 var remove_old = (op == 'edit' || op == 'delete'); 139 if (remove_old) { 140 JX.DOM.remove(this.getRow()); 141 var other_rows = this.getOtherRows(); 142 for(var i = 0; i < other_rows.length; ++i) { 143 JX.DOM.remove(other_rows[i]); 144 } 145 } 146 147 // Once the user saves something, get rid of the 'undo' option. A 148 // particular case where we need this is saving a delete, when we might 149 // otherwise leave around an 'undo' for an earlier edit to the same 150 // comment. 151 this._removeUndoLink(); 152 153 JX.Stratcom.invoke('differential-inline-comment-update'); 154 this.invoke('done'); 155 }, 156 _didCancelWorkflow : function() { 157 this.invoke('done'); 158 159 var op = this.getOperation(); 160 if (op == 'delete') { 161 // No undo for delete, we prompt the user explicitly. 162 return; 163 } 164 165 var textarea; 166 try { 167 textarea = JX.DOM.find( 168 document.body, // TODO: use getDialogRootNode() when available 169 'textarea', 170 'differential-inline-comment-edit-textarea'); 171 } catch (ex) { 172 // The close handler is called whenever the dialog closes, even if the 173 // user closed it by completing the workflow with "Save". The 174 // JX.Workflow API should probably be refined to allow programmatic 175 // distinction of close caused by 'cancel' vs 'submit'. Testing for 176 // presence of the textarea serves as a proxy for detecting a 'cancel'. 177 return; 178 } 179 180 var text = textarea.value; 181 182 // If the user hasn't edited the text (i.e., no change from original for 183 // 'edit' or no text at all), don't offer them an undo. 184 if (text == this.getOriginalText() || text === '') { 185 return; 186 } 187 188 // Save the text so we can 'undo' back to it. 189 this._undoText = text; 190 191 var templates = this.getTemplates(); 192 var template = this.getOnRight() ? templates.r : templates.l; 193 template = JX.$H(template).getNode(); 194 195 // NOTE: Operation order matters here; we can't remove anything until 196 // after we draw the new rows because _draw uses the old rows to figure 197 // out where to place the comment. 198 199 // We use 'exact_row' to put the "undo" text directly above the affected 200 // comment. 201 var exact_row = true; 202 var rows = this._draw(template, exact_row); 203 204 this._removeUndoLink(); 205 206 JX.DifferentialInlineCommentEditor._undoRows = rows; 207 }, 208 209 start : function() { 210 this._registerUndoListener(); 211 212 var data = this._buildRequestData(); 213 214 var op = this.getOperation(); 215 216 217 if (op == 'delete') { 218 this._setRowState('loading'); 219 var oncomplete = JX.bind(this, this._didCompleteWorkflow); 220 var onclose = JX.bind(this, function() { 221 this._setRowState('visible'); 222 this._didCancelWorkflow(); 223 }); 224 225 new JX.Workflow(this._uri, data) 226 .setHandler(oncomplete) 227 .setCloseHandler(onclose) 228 .start(); 229 } else { 230 var handler = JX.bind(this, this._didContinueWorkflow); 231 232 if (op == 'edit') { 233 this._setRowState('loading'); 234 } 235 236 new JX.Request(this._uri, handler) 237 .setData(data) 238 .send(); 239 } 240 241 return this; 242 } 243 }, 244 245 statics : { 246 /** 247 * Global refernece to the 'undo' rows currently rendered in the document. 248 */ 249 _undoRows : null, 250 251 /** 252 * Global listener for the 'undo' click associated with the currently 253 * displayed 'undo' link. When an editor is start()ed, it becomes the active 254 * editor. 255 */ 256 _activeEditor : null 257 }, 258 259 properties : { 260 operation : null, 261 row : null, 262 otherRows: [], 263 table : null, 264 onRight : null, 265 ID : null, 266 lineNumber : null, 267 changeset : null, 268 length : null, 269 isNew : null, 270 text : null, 271 templates : null, 272 originalText : null 273 } 274 275 });
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |