Changeset View
Changeset View
Standalone View
Standalone View
webroot/rsrc/js/application/diff/DiffInline.js
Show All 12 Lines | members: { | ||||
_id: null, | _id: null, | ||||
_phid: null, | _phid: null, | ||||
_changesetID: null, | _changesetID: null, | ||||
_row: null, | _row: null, | ||||
_number: null, | _number: null, | ||||
_length: null, | _length: null, | ||||
_displaySide: null, | _displaySide: null, | ||||
_isNewFile: null, | _isNewFile: null, | ||||
_undoRow: null, | |||||
_replyToCommentPHID: null, | _replyToCommentPHID: null, | ||||
_originalText: null, | _originalText: null, | ||||
_snippet: null, | _snippet: null, | ||||
_isDeleted: false, | _isDeleted: false, | ||||
_isInvisible: false, | _isInvisible: false, | ||||
_isLoading: false, | _isLoading: false, | ||||
_changeset: null, | _changeset: null, | ||||
_isCollapsed: false, | _isCollapsed: false, | ||||
_isDraft: null, | _isDraft: null, | ||||
_isDraftDone: null, | _isDraftDone: null, | ||||
_isFixed: null, | _isFixed: null, | ||||
_isEditing: false, | _isEditing: false, | ||||
_isNew: false, | _isNew: false, | ||||
_isSynthetic: false, | _isSynthetic: false, | ||||
_isHidden: false, | _isHidden: false, | ||||
_editRow: null, | |||||
_undoRow: null, | |||||
_undoType: null, | |||||
_undoText: null, | |||||
bindToRow: function(row) { | bindToRow: function(row) { | ||||
this._row = row; | this._row = row; | ||||
var row_data = JX.Stratcom.getData(row); | var row_data = JX.Stratcom.getData(row); | ||||
row_data.inline = this; | row_data.inline = this; | ||||
this._isCollapsed = row_data.hidden || false; | this._isCollapsed = row_data.hidden || false; | ||||
// TODO: Get smarter about this once we do more editing, this is pretty | // TODO: Get smarter about this once we do more editing, this is pretty | ||||
// hacky. | // hacky. | ||||
var comment = JX.DOM.find(row, 'div', 'differential-inline-comment'); | var comment = JX.DOM.find(row, 'div', 'differential-inline-comment'); | ||||
var data = JX.Stratcom.getData(comment); | var data = JX.Stratcom.getData(comment); | ||||
this._id = data.id; | this._readInlineState(data); | ||||
this._phid = data.phid; | this._phid = data.phid; | ||||
// TODO: This is very, very, very, very, very, very, very hacky. | if (data.on_right) { | ||||
var td = comment.parentNode; | |||||
var th = td.previousSibling; | |||||
if (th.parentNode.firstChild != th) { | |||||
this._displaySide = 'right'; | this._displaySide = 'right'; | ||||
} else { | } else { | ||||
this._displaySide = 'left'; | this._displaySide = 'left'; | ||||
} | } | ||||
this._number = parseInt(data.number, 10); | this._number = parseInt(data.number, 10); | ||||
this._length = parseInt(data.length, 10); | this._length = parseInt(data.length, 10); | ||||
this._originalText = data.original; | this._originalText = data.original; | ||||
this._isNewFile = | this._isNewFile = data.isNewFile; | ||||
(this.getDisplaySide() == 'right') || | |||||
(data.left != data.right); | |||||
this._replyToCommentPHID = data.replyToCommentPHID; | this._replyToCommentPHID = data.replyToCommentPHID; | ||||
this._isDraft = data.isDraft; | this._isDraft = data.isDraft; | ||||
this._isFixed = data.isFixed; | this._isFixed = data.isFixed; | ||||
this._isGhost = data.isGhost; | this._isGhost = data.isGhost; | ||||
this._isSynthetic = data.isSynthetic; | this._isSynthetic = data.isSynthetic; | ||||
this._isDraftDone = data.isDraftDone; | this._isDraftDone = data.isDraftDone; | ||||
this._changesetID = data.changesetID; | this._changesetID = data.changesetID; | ||||
this._isNew = false; | this._isNew = false; | ||||
this._snippet = data.snippet; | this._snippet = data.snippet; | ||||
this._isEditing = data.isEditing; | |||||
if (this._isEditing) { | |||||
this.edit(); | |||||
} else { | |||||
this.setInvisible(false); | this.setInvisible(false); | ||||
} | |||||
return this; | return this; | ||||
}, | }, | ||||
isDraft: function() { | isDraft: function() { | ||||
return this._isDraft; | return this._isDraft; | ||||
}, | }, | ||||
▲ Show 20 Lines • Show All 299 Lines • ▼ Show 20 Lines | delete: function(is_ref) { | ||||
var op; | var op; | ||||
if (is_ref) { | if (is_ref) { | ||||
op = 'refdelete'; | op = 'refdelete'; | ||||
} else { | } else { | ||||
op = 'delete'; | op = 'delete'; | ||||
} | } | ||||
// If there's an existing "unedit" undo element, remove it. | |||||
if (this._undoRow) { | |||||
JX.DOM.remove(this._undoRow); | |||||
this._undoRow = null; | |||||
} | |||||
var data = this._newRequestData(op); | var data = this._newRequestData(op); | ||||
this.setLoading(true); | this.setLoading(true); | ||||
new JX.Workflow(uri, data) | new JX.Workflow(uri, data) | ||||
.setHandler(handler) | .setHandler(handler) | ||||
.start(); | .start(); | ||||
}, | }, | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | _newRequestData: function(operation, text) { | ||||
is_new: this.isNewFile(), | is_new: this.isNewFile(), | ||||
changesetID: this.getChangesetID(), | changesetID: this.getChangesetID(), | ||||
replyToCommentPHID: this.getReplyToCommentPHID() || '', | replyToCommentPHID: this.getReplyToCommentPHID() || '', | ||||
text: text || '' | text: text || '' | ||||
}; | }; | ||||
}, | }, | ||||
_oneditresponse: function(response) { | _oneditresponse: function(response) { | ||||
var rows = JX.$H(response).getNode(); | var rows = JX.$H(response.view).getNode(); | ||||
this._readInlineState(response.inline); | |||||
this._drawEditRows(rows); | this._drawEditRows(rows); | ||||
this.setLoading(false); | this.setLoading(false); | ||||
this.setInvisible(true); | this.setInvisible(true); | ||||
}, | }, | ||||
_oncreateresponse: function(response) { | _oncreateresponse: function(response) { | ||||
var rows = JX.$H(response).getNode(); | var rows = JX.$H(response.view).getNode(); | ||||
this._readInlineState(response.inline); | |||||
this._drawEditRows(rows); | this._drawEditRows(rows); | ||||
}, | }, | ||||
_readInlineState: function(state) { | |||||
this._id = state.id; | |||||
}, | |||||
_ondeleteresponse: function() { | _ondeleteresponse: function() { | ||||
this._drawUndeleteRows(); | this._drawUndeleteRows(); | ||||
this.setLoading(false); | this.setLoading(false); | ||||
this.setDeleted(true); | this.setDeleted(true); | ||||
this._didUpdate(); | this._didUpdate(); | ||||
}, | }, | ||||
_drawUndeleteRows: function() { | _drawUndeleteRows: function() { | ||||
this._undoType = 'undelete'; | |||||
this._undoText = null; | |||||
return this._drawUndoRows('undelete', this._row); | return this._drawUndoRows('undelete', this._row); | ||||
}, | }, | ||||
_drawUneditRows: function(text) { | _drawUneditRows: function(text) { | ||||
this._undoType = 'unedit'; | |||||
this._undoText = text; | |||||
return this._drawUndoRows('unedit', null, text); | return this._drawUndoRows('unedit', null, text); | ||||
}, | }, | ||||
_drawUndoRows: function(mode, cursor, text) { | _drawUndoRows: function(mode, cursor, text) { | ||||
var templates = this.getChangeset().getUndoTemplates(); | var templates = this.getChangeset().getUndoTemplates(); | ||||
var template; | var template; | ||||
if (this.getDisplaySide() == 'right') { | if (this.getDisplaySide() == 'right') { | ||||
template = templates.r; | template = templates.r; | ||||
} else { | } else { | ||||
template = templates.l; | template = templates.l; | ||||
} | } | ||||
template = JX.$H(template).getNode(); | template = JX.$H(template).getNode(); | ||||
this._undoRow = this._drawRows(template, cursor, mode, text); | this._undoRow = this._drawRows(template, cursor, mode, text); | ||||
}, | }, | ||||
_drawContentRows: function(rows) { | _drawContentRows: function(rows) { | ||||
return this._drawRows(rows, null, 'content'); | return this._drawRows(rows, null, 'content'); | ||||
}, | }, | ||||
_drawEditRows: function(rows) { | _drawEditRows: function(rows) { | ||||
this.setEditing(true); | this.setEditing(true); | ||||
return this._drawRows(rows, null, 'edit'); | this._editRow = this._drawRows(rows, null, 'edit'); | ||||
}, | }, | ||||
_drawRows: function(rows, cursor, type, text) { | _drawRows: function(rows, cursor, type, text) { | ||||
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 anchor = cursor || this._row; | var anchor = cursor || this._row; | ||||
cursor = cursor || this._row.nextSibling; | cursor = cursor || this._row.nextSibling; | ||||
var result_row; | |||||
var next_row; | var next_row; | ||||
while (row) { | while (row) { | ||||
// Grab this first, since it's going to change once we insert the row | // Grab this first, since it's going to change once we insert the row | ||||
// into the document. | // into the document. | ||||
next_row = row.nextSibling; | next_row = row.nextSibling; | ||||
// Bind edit and undo rows to this DiffInline object so that | // Bind edit and undo rows to this DiffInline object so that | ||||
// interactions like hovering work properly. | // interactions like hovering work properly. | ||||
JX.Stratcom.getData(row).inline = this; | JX.Stratcom.getData(row).inline = this; | ||||
anchor.parentNode.insertBefore(row, cursor); | anchor.parentNode.insertBefore(row, cursor); | ||||
cursor = row; | cursor = row; | ||||
var row_meta = { | if (!result_row) { | ||||
node: row, | result_row = row; | ||||
type: type, | |||||
text: text || null, | |||||
listeners: [] | |||||
}; | |||||
if (!first_meta) { | |||||
first_meta = row_meta; | |||||
} | |||||
if (type == 'edit') { | |||||
row_meta.listeners.push( | |||||
JX.DOM.listen( | |||||
row, | |||||
['submit', 'didSyntheticSubmit'], | |||||
'inline-edit-form', | |||||
JX.bind(this, this._onsubmit, row_meta))); | |||||
row_meta.listeners.push( | |||||
JX.DOM.listen( | |||||
row, | |||||
'click', | |||||
'inline-edit-cancel', | |||||
JX.bind(this, this._oncancel, row_meta))); | |||||
} else if (type == 'content') { | |||||
// No special listeners for these rows. | |||||
} else { | |||||
row_meta.listeners.push( | |||||
JX.DOM.listen( | |||||
row, | |||||
'click', | |||||
'differential-inline-comment-undo', | |||||
JX.bind(this, this._onundo, row_meta))); | |||||
} | } | ||||
// If the row has a textarea, focus it. This allows the user to start | // If the row has a textarea, focus it. This allows the user to start | ||||
// typing a comment immediately after a "new", "edit", or "reply" | // typing a comment immediately after a "new", "edit", or "reply" | ||||
// action. | // action. | ||||
var textareas = JX.DOM.scry( | var textareas = JX.DOM.scry( | ||||
row, | row, | ||||
'textarea', | 'textarea', | ||||
'differential-inline-comment-edit-textarea'); | 'differential-inline-comment-edit-textarea'); | ||||
if (textareas.length) { | if (textareas.length) { | ||||
var area = textareas[0]; | var area = textareas[0]; | ||||
area.focus(); | area.focus(); | ||||
var length = area.value.length; | var length = area.value.length; | ||||
JX.TextAreaUtils.setSelectionRange(area, length, length); | JX.TextAreaUtils.setSelectionRange(area, length, length); | ||||
} | } | ||||
row = next_row; | row = next_row; | ||||
} | } | ||||
JX.Stratcom.invoke('resize'); | JX.Stratcom.invoke('resize'); | ||||
return first_meta; | return result_row; | ||||
}, | }, | ||||
_onsubmit: function(row, e) { | save: function(form) { | ||||
e.kill(); | var handler = JX.bind(this, this._onsubmitresponse); | ||||
var handler = JX.bind(this, this._onsubmitresponse, row); | |||||
this.setLoading(true); | this.setLoading(true); | ||||
JX.Workflow.newFromForm(e.getTarget()) | JX.Workflow.newFromForm(form) | ||||
.setHandler(handler) | .setHandler(handler) | ||||
.start(); | .start(); | ||||
}, | }, | ||||
_onundo: function(row, e) { | undo: function() { | ||||
e.kill(); | |||||
this._removeRow(row); | JX.DOM.remove(this._undoRow); | ||||
this._undoRow = null; | |||||
if (row.type == 'undelete') { | if (this._undoType === 'undelete') { | ||||
var uri = this._getInlineURI(); | var uri = this._getInlineURI(); | ||||
var data = this._newRequestData('undelete'); | var data = this._newRequestData('undelete'); | ||||
var handler = JX.bind(this, this._onundelete); | var handler = JX.bind(this, this._onundelete); | ||||
this.setDeleted(false); | this.setDeleted(false); | ||||
this.setLoading(true); | this.setLoading(true); | ||||
new JX.Request(uri, handler) | new JX.Request(uri, handler) | ||||
.setData(data) | .setData(data) | ||||
.send(); | .send(); | ||||
} | } | ||||
if (row.type == 'unedit') { | if (this._undoType === 'unedit') { | ||||
if (this.getID()) { | this.edit(this._undoText); | ||||
this.edit(row.text); | |||||
} else { | |||||
this.create(row.text); | |||||
} | |||||
} | } | ||||
}, | }, | ||||
_onundelete: function() { | _onundelete: function() { | ||||
this.setLoading(false); | this.setLoading(false); | ||||
this._didUpdate(); | this._didUpdate(); | ||||
}, | }, | ||||
_oncancel: function(row, e) { | cancel: function() { | ||||
e.kill(); | var text = this._readText(this._editRow); | ||||
JX.DOM.remove(this._editRow); | |||||
this._editRow = null; | |||||
var text = this._readText(row.node); | |||||
if (text && text.length && (text != this._originalText)) { | if (text && text.length && (text != this._originalText)) { | ||||
this._drawUneditRows(text); | this._drawUneditRows(text); | ||||
} | } | ||||
this._removeRow(row); | |||||
this.setEditing(false); | this.setEditing(false); | ||||
this.setInvisible(false); | this.setInvisible(false); | ||||
this._didUpdate(true); | this._didUpdate(true); | ||||
}, | }, | ||||
_readText: function(row) { | _readText: function(row) { | ||||
var textarea; | var textarea; | ||||
try { | try { | ||||
textarea = JX.DOM.find( | textarea = JX.DOM.find( | ||||
row, | row, | ||||
'textarea', | 'textarea', | ||||
'differential-inline-comment-edit-textarea'); | 'differential-inline-comment-edit-textarea'); | ||||
} catch (ex) { | } catch (ex) { | ||||
return null; | return null; | ||||
} | } | ||||
return textarea.value; | return textarea.value; | ||||
}, | }, | ||||
_onsubmitresponse: function(row, response) { | _onsubmitresponse: function(response) { | ||||
this._removeRow(row); | if (this._editRow) { | ||||
JX.DOM.remove(this._editRow); | |||||
this._editRow = null; | |||||
} | |||||
this.setLoading(false); | this.setLoading(false); | ||||
this.setInvisible(false); | this.setInvisible(false); | ||||
this.setEditing(false); | this.setEditing(false); | ||||
this._onupdate(response); | this._onupdate(response); | ||||
}, | }, | ||||
_onupdate: function(response) { | _onupdate: function(response) { | ||||
var new_row; | var new_row; | ||||
if (response.markup) { | if (response.view) { | ||||
new_row = this._drawContentRows(JX.$H(response.markup).getNode()).node; | new_row = this._drawContentRows(JX.$H(response.view).getNode()); | ||||
} | } | ||||
// 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); | ||||
} | } | ||||
Show All 32 Lines | _redraw: function() { | ||||
var is_collapsed = (this._isCollapsed && !this._isHidden); | var is_collapsed = (this._isCollapsed && !this._isHidden); | ||||
var row = this._row; | var row = this._row; | ||||
JX.DOM.alterClass(row, 'differential-inline-hidden', is_invisible); | JX.DOM.alterClass(row, 'differential-inline-hidden', is_invisible); | ||||
JX.DOM.alterClass(row, 'differential-inline-loading', is_loading); | JX.DOM.alterClass(row, 'differential-inline-loading', is_loading); | ||||
JX.DOM.alterClass(row, 'inline-hidden', is_collapsed); | JX.DOM.alterClass(row, 'inline-hidden', is_collapsed); | ||||
}, | }, | ||||
_removeRow: function(row) { | |||||
JX.DOM.remove(row.node); | |||||
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(); | ||||
} | } | ||||
} | } | ||||
}); | }); |