diff --git a/notebook/static/notebook/js/celltoolbarpresets/tags.js b/notebook/static/notebook/js/celltoolbarpresets/tags.js new file mode 100644 index 0000000000..6289e7082f --- /dev/null +++ b/notebook/static/notebook/js/celltoolbarpresets/tags.js @@ -0,0 +1,251 @@ +// Copyright (c) Jupyter Development Team. +// Distributed under the terms of the Modified BSD License. + +define([ + 'notebook/js/celltoolbar', + 'base/js/dialog', +], function(celltoolbar, dialog) { + "use strict"; + + var CellToolbar = celltoolbar.CellToolbar; + + var array_difference = function(a, b) { + return a.filter(function(n) { + return b.indexOf(n) === -1; + }); + } + + var write_tag = function(cell, name, add) { + if (add) { + // Add to metadata + if (cell.metadata.tags === undefined) { + cell.metadata.tags = []; + } else if (cell.metadata.tags.indexOf(name) !== -1) { + // Tag already exists + return false; + } + cell.metadata.tags.push(name); + } else { + // Remove from metadata + if (!cell.metadata || !cell.metadata.tags) { + // No tags to remove + return false; + } + // Remove tag from tags list + var index = cell.metadata.tags.indexOf(name); + if (index !== -1) { + cell.metadata.tags.splice(index, 1); + } + // If tags list is empty, remove it + if (cell.metadata.tags.length === 0) { + delete cell.metadata.tags; + } + } + cell.events.trigger('set_dirty.Notebook', {value: true}); + return true; + } + + var preprocess_input = function(input) { + // Split on whitespace: + return input.split(/\s/); + } + + var add_tag = function(cell, tag_container, on_remove) { + return function(name) { + if (name === '') { + // Skip empty strings + return; + } + // Write tag to metadata + var changed = write_tag(cell, name, true); + + if (changed) { + // Make tag UI + var tag = make_tag(name, on_remove); + tag_container.append(tag); + var tag_map = jQuery.data(tag_container, "tag_map") || {}; + tag_map[name] = tag; + jQuery.data(tag_container, 'tag_map', tag_map); + } + }; + }; + + var remove_tag = function(cell, tag_container) { + return function(name) { + var changed = write_tag(cell, name, false); + if (changed) { + // Remove tag UI + var tag_map = jQuery.data(tag_container, "tag_map") || {}; + var tag_UI = tag_map[name]; + delete tag_map[name]; + tag_UI.remove(); + } + }; + }; + + var init_tag_container = function(cell, tag_container, on_remove) { + var tag_list = cell.metadata.tags || []; + if (!Array.isArray(tag_list)) { + // We cannot make tags UI for this cell! + // Maybe someone else used "tags" for something? + return false; // Fail gracefully + } + + var tag_map = {}; + for (var i=0; i < tag_list.length; ++i) { + var tag_name = tag_list[i]; + if (typeof tag_name !== 'string') { + // Unexpected type, disable toolbar for safety + return false; + } + var tag = make_tag(tag_name, on_remove); + tag_container.append(tag); + tag_map[tag_name] = tag; + } + jQuery.data(tag_container, 'tag_map', tag_map); + return true; + }; + + var make_tag = function(name, on_remove) { + var tag_UI = $('') + .addClass('cell-tag') + .text(name); + + var remove_button = $('') + .addClass('remove-tag-btn') + .text('X') + .click( function(ev) { + if (ev.button === 0) { + on_remove(name); + return false; + } + }); + tag_UI.append(remove_button); + return tag_UI; + }; + + // Single edit with button to add tags + var add_tag_edit = function(div, cell, on_add, on_remove) { + var button_container = $(div); + + var text = $('').attr('type', 'text'); + var button = $('') + .addClass('btn btn-default btn-xs') + .text('Add tag') + .click(function() { + var tags = preprocess_input(text[0].value); + for (var i=0; i < tags.length; ++i) { + on_add(tags[i]); + } + // Clear input after adding: + text[0].value = ''; + return false; + }); + // Wire enter in input to button click + text.keyup(function(event){ + if(event.keyCode == 13){ + button.click(); + } + }); + var input_container = $('') + .addClass('tags-input') + add_dialog_button(input_container, cell, on_add, on_remove); + button_container.append(input_container + .append(text) + .append(button) + ); + IPython.keyboard_manager.register_events(text); + }; + + var tag_dialog = function(cell, on_add, on_remove) { + var tag_list = cell.metadata.tags || []; + + var message = + "Edit the list of tags below. All whitespace " + + "is treated as tag separators."; + + var textarea = $('') + .attr('rows', '13') + .attr('cols', '80') + .attr('name', 'tags') + .text(tag_list.join('\n')); + + var dialogform = $('
').attr('title', 'Edit the tags') + .append( + $('').append( + $('').append( + $('') + .attr('for','tags') + .text(message) + ) + .append($('