/** * @provides javelin-behavior-pholio-mock-edit * @requires javelin-behavior * javelin-stratcom * javelin-dom * javelin-workflow * javelin-quicksand * phabricator-phtize * phabricator-drag-and-drop-file-upload * phabricator-draggable-list */ JX.behavior('pholio-mock-edit', function(config, statics) { var pht = JX.phtize(config.pht); var uploading = []; /* -( Deleting Images )---------------------------------------------------- */ // When the user clicks the "X" on an image, we replace it with a "click to // undo" element. If they click to undo, we put the original node back in the // DOM. var pholio_drop_remove = function(e) { e.kill(); var node = e.getNode('pholio-drop-image'); var undo = render_undo(); JX.DOM.listen(undo, 'click', 'pholio-drop-undo', function(e) { e.kill(); JX.DOM.replace(undo, node); synchronize_order(); }); JX.DOM.replace(node, undo); synchronize_order(); }; /* -( Reordering Images )-------------------------------------------------- */ // Reflect the display order in a hidden input. var synchronize_order = function() { var items = statics.draglist.findItems(); var order = []; for (var ii = 0; ii < items.length; ii++) { order.push(JX.Stratcom.getData(items[ii]).filePHID); } statics.nodes.order.value = order.join(','); }; var build_draglist = function(node) { var draglist = new JX.DraggableList('pholio-drop-image', node) .setGhostNode(JX.$N('div', {className: 'drag-ghost'})) .setFindItemsHandler(function() { return JX.DOM.scry(node, 'div', 'pholio-drop-image'); }); // Only let the user drag images by the handle, not the whole entry. draglist.listen('shouldBeginDrag', function(e) { if (!e.getNode('pholio-drag-handle')) { JX.Stratcom.context().prevent(); } }); draglist.listen('didDrop', synchronize_order); return draglist; }; /* -( Build )-------------------------------------------------------------- */ var build_drop_upload = function(node) { var drop = new JX.PhabricatorDragAndDropFileUpload(node) .setURI(config.uploadURI); drop.listen('didBeginDrag', function() { JX.DOM.alterClass(node, 'pholio-drop-active', true); }); drop.listen('didEndDrag', function() { JX.DOM.alterClass(node, 'pholio-drop-active', false); }); return drop; }; var build_add_control = function(add_node) { var drop = build_drop_upload(add_node); drop.listen('willUpload', function(file) { var node = render_uploading(); uploading.push({node: node, file: file}); statics.nodes.list.appendChild(node); }); drop.listen('didUpload', function(file) { var node; for (var ii = 0; ii < uploading.length; ii++) { if (uploading[ii].file === file) { node = uploading[ii].node; uploading.splice(ii, 1); break; } } render_upload(node, file); }); drop.start(); JX.DOM.listen(add_node, 'click', null, function(e) { e.kill(); new JX.Workflow('/file/uploaddialog/') .setHandler(function(response) { var files = response.files; for (var ii = 0; ii < files.length; ii++) { var file = files[ii]; var upload = new JX.PhabricatorFileUpload() .setID(file.id) .setPHID(file.phid) .setURI(file.uri); var node = render_uploading(); statics.nodes.list.appendChild(node); render_upload(node, upload); } }) .start(); }); }; var render_upload = function(node, file) { JX.DOM.setContent(node, pht('uploaded')); new JX.Workflow(config.renderURI, {filePHID: file.getPHID()}) .setHandler(function(response) { var new_node = JX.$H(response.markup).getFragment().firstChild; build_update_control(new_node); JX.DOM.replace(node, new_node); synchronize_order(); }) .start(); }; var build_list_controls = function(list_node) { var nodes = JX.DOM.scry(list_node, 'div', 'pholio-drop-image'); for (var ii = 0; ii < nodes.length; ii++) { build_update_control(nodes[ii]); } }; var build_update_control = function(node) { var did_upload = function(node, file) { var node_data = JX.Stratcom.getData(node); var data = { filePHID: file.getPHID(), replacesPHID: node_data.replacesPHID || node_data.filePHID || null, title: JX.DOM.find(node, 'input', 'image-title').value, description: JX.DOM.find(node, 'textarea', 'image-description').value }; new JX.Workflow(config.renderURI, data) .setHandler(function(response) { var new_node = JX.$H(response.markup).getFragment().firstChild; build_update_control(new_node); JX.DOM.replace(node, new_node); JX.DOM.alterClass(node, 'pholio-replacing', false); synchronize_order(); }) .start(); }; var drop = build_drop_upload(node); drop.listen('willUpload', function() { JX.DOM.alterClass(node, 'pholio-replacing', true); }); drop.listen('didUpload', function(file) { did_upload(node, file); }); drop.start(); JX.DOM.listen(node, 'click', 'pholio-uploaded-thumb', function(e) { e.kill(); new JX.Workflow('/file/uploaddialog/single/') .setHandler(function(response) { var files = response.files; for (var ii = 0; ii < files.length; ii++) { var file = files[ii]; var upload = new JX.PhabricatorFileUpload() .setID(file.id) .setPHID(file.phid) .setURI(file.uri); did_upload(node, upload); } }) .start(); }); }; /* -( Rendering )---------------------------------------------------------- */ var render_uploading = function() { return JX.$N( 'div', {className: 'pholio-drop-uploading'}, pht('uploading')); }; var render_undo = function() { var link = JX.$N( 'a', {href: '#', sigil: 'pholio-drop-undo'}, pht('undo')); return JX.$N( 'div', {className: 'pholio-drop-undo'}, [pht('removed'), ' ', link]); }; /* -( Init )--------------------------------------------------------------- */ function update_statics(data, page_id, no_build) { statics.nodes = { list: JX.$(data.listID), drop: JX.$(data.dropID), order: JX.$(data.orderID) }; if (!statics.mockEditCache[page_id]) { statics.mockEditCache[page_id] = {}; } statics.mockEditCache[page_id].config = config; statics.mockEditCache[page_id].nodes = statics.nodes; if (no_build !== true) { build_add_control(statics.nodes.drop); build_list_controls(statics.nodes.list); statics.draglist = build_draglist(statics.nodes.list); statics.mockEditCache[page_id].draglist = statics.draglist; } else { statics.draglist = statics.mockEditCache[page_id].draglist; } synchronize_order(); } function install() { statics.mockEditCache = {}; JX.Stratcom.listen('click', 'pholio-drop-remove', pholio_drop_remove); JX.Stratcom.listen( 'quicksand-redraw', null, function (e) { e.kill(); var data = e.getData(); if (!data.newResponse.mockEditConfig) { return; } if (data.fromServer) { // we ran update_statics(config) below already } else { var page_id = data.newResponseID; var new_config = statics.mockEditCache[page_id].config; update_statics(new_config, page_id, true); } }); return true; } statics.installed = statics.installed || install(); update_statics(config, JX.Quicksand.getCurrentPageID(), false); });