mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 17:02:41 +01:00
1663dc32c9
Summary: ...bsasically add a "view mode" and play with that throughout the stack. Differences are... - normal mode has comments; history mode does not - normal mode has inline comments; history mode does not - page uris are correct with respect to either mode ...and that's about it. I played around (wasted too much time) trying to make this cuter. I think just jamming this mode in here is the easiest / cleanest thing at the end. Feel free to tell me otherwise! This largely gets even better via T3612. However, this fixes T3572. Test Plan: played around with a mock with some history. noted correct uris on images. noted no errors in js console. Reviewers: epriestley Reviewed By: epriestley CC: aran, Korvin Maniphest Tasks: T3572 Differential Revision: https://secure.phabricator.com/D6638
855 lines
20 KiB
JavaScript
855 lines
20 KiB
JavaScript
/**
|
|
* @provides javelin-behavior-pholio-mock-view
|
|
* @requires javelin-behavior
|
|
* javelin-util
|
|
* javelin-stratcom
|
|
* javelin-dom
|
|
* javelin-vector
|
|
* javelin-magical-init
|
|
* javelin-request
|
|
* javelin-history
|
|
* javelin-workflow
|
|
* javelin-mask
|
|
* javelin-behavior-device
|
|
* phabricator-keyboard-shortcut
|
|
*/
|
|
JX.behavior('pholio-mock-view', function(config) {
|
|
var is_dragging = false;
|
|
|
|
var drag_begin;
|
|
var drag_end;
|
|
var panel = JX.$(config.panelID);
|
|
var viewport = JX.$(config.viewportID);
|
|
|
|
var selection_border;
|
|
var selection_fill;
|
|
var active_image;
|
|
|
|
var inline_comments = {};
|
|
|
|
|
|
/* -( Stage )-------------------------------------------------------------- */
|
|
|
|
|
|
var stage = (function() {
|
|
var loading = false;
|
|
var stageElement = JX.$(config.panelID);
|
|
var viewElement = JX.$(config.viewportID);
|
|
var gutterElement = JX.$('mock-inline-comments');
|
|
var reticles = [];
|
|
var cards = [];
|
|
var inline_phid_map = {};
|
|
|
|
function begin_load() {
|
|
if (loading) {
|
|
return;
|
|
}
|
|
loading = true;
|
|
clear_stage();
|
|
draw_loading();
|
|
}
|
|
|
|
function end_load() {
|
|
if (!loading) {
|
|
return;
|
|
}
|
|
loading = false;
|
|
draw_loading();
|
|
}
|
|
|
|
function draw_loading() {
|
|
JX.DOM.alterClass(stageElement, 'pholio-image-loading', loading);
|
|
}
|
|
|
|
function add_inline_node(node, phid) {
|
|
inline_phid_map[phid] = (inline_phid_map[phid] || []);
|
|
inline_phid_map[phid].push(node);
|
|
}
|
|
|
|
function add_reticle(reticle, phid) {
|
|
mark_ref(reticle, phid);
|
|
|
|
reticles.push(reticle);
|
|
add_inline_node(reticle, phid);
|
|
|
|
viewElement.appendChild(reticle);
|
|
}
|
|
|
|
function clear_stage() {
|
|
var ii;
|
|
for (ii = 0; ii < reticles.length; ii++) {
|
|
JX.DOM.remove(reticles[ii]);
|
|
}
|
|
for (ii = 0; ii < cards.length; ii++) {
|
|
JX.DOM.remove(cards[ii]);
|
|
}
|
|
reticles = [];
|
|
cards = [];
|
|
inline_phid_map = {};
|
|
}
|
|
|
|
function highlight_inline(phid, show) {
|
|
var nodes = inline_phid_map[phid] || [];
|
|
var cls = 'pholio-mock-inline-comment-highlight';
|
|
for (var ii = 0; ii < nodes.length; ii++) {
|
|
JX.DOM.alterClass(nodes[ii], cls, show);
|
|
}
|
|
}
|
|
|
|
function remove_inline(phid) {
|
|
var nodes = inline_phid_map[phid] || [];
|
|
for (var ii = 0; ii < nodes.length; ii++) {
|
|
JX.DOM.remove(nodes[ii]);
|
|
}
|
|
delete inline_phid_map[phid];
|
|
}
|
|
|
|
function mark_ref(node, phid) {
|
|
JX.Stratcom.addSigil(node, 'pholio-inline-ref');
|
|
JX.Stratcom.addData(node, {phid: phid});
|
|
}
|
|
|
|
function add_card(card, phid) {
|
|
mark_ref(card, phid);
|
|
|
|
cards.push(card);
|
|
add_inline_node(card, phid);
|
|
|
|
gutterElement.appendChild(card);
|
|
}
|
|
|
|
return {
|
|
beginLoad: begin_load,
|
|
endLoad: end_load,
|
|
addReticle: add_reticle,
|
|
clearStage: clear_stage,
|
|
highlightInline: highlight_inline,
|
|
removeInline: remove_inline,
|
|
addCard: add_card
|
|
};
|
|
})();
|
|
|
|
function get_image_index(id) {
|
|
for (var ii = 0; ii < config.images.length; ii++) {
|
|
if (config.images[ii].id == id) {
|
|
return ii;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function get_image(id) {
|
|
var idx = get_image_index(id);
|
|
if (idx === null) {
|
|
return idx;
|
|
}
|
|
return config.images[idx];
|
|
}
|
|
|
|
function onload_image(id) {
|
|
if (active_image.id != id) {
|
|
// The user has clicked another image before this one loaded, so just
|
|
// bail.
|
|
return;
|
|
}
|
|
|
|
active_image.tag = this;
|
|
redraw_image();
|
|
}
|
|
|
|
function switch_image(delta) {
|
|
if (!active_image) {
|
|
return;
|
|
}
|
|
var idx = get_image_index(active_image.id);
|
|
idx = (idx + delta + config.images.length) % config.images.length;
|
|
select_image(config.images[idx].id);
|
|
}
|
|
|
|
function redraw_image() {
|
|
|
|
// Force the stage to scale as a function of the viewport size. Broadly,
|
|
// we make the stage 95% of the height of the viewport, then scale images
|
|
// to fit within it.
|
|
var new_y = (JX.Vector.getViewport().y * 0.90) - 150;
|
|
new_y = Math.max(320, new_y);
|
|
panel.style.height = new_y + 'px';
|
|
|
|
if (!active_image || !active_image.tag) {
|
|
return;
|
|
}
|
|
|
|
var tag = active_image.tag;
|
|
|
|
// If the image is too wide or tall for the viewport, scale it down so it
|
|
// fits.
|
|
var w = JX.Vector.getDim(panel);
|
|
w.x -= 40;
|
|
w.y -= 40;
|
|
var scale = 1;
|
|
if (w.x < tag.naturalWidth) {
|
|
scale = Math.min(scale, w.x / tag.naturalWidth);
|
|
}
|
|
if (w.y < tag.naturalHeight) {
|
|
scale = Math.min(scale, w.y / tag.naturalHeight);
|
|
}
|
|
|
|
if (scale < 1) {
|
|
tag.width = Math.floor(scale * tag.naturalWidth);
|
|
tag.height = Math.floor(scale * tag.naturalHeight);
|
|
} else {
|
|
tag.width = tag.naturalWidth;
|
|
tag.height = tag.naturalHeight;
|
|
}
|
|
|
|
viewport.style.top = Math.floor((new_y - tag.height) / 2) + 'px';
|
|
|
|
stage.endLoad();
|
|
|
|
JX.DOM.setContent(viewport, tag);
|
|
|
|
redraw_inlines(active_image.id);
|
|
}
|
|
|
|
function select_image(image_id) {
|
|
active_image = get_image(image_id);
|
|
active_image.tag = null;
|
|
|
|
stage.beginLoad();
|
|
|
|
var img = JX.$N('img', {className: 'pholio-mock-image'});
|
|
img.onload = JX.bind(img, onload_image, active_image.id);
|
|
img.src = active_image.fullURI;
|
|
|
|
var thumbs = JX.DOM.scry(
|
|
JX.$('pholio-mock-carousel'),
|
|
'a',
|
|
'mock-thumbnail');
|
|
|
|
for(var k in thumbs) {
|
|
var thumb_meta = JX.Stratcom.getData(thumbs[k]);
|
|
|
|
JX.DOM.alterClass(
|
|
thumbs[k],
|
|
'pholio-mock-carousel-thumb-current',
|
|
(active_image.id == thumb_meta.imageID));
|
|
}
|
|
|
|
load_inline_comments();
|
|
|
|
if (image_id != config.selectedID) {
|
|
JX.History.replace(active_image.pageURI);
|
|
}
|
|
}
|
|
|
|
JX.Stratcom.listen(
|
|
['mousedown', 'click'],
|
|
'mock-thumbnail',
|
|
function(e) {
|
|
if (!e.isNormalMouseEvent()) {
|
|
return;
|
|
}
|
|
e.kill();
|
|
select_image(e.getNodeData('mock-thumbnail').imageID);
|
|
});
|
|
|
|
select_image(config.selectedID);
|
|
|
|
JX.Stratcom.listen('mousedown', 'mock-viewport', function(e) {
|
|
if (!e.isNormalMouseEvent()) {
|
|
return;
|
|
}
|
|
|
|
if (JX.Device.getDevice() != 'desktop') {
|
|
return;
|
|
}
|
|
|
|
if (config.viewMode == 'history') {
|
|
return;
|
|
}
|
|
|
|
if (drag_begin) {
|
|
return;
|
|
}
|
|
|
|
e.kill();
|
|
|
|
is_dragging = true;
|
|
drag_begin = get_image_xy(JX.$V(e));
|
|
drag_end = drag_begin;
|
|
|
|
redraw_selection();
|
|
});
|
|
|
|
|
|
JX.enableDispatch(document.body, 'mousemove');
|
|
JX.Stratcom.listen('mousemove', null, function(e) {
|
|
if (!is_dragging) {
|
|
return;
|
|
}
|
|
drag_end = get_image_xy(JX.$V(e));
|
|
redraw_selection();
|
|
});
|
|
|
|
JX.Stratcom.listen(
|
|
['mouseover', 'mouseout'],
|
|
'pholio-inline-ref',
|
|
function(e) {
|
|
var phid = e.getNodeData('pholio-inline-ref').phid;
|
|
var show = (e.getType() == 'mouseover');
|
|
stage.highlightInline(phid, show);
|
|
});
|
|
|
|
JX.Stratcom.listen(
|
|
'mouseup',
|
|
null,
|
|
function(e) {
|
|
if (!is_dragging) {
|
|
return;
|
|
}
|
|
|
|
is_dragging = false;
|
|
if (!config.loggedIn) {
|
|
new JX.Workflow(config.logInLink).start();
|
|
return;
|
|
}
|
|
|
|
drag_end = get_image_xy(JX.$V(e));
|
|
var scale = get_image_scale();
|
|
|
|
resize_selection(16);
|
|
|
|
var data = {mockID: config.mockID};
|
|
var handler = function(r) {
|
|
var dialog = JX.$H(r).getFragment().firstChild;
|
|
JX.DOM.appendContent(viewport, dialog);
|
|
|
|
var x = Math.min(drag_begin.x * scale, drag_end.x * scale);
|
|
var y = Math.max(drag_begin.y * scale, drag_end.y * scale) + 4;
|
|
JX.$V(x, y).setPos(dialog);
|
|
|
|
JX.DOM.focus(JX.DOM.find(dialog, 'textarea'));
|
|
};
|
|
|
|
new JX.Workflow('/pholio/inline/save/', data)
|
|
.setHandler(handler)
|
|
.start();
|
|
});
|
|
|
|
function resize_selection(min_size) {
|
|
var start = {
|
|
x: Math.min(drag_begin.x, drag_end.x),
|
|
y: Math.min(drag_begin.y, drag_end.y)
|
|
};
|
|
var end = {
|
|
x: Math.max(drag_begin.x, drag_end.x),
|
|
y: Math.max(drag_begin.y, drag_end.y)
|
|
};
|
|
|
|
var width = end.x - start.x;
|
|
var height = end.y - start.y;
|
|
var addon;
|
|
|
|
if (width < min_size) {
|
|
addon = (min_size-width)/2;
|
|
|
|
start.x = Math.max(0, start.x - addon);
|
|
end.x = Math.min(active_image.tag.naturalWidth, end.x + addon);
|
|
|
|
if (start.x === 0) {
|
|
end.x = Math.min(min_size, active_image.tag.naturalWidth);
|
|
} else if (end.x == active_image.tag.naturalWidth) {
|
|
start.x = Math.max(0, active_image.tag.naturalWidth - min_size);
|
|
}
|
|
}
|
|
|
|
if (height < min_size) {
|
|
addon = (min_size-height)/2;
|
|
|
|
start.y = Math.max(0, start.y - addon);
|
|
end.y = Math.min(active_image.tag.naturalHeight, end.y + addon);
|
|
|
|
if (start.y === 0) {
|
|
end.y = Math.min(min_size, active_image.tag.naturalHeight);
|
|
} else if (end.y == active_image.tag.naturalHeight) {
|
|
start.y = Math.max(0, active_image.tag.naturalHeight - min_size);
|
|
}
|
|
}
|
|
|
|
drag_begin = start;
|
|
drag_end = end;
|
|
redraw_selection();
|
|
}
|
|
|
|
function redraw_inlines(id) {
|
|
if (!active_image) {
|
|
return;
|
|
}
|
|
|
|
if (active_image.id != id) {
|
|
return;
|
|
}
|
|
|
|
stage.clearStage();
|
|
var comment_holder = JX.$('mock-inline-comments');
|
|
JX.DOM.setContent(comment_holder, render_image_info(active_image));
|
|
|
|
var inlines = inline_comments[active_image.id];
|
|
if (!inlines || !inlines.length) {
|
|
return;
|
|
}
|
|
|
|
for (var ii = 0; ii < inlines.length; ii++) {
|
|
var inline = inlines[ii];
|
|
var card = JX.$H(inline.contentHTML).getFragment().firstChild;
|
|
|
|
stage.addCard(card, inline.phid);
|
|
|
|
if (!active_image.tag) {
|
|
// The image itself hasn't loaded yet, so we can't draw the inline
|
|
// reticles.
|
|
continue;
|
|
}
|
|
|
|
var inline_selection = render_reticle_fill();
|
|
stage.addReticle(inline_selection, inline.phid);
|
|
position_inline_rectangle(inline, inline_selection);
|
|
|
|
if (!inline.transactionphid) {
|
|
var inline_draft = render_reticle_border();
|
|
stage.addReticle(inline_draft, inline.phid);
|
|
position_inline_rectangle(inline, inline_draft);
|
|
}
|
|
}
|
|
}
|
|
|
|
function position_inline_rectangle(inline, rect) {
|
|
var scale = get_image_scale();
|
|
|
|
JX.$V(scale * inline.x, scale * inline.y).setPos(rect);
|
|
JX.$V(scale * inline.width, scale * inline.height).setDim(rect);
|
|
}
|
|
|
|
function get_image_xy(p) {
|
|
var img = active_image.tag;
|
|
var imgp = JX.$V(img);
|
|
|
|
var scale = 1 / get_image_scale();
|
|
|
|
var x = scale * Math.max(0, Math.min(p.x - imgp.x, img.width));
|
|
var y = scale * Math.max(0, Math.min(p.y - imgp.y, img.height));
|
|
|
|
return {
|
|
x: x,
|
|
y: y
|
|
};
|
|
}
|
|
|
|
function get_image_scale() {
|
|
var img = active_image.tag;
|
|
return Math.min(
|
|
img.width / img.naturalWidth,
|
|
img.height / img.naturalHeight);
|
|
}
|
|
|
|
function redraw_selection() {
|
|
selection_border = selection_border || render_reticle_border();
|
|
selection_fill = selection_fill || render_reticle_fill();
|
|
|
|
var p = JX.$V(
|
|
Math.min(drag_begin.x, drag_end.x),
|
|
Math.min(drag_begin.y, drag_end.y));
|
|
|
|
var d = JX.$V(
|
|
Math.max(drag_begin.x, drag_end.x) - p.x,
|
|
Math.max(drag_begin.y, drag_end.y) - p.y);
|
|
|
|
var scale = get_image_scale();
|
|
|
|
p.x *= scale;
|
|
p.y *= scale;
|
|
d.x *= scale;
|
|
d.y *= scale;
|
|
|
|
var nodes = [selection_fill, selection_border];
|
|
for (var ii = 0; ii < nodes.length; ii++) {
|
|
var node = nodes[ii];
|
|
viewport.appendChild(node);
|
|
p.setPos(node);
|
|
d.setDim(node);
|
|
}
|
|
}
|
|
|
|
function clear_selection() {
|
|
selection_fill && JX.DOM.remove(selection_fill);
|
|
selection_border && JX.DOM.remove(selection_border);
|
|
}
|
|
|
|
function load_inline_comments() {
|
|
var id = active_image.id;
|
|
var inline_comments_uri = "/pholio/inline/" + id + "/";
|
|
|
|
new JX.Request(inline_comments_uri, function(r) {
|
|
inline_comments[id] = r;
|
|
redraw_inlines(id);
|
|
}).send();
|
|
}
|
|
|
|
JX.Stratcom.listen(
|
|
'click',
|
|
'inline-delete',
|
|
function(e) {
|
|
var data = e.getNodeData('inline-delete');
|
|
e.kill();
|
|
interrupt_typing();
|
|
|
|
stage.removeInline(data.phid);
|
|
|
|
var deleteURI = '/pholio/inline/delete/' + data.id + '/';
|
|
var del = new JX.Request(deleteURI, function(r) {
|
|
|
|
});
|
|
del.send();
|
|
|
|
});
|
|
|
|
JX.Stratcom.listen(
|
|
'click',
|
|
'inline-edit',
|
|
function(e) {
|
|
var data = e.getNodeData('inline-edit');
|
|
e.kill();
|
|
|
|
interrupt_typing();
|
|
|
|
var editURI = "/pholio/inline/edit/" + data.id + '/';
|
|
|
|
var edit_dialog = new JX.Request(editURI, function(r) {
|
|
var dialog = JX.$N(
|
|
'div',
|
|
{
|
|
className: 'pholio-edit-inline-popup'
|
|
},
|
|
JX.$H(r));
|
|
|
|
JX.DOM.setContent(JX.$(data.phid + '_comment'), dialog);
|
|
});
|
|
|
|
edit_dialog.send();
|
|
});
|
|
|
|
JX.Stratcom.listen(
|
|
'click',
|
|
'inline-edit-cancel',
|
|
function(e) {
|
|
var data = e.getNodeData('inline-edit-cancel');
|
|
e.kill();
|
|
load_inline_comment(data.id);
|
|
});
|
|
|
|
JX.Stratcom.listen(
|
|
'click',
|
|
'inline-edit-submit',
|
|
function(e) {
|
|
var data = e.getNodeData('inline-edit-submit');
|
|
var editURI = "/pholio/inline/edit/" + data.id + '/';
|
|
e.kill();
|
|
|
|
var edit = new JX.Request(editURI, function(r) {
|
|
load_inline_comment(data.id);
|
|
JX.DOM.invoke(JX.$(config.commentFormID), 'shouldRefresh');
|
|
});
|
|
edit.addData({
|
|
op: 'update',
|
|
content: JX.DOM.find(JX.$(data.phid + '_comment'), 'textarea').value
|
|
});
|
|
edit.send();
|
|
});
|
|
|
|
JX.Stratcom.listen(
|
|
'click',
|
|
'inline-save-cancel',
|
|
function(e) {
|
|
e.kill();
|
|
interrupt_typing();
|
|
}
|
|
);
|
|
|
|
JX.Stratcom.listen(
|
|
'click',
|
|
'inline-save-submit',
|
|
function(e) {
|
|
e.kill();
|
|
|
|
var form = JX.$('pholio-new-inline-comment-dialog');
|
|
var text = JX.DOM.find(form, 'textarea').value;
|
|
if (!text.length) {
|
|
interrupt_typing();
|
|
return;
|
|
}
|
|
|
|
var data = {
|
|
mockID: config.mockID,
|
|
imageID: active_image.id,
|
|
startX: Math.min(drag_begin.x, drag_end.x),
|
|
startY: Math.min(drag_begin.y, drag_end.y),
|
|
endX: Math.max(drag_begin.x, drag_end.x),
|
|
endY: Math.max(drag_begin.y, drag_end.y)
|
|
};
|
|
|
|
var handler = function(r) {
|
|
if (!inline_comments[active_image.id]) {
|
|
inline_comments[active_image.id] = [];
|
|
}
|
|
inline_comments[active_image.id].push(r);
|
|
|
|
interrupt_typing();
|
|
redraw_inlines(active_image.id);
|
|
JX.DOM.invoke(JX.$(config.commentFormID), 'shouldRefresh');
|
|
};
|
|
|
|
JX.Workflow.newFromForm(form, data)
|
|
.setHandler(handler)
|
|
.start();
|
|
}
|
|
);
|
|
|
|
function load_inline_comment(id) {
|
|
var viewInlineURI = '/pholio/inline/view/' + id + '/';
|
|
var inline_comment = new JX.Request(viewInlineURI, function(r) {
|
|
JX.DOM.replace(JX.$(r.phid + '_comment'), JX.$H(r.contentHTML));
|
|
});
|
|
inline_comment.send();
|
|
}
|
|
|
|
function interrupt_typing() {
|
|
clear_selection();
|
|
|
|
try {
|
|
JX.DOM.remove(JX.$('pholio-new-inline-comment-dialog'));
|
|
} catch (x) {
|
|
// TODO: For now, ignore this.
|
|
}
|
|
|
|
drag_begin = null;
|
|
}
|
|
|
|
load_inline_comments();
|
|
if (config.loggedIn && config.commentFormID) {
|
|
JX.DOM.invoke(JX.$(config.commentFormID), 'shouldRefresh');
|
|
}
|
|
|
|
JX.Stratcom.listen('resize', null, redraw_image);
|
|
redraw_image();
|
|
|
|
|
|
/* -( Keyboard Shortcuts )------------------------------------------------- */
|
|
|
|
|
|
new JX.KeyboardShortcut(['j', 'right'], 'Show next image.')
|
|
.setHandler(function() {
|
|
switch_image(1);
|
|
})
|
|
.register();
|
|
|
|
new JX.KeyboardShortcut(['k', 'left'], 'Show previous image.')
|
|
.setHandler(function() {
|
|
switch_image(-1);
|
|
})
|
|
.register();
|
|
|
|
JX.DOM.listen(panel, 'gesture.swipe.end', null, function(e) {
|
|
var data = e.getData();
|
|
|
|
if (data.length <= (JX.Vector.getDim(panel) / 2)) {
|
|
// If the user didn't move their finger far enough, don't switch.
|
|
return;
|
|
}
|
|
|
|
switch_image(data.direction == 'right' ? -1 : 1);
|
|
});
|
|
|
|
/* -( Render )------------------------------------------------------------- */
|
|
|
|
|
|
function render_image_info(image) {
|
|
var info = [];
|
|
|
|
var title = JX.$N(
|
|
'div',
|
|
{className: 'pholio-image-title'},
|
|
image.title);
|
|
info.push(title);
|
|
|
|
var desc = JX.$N(
|
|
'div',
|
|
{className: 'pholio-image-description'},
|
|
image.desc);
|
|
info.push(desc);
|
|
|
|
if (!image.isObsolete) {
|
|
var embed = JX.$N(
|
|
'div',
|
|
{className: 'pholio-image-embedding'},
|
|
JX.$H('Embed this image:<br />{M' + config.mockID +
|
|
', image=' + image.id + '}'));
|
|
info.push(embed);
|
|
}
|
|
|
|
// Render image dimensions and visible size. If we have this infomation
|
|
// from the server we can display some of it immediately; otherwise, we need
|
|
// to wait for the image to load so we can read dimension information from
|
|
// it.
|
|
|
|
var image_x = image.width;
|
|
var image_y = image.height;
|
|
var display_x = null;
|
|
if (image.tag) {
|
|
image_x = image.tag.naturalWidth;
|
|
image_y = image.tag.naturalHeight;
|
|
display_x = image.tag.width;
|
|
}
|
|
|
|
var visible = [];
|
|
if (image_x) {
|
|
visible.push([image_x, '\u00d7', image_y, 'px']);
|
|
if (display_x) {
|
|
var area = Math.round(100 * (display_x / image_x));
|
|
visible.push(' ');
|
|
visible.push(
|
|
JX.$N(
|
|
'span',
|
|
{className: 'pholio-visible-size'},
|
|
['(', area, '%', ')']));
|
|
}
|
|
}
|
|
|
|
if (visible.length) {
|
|
info.push(visible);
|
|
}
|
|
|
|
var full_link = JX.$N(
|
|
'a',
|
|
{href: image.fullURI, target: '_blank'},
|
|
'View Full Image');
|
|
info.push(full_link);
|
|
|
|
if (config.viewMode != 'history') {
|
|
var history_link = JX.$N(
|
|
'a',
|
|
{ href: image.historyURI },
|
|
'View Image History');
|
|
info.push(history_link);
|
|
}
|
|
|
|
|
|
for (var ii = 0; ii < info.length; ii++) {
|
|
info[ii] = JX.$N('div', {className: 'pholio-image-info-item'}, info[ii]);
|
|
}
|
|
info = JX.$N('div', {className: 'pholio-image-info'}, info);
|
|
|
|
return info;
|
|
}
|
|
|
|
function render_reticle_border() {
|
|
return JX.$N(
|
|
'div',
|
|
{className: 'pholio-mock-select-border'});
|
|
}
|
|
|
|
function render_reticle_fill() {
|
|
return JX.$N(
|
|
'div',
|
|
{className: 'pholio-mock-select-fill'});
|
|
}
|
|
|
|
|
|
/* -( Device Lightbox )---------------------------------------------------- */
|
|
|
|
// On devices, we show images full-size when the user taps them instead of
|
|
// attempting to implement inlines.
|
|
|
|
var lightbox = null;
|
|
|
|
JX.Stratcom.listen('click', 'mock-viewport', function(e) {
|
|
if (!e.isNormalMouseEvent()) {
|
|
return;
|
|
}
|
|
if (JX.Device.getDevice() == 'desktop') {
|
|
return;
|
|
}
|
|
lightbox_attach();
|
|
e.kill();
|
|
});
|
|
|
|
JX.Stratcom.listen('click', 'pholio-device-lightbox', lightbox_detach);
|
|
JX.Stratcom.listen('resize', null, lightbox_resize);
|
|
|
|
function lightbox_attach() {
|
|
JX.DOM.alterClass(document.body, 'lightbox-attached', true);
|
|
JX.Mask.show('jx-dark-mask');
|
|
|
|
lightbox = lightbox_render();
|
|
var image = JX.$N('img');
|
|
image.onload = lightbox_loaded;
|
|
setTimeout(function() {
|
|
image.src = active_image.fullURI;
|
|
}, 1000);
|
|
JX.DOM.setContent(lightbox, image);
|
|
JX.DOM.alterClass(lightbox, 'pholio-device-lightbox-loading', true);
|
|
|
|
lightbox_resize();
|
|
|
|
document.body.appendChild(lightbox);
|
|
}
|
|
|
|
function lightbox_detach() {
|
|
JX.DOM.remove(lightbox);
|
|
JX.Mask.hide();
|
|
JX.DOM.alterClass(document.body, 'lightbox-attached', false);
|
|
lightbox = null;
|
|
}
|
|
|
|
function lightbox_resize(e) {
|
|
if (!lightbox) {
|
|
return;
|
|
}
|
|
JX.Vector.getScroll().setPos(lightbox);
|
|
JX.Vector.getViewport().setDim(lightbox);
|
|
}
|
|
|
|
function lightbox_loaded() {
|
|
JX.DOM.alterClass(lightbox, 'pholio-device-lightbox-loading', false);
|
|
}
|
|
|
|
function lightbox_render() {
|
|
var el = JX.$N('div', {className: 'pholio-device-lightbox'});
|
|
JX.Stratcom.addSigil(el, 'pholio-device-lightbox');
|
|
return el;
|
|
}
|
|
|
|
|
|
/* -( Preload )------------------------------------------------------------ */
|
|
|
|
var preload = [];
|
|
for (var ii = 0; ii < config.images.length; ii++) {
|
|
preload.push(config.images[ii].fullURI);
|
|
}
|
|
|
|
function preload_next() {
|
|
next_src = preload[0];
|
|
if (!next_src) {
|
|
return;
|
|
}
|
|
preload.splice(0, 1);
|
|
|
|
var img = JX.$N('img');
|
|
img.onload = preload_next;
|
|
img.onerror = preload_next;
|
|
img.src = next_src;
|
|
}
|
|
|
|
preload_next();
|
|
|
|
|
|
});
|