Changeset View
Changeset View
Standalone View
Standalone View
webroot/rsrc/js/core/behavior-lightbox-attachments.js
/** | /** | ||||
* @provides javelin-behavior-lightbox-attachments | * @provides javelin-behavior-lightbox-attachments | ||||
* @requires javelin-behavior | * @requires javelin-behavior | ||||
* javelin-stratcom | * javelin-stratcom | ||||
* javelin-dom | * javelin-dom | ||||
* javelin-mask | * javelin-mask | ||||
* javelin-util | * javelin-util | ||||
* phuix-icon-view | * phuix-icon-view | ||||
* phabricator-busy | * phabricator-busy | ||||
*/ | */ | ||||
JX.behavior('lightbox-attachments', function (config) { | JX.behavior('lightbox-attachments', function (config) { | ||||
var lightbox = null; | var lightbox = null; | ||||
var prev = null; | var prev = null; | ||||
var next = null; | var next = null; | ||||
var shown = false; | |||||
var downloadForm = JX.$H(config.downloadForm).getFragment().firstChild; | var downloadForm = JX.$H(config.downloadForm).getFragment().firstChild; | ||||
var lightbox_id = config.lightbox_id; | |||||
function _toggleComment(e) { | |||||
e.kill(); | |||||
shown = !shown; | |||||
JX.DOM.alterClass(JX.$(lightbox_id), 'comment-panel-open', shown); | |||||
} | |||||
function markCommentsLoading(loading) { | |||||
var frame = JX.$('lightbox-comment-frame'); | |||||
JX.DOM.alterClass(frame, 'loading', loading); | |||||
} | |||||
function onLoadCommentsResponse(r) { | |||||
var frame = JX.$('lightbox-comment-frame'); | |||||
JX.DOM.setContent(frame, JX.$H(r)); | |||||
markCommentsLoading(false); | |||||
} | |||||
function loadComments(phid) { | |||||
markCommentsLoading(true); | |||||
var uri = '/file/thread/' + phid + '/'; | |||||
new JX.Workflow(uri) | |||||
.setHandler(onLoadCommentsResponse) | |||||
.start(); | |||||
epriestley: This should be `markCommentsLoading(true)` -- comments are now loading?
I think it's slightly… | |||||
Not Done Inline ActionsThis is still a bit funky but it doesn't really matter until there's CSS. epriestley: This is still a bit funky but it doesn't really matter until there's CSS. | |||||
} | |||||
function loadLightBox(e) { | function loadLightBox(e) { | ||||
if (!e.isNormalClick()) { | if (!e.isNormalClick()) { | ||||
return; | return; | ||||
} | } | ||||
e.kill(); | e.kill(); | ||||
Show All 30 Lines | function loadLightBox(e) { | ||||
var name_element = ''; | var name_element = ''; | ||||
// for now, this conditional is always true | // for now, this conditional is always true | ||||
// revisit if / when we decide to add non-images to lightbox view | // revisit if / when we decide to add non-images to lightbox view | ||||
if (target_data.viewable) { | if (target_data.viewable) { | ||||
img_uri = target_data.uri; | img_uri = target_data.uri; | ||||
} else { | } else { | ||||
img_uri = config.defaultImageUri; | img_uri = config.defaultImageUri; | ||||
extra_status = ' Image may not be representative of actual attachment.'; | extra_status = ' Image may not be representative of actual attachment.'; | ||||
name_element = JX.$N('div', | name_element = | ||||
{ className : 'attachment-name' }, | JX.$N('div', | ||||
{ | |||||
className : 'attachment-name' | |||||
}, | |||||
target_data.name | target_data.name | ||||
); | ); | ||||
} | } | ||||
var alt_name = ''; | var alt_name = ''; | ||||
if (typeof target_data.name != 'undefined') { | if (typeof target_data.name != 'undefined') { | ||||
alt_name = target_data.name; | alt_name = target_data.name; | ||||
} | } | ||||
var img = JX.$N('img', | var img = | ||||
JX.$N('img', | |||||
{ | { | ||||
className : 'loading', | className : 'loading', | ||||
alt : alt_name | alt : alt_name | ||||
} | } | ||||
); | ); | ||||
lightbox = JX.$N('div', | var imgFrame = | ||||
JX.$N('div', | |||||
{ | { | ||||
className : 'lightbox-attachment', | className : 'lightbox-image-frame', | ||||
sigil: 'lightbox-attachment' | |||||
}, | }, | ||||
img | img | ||||
); | ); | ||||
var statusSpan = JX.$N('span', | var commentFrame = | ||||
JX.$N('div', | |||||
{ | |||||
className : 'lightbox-comment-frame', | |||||
id : 'lightbox-comment-frame' | |||||
} | |||||
); | |||||
var commentClass = (shown) ? 'comment-panel-open' : ''; | |||||
lightbox = | |||||
JX.$N('div', | |||||
{ | |||||
className : 'lightbox-attachment ' + commentClass, | |||||
sigil : 'lightbox-attachment', | |||||
id : lightbox_id | |||||
}, | |||||
[imgFrame, commentFrame] | |||||
); | |||||
var monogram = JX.$N('strong', {}, target_data.monogram); | |||||
var m_url = JX.$N('a', { href : '/' + target_data.monogram }, monogram); | |||||
var statusSpan = | |||||
JX.$N('span', | |||||
{ | { | ||||
className: 'lightbox-status-txt' | className: 'lightbox-status-txt' | ||||
}, | }, | ||||
[ | |||||
m_url, | |||||
'Image '+current+' of '+total+'.'+extra_status | ' Image ' + current + ' of ' + total + '.' + extra_status | ||||
] | |||||
); | ); | ||||
var downloadSpan = JX.$N('span', | var downloadSpan = | ||||
JX.$N('span', | |||||
{ | { | ||||
className : 'lightbox-download' | className : 'lightbox-download' | ||||
}); | } | ||||
var closeButton = JX.$N('a', | ); | ||||
var commentIcon = new JX.PHUIXIconView() | |||||
.setIcon('fa-comment-o') | |||||
.getNode(); | |||||
var commentButton = | |||||
JX.$N('a', | |||||
{ | |||||
className : 'lightbox-comment button grey has-icon', | |||||
href : '#', | |||||
sigil : 'lightbox-comment' | |||||
}, | |||||
[commentIcon, 'Comment'] | |||||
); | |||||
var closeButton = | |||||
JX.$N('a', | |||||
{ | { | ||||
className : 'lightbox-close button grey', | className : 'lightbox-close button grey', | ||||
href : '#' | href : '#' | ||||
}, | }, | ||||
'Close'); | 'Close'); | ||||
var statusHTML = JX.$N('div', | var statusHTML = | ||||
JX.$N('div', | |||||
{ | { | ||||
className : 'lightbox-status' | className : 'lightbox-status' | ||||
}, | }, | ||||
[statusSpan, closeButton, downloadSpan] | [statusSpan, closeButton, commentButton, downloadSpan] | ||||
); | ); | ||||
JX.DOM.appendContent(lightbox, statusHTML); | JX.DOM.appendContent(lightbox, statusHTML); | ||||
JX.DOM.appendContent(lightbox, name_element); | JX.DOM.appendContent(lightbox, name_element); | ||||
JX.DOM.listen(closeButton, 'click', null, closeLightBox); | JX.DOM.listen(closeButton, 'click', null, closeLightBox); | ||||
var leftIcon = ''; | var leftIcon = ''; | ||||
if (next) { | if (next) { | ||||
var r_icon = new JX.PHUIXIconView() | var r_icon = new JX.PHUIXIconView() | ||||
.setIcon('fa-angle-right') | .setIcon('fa-angle-right') | ||||
.setColor('lightgreytext') | .setColor('lightgreytext') | ||||
.getNode(); | .getNode(); | ||||
leftIcon = JX.$N('a', | leftIcon = | ||||
JX.$N('a', | |||||
{ | { | ||||
className : 'lightbox-right', | className : 'lightbox-right', | ||||
href : '#' | href : '#' | ||||
}, | }, | ||||
r_icon); | r_icon | ||||
); | |||||
JX.DOM.listen(leftIcon, | JX.DOM.listen(leftIcon, | ||||
'click', | 'click', | ||||
null, | null, | ||||
JX.bind(null, loadAnotherLightBox, next) | JX.bind(null, loadAnotherLightBox, next) | ||||
); | ); | ||||
} | } | ||||
JX.DOM.appendContent(lightbox, leftIcon); | JX.DOM.appendContent(lightbox, leftIcon); | ||||
var rightIcon = ''; | var rightIcon = ''; | ||||
if (prev) { | if (prev) { | ||||
var l_icon = new JX.PHUIXIconView() | var l_icon = new JX.PHUIXIconView() | ||||
.setIcon('fa-angle-left') | .setIcon('fa-angle-left') | ||||
.setColor('lightgreytext') | .setColor('lightgreytext') | ||||
.getNode(); | .getNode(); | ||||
rightIcon = JX.$N('a', | rightIcon = | ||||
JX.$N('a', | |||||
{ | { | ||||
className : 'lightbox-left', | className : 'lightbox-left', | ||||
href : '#' | href : '#' | ||||
}, | }, | ||||
l_icon); | l_icon | ||||
); | |||||
JX.DOM.listen(rightIcon, | JX.DOM.listen(rightIcon, | ||||
'click', | 'click', | ||||
null, | null, | ||||
JX.bind(null, loadAnotherLightBox, prev) | JX.bind(null, loadAnotherLightBox, prev) | ||||
); | ); | ||||
} | } | ||||
JX.DOM.appendContent(lightbox, rightIcon); | JX.DOM.appendContent(lightbox, rightIcon); | ||||
JX.DOM.alterClass(document.body, 'lightbox-attached', true); | JX.DOM.alterClass(document.body, 'lightbox-attached', true); | ||||
JX.Mask.show('jx-dark-mask'); | JX.Mask.show('jx-dark-mask'); | ||||
downloadForm.action = target_data.dUri; | downloadForm.action = target_data.dUri; | ||||
downloadSpan.appendChild(downloadForm); | downloadSpan.appendChild(downloadForm); | ||||
document.body.appendChild(lightbox); | document.body.appendChild(lightbox); | ||||
JX.Busy.start(); | JX.Busy.start(); | ||||
img.onload = function() { | img.onload = function() { | ||||
JX.DOM.alterClass(img, 'loading', false); | JX.DOM.alterClass(img, 'loading', false); | ||||
JX.Busy.done(); | JX.Busy.done(); | ||||
}; | }; | ||||
img.src = img_uri; | img.src = img_uri; | ||||
loadComments(target_data.phid); | |||||
} | } | ||||
// TODO - make this work with KeyboardShortcut, which means | // TODO - make this work with KeyboardShortcut, which means | ||||
// making an uninstall / de-register for KeyboardShortcut | // making an uninstall / de-register for KeyboardShortcut | ||||
function lightBoxHandleKeyDown(e) { | function lightBoxHandleKeyDown(e) { | ||||
if (!lightbox) { | if (!lightbox) { | ||||
return; | return; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | function (e) { | ||||
// Don't close if they clicked some other element, like the image | // Don't close if they clicked some other element, like the image | ||||
// itself or the next/previous arrows. | // itself or the next/previous arrows. | ||||
return; | return; | ||||
} | } | ||||
closeLightBox(e); | closeLightBox(e); | ||||
e.kill(); | e.kill(); | ||||
}); | }); | ||||
JX.Stratcom.listen( | |||||
'click', | |||||
'lightbox-comment', | |||||
_toggleComment); | |||||
Not Done Inline Actions(Weird indent.) epriestley: (Weird indent.) | |||||
}); | }); |
This should be markCommentsLoading(true) -- comments are now loading?
I think it's slightly better to sequence this code like this:
That is, mark loading first, then start the workflow.
If you do it in the other order, it's possible that we'll introduce some kind of, e.g., caching or optimization into Workflow later (or change JX.Workflow to a different call to fetch data) that makes it return immediately, inside start(). If we do, code like this won't work:
There isn't any particular reason to believe we'll make this change, but I think the code is more robust overall in the other order.