Changeset View
Changeset View
Standalone View
Standalone View
webroot/rsrc/js/application/diff/DiffInline.js
Show First 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | JX.install('DiffInline', { | ||||
members: { | members: { | ||||
_id: null, | _id: null, | ||||
_row: null, | _row: null, | ||||
_hidden: false, | _hidden: false, | ||||
_number: null, | _number: null, | ||||
_length: null, | _length: null, | ||||
_displaySide: null, | _displaySide: null, | ||||
_isNewFile: null, | _isNewFile: null, | ||||
_undoRow: null, | |||||
_isDeleted: false, | |||||
_isInvisible: false, | |||||
_isLoading: false, | |||||
setHidden: function(hidden) { | setHidden: function(hidden) { | ||||
this._hidden = hidden; | this._hidden = hidden; | ||||
JX.DOM.alterClass(this._row, 'inline-hidden', this._hidden); | JX.DOM.alterClass(this._row, 'inline-hidden', this._hidden); | ||||
var op; | var op; | ||||
if (hidden) { | if (hidden) { | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | _ondone: function(response) { | ||||
// as opposed to a submitted checkmark. This is different from the | // as opposed to a submitted checkmark. This is different from the | ||||
// top-level "draft" state of unsubmitted comments. | // top-level "draft" state of unsubmitted comments. | ||||
JX.DOM.alterClass(comment, 'inline-state-is-draft', response.draftState); | JX.DOM.alterClass(comment, 'inline-state-is-draft', response.draftState); | ||||
this._didUpdate(); | this._didUpdate(); | ||||
}, | }, | ||||
edit: function() { | edit: function() { | ||||
var handler = JX.bind(this, this._oneditresponse); | |||||
var uri = this._getInlineURI(); | var uri = this._getInlineURI(); | ||||
var data = this._newRequestData(); | var handler = JX.bind(this, this._oneditresponse); | ||||
var data = this._newRequestData('edit'); | |||||
// TODO: Set state to "loading". | this.setLoading(true); | ||||
new JX.Request(uri, handler) | new JX.Request(uri, handler) | ||||
.setData(data) | .setData(data) | ||||
.send(); | .send(); | ||||
}, | }, | ||||
delete: function(is_ref) { | |||||
var uri = this._getInlineURI(); | |||||
var handler = JX.bind(this, this._ondeleteresponse); | |||||
// NOTE: This may be a direct delete (the user clicked on the inline | |||||
// itself) or a "refdelete" (the user clicked somewhere else, like the | |||||
// preview, but the inline is present on the page). | |||||
// For a "refdelete", we prompt the user to confirm that they want to | |||||
// delete the comment, because they can not undo deletions from the | |||||
// preview. We could jump the user to the inline instead, but this would | |||||
// be somewhat disruptive and make deleting several comments more | |||||
// difficult. | |||||
var op; | |||||
if (is_ref) { | |||||
op = 'refdelete'; | |||||
} else { | |||||
op = 'delete'; | |||||
} | |||||
var data = this._newRequestData(op); | |||||
this.setLoading(true); | |||||
new JX.Workflow(uri, data) | |||||
.setHandler(handler) | |||||
.start(); | |||||
}, | |||||
getDisplaySide: function() { | getDisplaySide: function() { | ||||
return this._displaySide; | return this._displaySide; | ||||
}, | }, | ||||
getLineNumber: function() { | getLineNumber: function() { | ||||
return this._number; | return this._number; | ||||
}, | }, | ||||
getLineLength: function() { | getLineLength: function() { | ||||
return this._length; | return this._length; | ||||
}, | }, | ||||
isNewFile: function() { | isNewFile: function() { | ||||
return this._isNewFile; | return this._isNewFile; | ||||
}, | }, | ||||
_newRequestData: function() { | getID: function() { | ||||
return this._id; | |||||
}, | |||||
setDeleted: function(deleted) { | |||||
this._isDeleted = deleted; | |||||
this._redraw(); | |||||
return this; | |||||
}, | |||||
setInvisible: function(invisible) { | |||||
this._isInvisible = invisible; | |||||
this._redraw(); | |||||
return this; | |||||
}, | |||||
setLoading: function(loading) { | |||||
this._isLoading = loading; | |||||
this._redraw(); | |||||
return this; | |||||
}, | |||||
_newRequestData: function(operation) { | |||||
return { | return { | ||||
op: 'edit', | op: operation, | ||||
id: this._id, | id: this._id, | ||||
on_right: ((this.getDisplaySide() == 'right') ? 1 : 0), | on_right: ((this.getDisplaySide() == 'right') ? 1 : 0), | ||||
renderer: this.getChangeset().getRenderer(), | renderer: this.getChangeset().getRenderer(), | ||||
number: this.getLineNumber(), | number: this.getLineNumber(), | ||||
length: this.getLineLength(), | length: this.getLineLength(), | ||||
is_new: this.isNewFile(), | is_new: this.isNewFile(), | ||||
replyToCommentPHID: '' | replyToCommentPHID: '' | ||||
}; | }; | ||||
}, | }, | ||||
_oneditresponse: function(response) { | _oneditresponse: function(response) { | ||||
var rows = JX.$H(response).getNode(); | var rows = JX.$H(response).getNode(); | ||||
this._drawEditRows(rows); | this._drawEditRows(rows); | ||||
// TODO: Set the row state to "hidden". | this.setLoading(false); | ||||
this.setInvisible(true); | |||||
}, | |||||
_ondeleteresponse: function() { | |||||
this._drawUndoRows(); | |||||
this.setLoading(false); | |||||
this.setDeleted(true); | |||||
this._didUpdate(); | |||||
}, | |||||
_drawUndoRows: function() { | |||||
var templates = this.getChangeset().getUndoTemplates(); | |||||
var template; | |||||
if (this.getDisplaySide() == 'right') { | |||||
template = templates.r; | |||||
} else { | |||||
template = templates.l; | |||||
} | |||||
template = JX.$H(template).getNode(); | |||||
this._undoRow = this._drawRows(template, this._row, 'undo'); | |||||
}, | }, | ||||
_drawEditRows: function(rows) { | _drawEditRows: function(rows) { | ||||
return this._drawRows(rows, null, 'edit'); | |||||
}, | |||||
_drawRows: function(rows, cursor, type) { | |||||
var first_row = JX.DOM.scry(rows, 'tr')[0]; | var first_row = JX.DOM.scry(rows, 'tr')[0]; | ||||
var first_meta; | |||||
var row = first_row; | var row = first_row; | ||||
var cursor = this._row; | cursor = cursor || this._row.nextSibling; | ||||
var next_row; | |||||
while (row) { | while (row) { | ||||
// Grab this first, since it's going to change once we insert the row | |||||
// into the document. | |||||
next_row = row.nextSibling; | |||||
cursor.parentNode.insertBefore(row, cursor.nextSibling); | cursor.parentNode.insertBefore(row, cursor.nextSibling); | ||||
cursor = row; | cursor = row; | ||||
var row_meta = { | var row_meta = { | ||||
node: row, | node: row, | ||||
type: 'edit', | type: type, | ||||
listeners: [] | listeners: [] | ||||
}; | }; | ||||
if (!first_meta) { | |||||
first_meta = row_meta; | |||||
} | |||||
if (type == 'edit') { | |||||
row_meta.listeners.push( | row_meta.listeners.push( | ||||
JX.DOM.listen( | JX.DOM.listen( | ||||
row, | row, | ||||
['submit', 'didSyntheticSubmit'], | ['submit', 'didSyntheticSubmit'], | ||||
'inline-edit-form', | 'inline-edit-form', | ||||
JX.bind(this, this._onsubmit, row_meta))); | JX.bind(this, this._onsubmit, row_meta))); | ||||
row_meta.listeners.push( | row_meta.listeners.push( | ||||
JX.DOM.listen( | JX.DOM.listen( | ||||
row, | row, | ||||
'click', | 'click', | ||||
'inline-edit-cancel', | 'inline-edit-cancel', | ||||
JX.bind(this, this._oncancel, row_meta))); | JX.bind(this, this._oncancel, row_meta))); | ||||
} else { | |||||
row_meta.listeners.push( | |||||
JX.DOM.listen( | |||||
row, | |||||
'click', | |||||
'differential-inline-comment-undo', | |||||
JX.bind(this, this._onundo, row_meta))); | |||||
} | |||||
row = row.nextSibling; | row = next_row; | ||||
} | } | ||||
return first_row; | return first_meta; | ||||
}, | }, | ||||
_onsubmit: function(row, e) { | _onsubmit: function(row, e) { | ||||
e.kill(); | e.kill(); | ||||
var handler = JX.bind(this, this._onsubmitresponse, row); | var handler = JX.bind(this, this._onsubmitresponse, row); | ||||
this.setLoading(true); | |||||
JX.Workflow.newFromForm(e.getTarget()) | JX.Workflow.newFromForm(e.getTarget()) | ||||
.setHandler(handler) | .setHandler(handler) | ||||
.start(); | .start(); | ||||
}, | |||||
_onundo: function(row, e) { | |||||
e.kill(); | |||||
// TODO: Set state to "loading". | this._removeRow(row); | ||||
var uri = this._getInlineURI(); | |||||
var data = this._newRequestData('undelete'); | |||||
var handler = JX.bind(this, this._onundelete); | |||||
this.setDeleted(false); | |||||
this.setLoading(true); | |||||
new JX.Request(uri, handler) | |||||
.setData(data) | |||||
.send(); | |||||
}, | |||||
_onundelete: function() { | |||||
this.setLoading(false); | |||||
this._didUpdate(); | |||||
}, | }, | ||||
_oncancel: function(row, e) { | _oncancel: function(row, e) { | ||||
e.kill(); | e.kill(); | ||||
// TODO: Capture edited text and offer "undo". | // TODO: Capture edited text and offer "undo". | ||||
JX.DOM.remove(row.node); | this._removeRow(row); | ||||
this._removeListeners(row.listeners); | |||||
// TODO: Restore state to "normal". | this.setInvisible(false); | ||||
}, | }, | ||||
_onsubmitresponse: function(row, response) { | _onsubmitresponse: function(row, response) { | ||||
this._removeRow(row); | |||||
JX.DOM.remove(row.node); | this.setInvisible(false); | ||||
this._removeListeners(row.listeners); | |||||
// TODO: Restore state to "normal". | |||||
this._onupdate(response); | this._onupdate(response); | ||||
}, | }, | ||||
_onupdate: function(response) { | _onupdate: function(response) { | ||||
var new_row; | var new_row; | ||||
if (response.markup) { | if (response.markup) { | ||||
new_row = this._drawEditRows(JX.$H(response.markup).getNode()); | new_row = this._drawEditRows(JX.$H(response.markup).getNode()).node; | ||||
} | } | ||||
// TODO: Save the old row so the action it's undo-able if it was a | // TODO: Save the old row so the action it's undo-able if it was a | ||||
// delete. | // delete. | ||||
var remove_old = true; | var remove_old = true; | ||||
if (remove_old) { | if (remove_old) { | ||||
JX.DOM.remove(this._row); | JX.DOM.remove(this._row); | ||||
} | } | ||||
this._row = new_row; | this._row = new_row; | ||||
this._didUpdate(); | this._didUpdate(); | ||||
}, | }, | ||||
_didUpdate: function() { | _didUpdate: function() { | ||||
// After making changes to inline comments, refresh the transaction | // After making changes to inline comments, refresh the transaction | ||||
// preview at the bottom of the page. | // preview at the bottom of the page. | ||||
this.getChangeset().getChangesetList().redrawPreview(); | |||||
}, | |||||
// TODO: This isn't the cleanest way to find the preview form, but | _redraw: function() { | ||||
// rendering no longer has direct access to it. | var is_invisible = (this._isInvisible || this._isDeleted); | ||||
var forms = JX.DOM.scry(document.body, 'form', 'transaction-append'); | var is_loading = (this._isLoading); | ||||
if (forms.length) { | |||||
JX.DOM.invoke(forms[0], 'shouldRefresh'); | var row = this._row; | ||||
} | JX.DOM.alterClass(row, 'differential-inline-hidden', is_invisible); | ||||
JX.DOM.alterClass(row, 'differential-inline-loading', is_loading); | |||||
}, | }, | ||||
_removeListeners: function(listeners) { | _removeRow: function(row) { | ||||
for (var ii = 0; ii < listeners.length; ii++) { | JX.DOM.remove(row.node); | ||||
listeners[ii].remove(); | for (var ii = 0; ii < row.listeners.length; ii++) { | ||||
row.listeners[ii].remove(); | |||||
} | } | ||||
}, | }, | ||||
_getInlineURI: function() { | _getInlineURI: function() { | ||||
var changeset = this.getChangeset(); | var changeset = this.getChangeset(); | ||||
var list = changeset.getChangesetList(); | var list = changeset.getChangesetList(); | ||||
return list.getInlineURI(); | return list.getInlineURI(); | ||||
} | } | ||||
} | } | ||||
}); | }); |