// Copyright (c) IPython Development Team. // Distributed under the terms of the Modified BSD License. define([ 'base/js/namespace', 'jquery', 'base/js/utils', 'base/js/dialog', 'base/js/events', 'base/js/keyboard', ], function(IPython, $, utils, dialog, events, keyboard) { "use strict"; var NotebookList = function (selector, options) { /** * Constructor * * Parameters: * selector: string * options: dictionary * Dictionary of keyword arguments. * session_list: SessionList instance * element_name: string * base_url: string * notebook_path: string * contents: Contents instance */ var that = this; this.session_list = options.session_list; // allow code re-use by just changing element_name in kernellist.js this.element_name = options.element_name || 'notebook'; this.selector = selector; if (this.selector !== undefined) { this.element = $(selector); this.style(); this.bind_events(); } this.notebooks_list = []; this.sessions = {}; this.base_url = options.base_url || utils.get_body_data("baseUrl"); this.notebook_path = options.notebook_path || utils.get_body_data("notebookPath"); this.contents = options.contents; if (this.session_list && this.session_list.events) { this.session_list.events.on('sessions_loaded.Dashboard', function(e, d) { that.sessions_loaded(d); }); } }; NotebookList.prototype.style = function () { var prefix = '#' + this.element_name; $(prefix + '_toolbar').addClass('list_toolbar'); $(prefix + '_list_info').addClass('toolbar_info'); $(prefix + '_buttons').addClass('toolbar_buttons'); $(prefix + '_list_header').addClass('list_header'); this.element.addClass("list_container"); }; NotebookList.prototype.bind_events = function () { var that = this; $('#refresh_' + this.element_name + '_list').click(function () { that.load_sessions(); }); this.element.bind('dragover', function () { return false; }); this.element.bind('drop', function(event){ that.handleFilesUpload(event,'drop'); return false; }); // Bind events for singleton controls. if (!NotebookList._bound_singletons) { NotebookList._bound_singletons = true; $('#new-file').click(function(e) { var w = window.open(); that.contents.new_untitled(that.notebook_path || '', {type: 'file', ext: '.txt'}).then(function(data) { var url = utils.url_join_encode( that.base_url, 'edit', data.path ); w.location = url; }); that.load_sessions(); }); $('#new-folder').click(function(e) { that.contents.new_untitled(that.notebook_path || '', {type: 'directory'}); that.load_sessions(); }); } }; NotebookList.prototype.handleFilesUpload = function(event, dropOrForm) { var that = this; var files; if(dropOrForm =='drop'){ files = event.originalEvent.dataTransfer.files; } else { files = event.originalEvent.target.files; } for (var i = 0; i < files.length; i++) { var f = files[i]; var name_and_ext = utils.splitext(f.name); var file_ext = name_and_ext[1]; var reader = new FileReader(); if (file_ext === '.ipynb') { reader.readAsText(f); } else { // read non-notebook files as binary reader.readAsArrayBuffer(f); } var item = that.new_item(0); item.addClass('new-file'); that.add_name_input(f.name, item, file_ext == '.ipynb' ? 'notebook' : 'file'); // Store the list item in the reader so we can use it later // to know which item it belongs to. $(reader).data('item', item); reader.onload = function (event) { var item = $(event.target).data('item'); that.add_file_data(event.target.result, item); that.add_upload_button(item); }; reader.onerror = function (event) { var item = $(event.target).data('item'); var name = item.data('name'); item.remove(); dialog.modal({ title : 'Failed to read file', body : "Failed to read file '" + name + "'", buttons : {'OK' : { 'class' : 'btn-primary' }} }); }; } // Replace the file input form wth a clone of itself. This is required to // reset the form. Otherwise, if you upload a file, delete it and try to // upload it again, the changed event won't fire. var form = $('input.fileinput'); form.replaceWith(form.clone(true)); return false; }; NotebookList.prototype.clear_list = function (remove_uploads) { /** * Clears the navigation tree. * * Parameters * remove_uploads: bool=False * Should upload prompts also be removed from the tree. */ if (remove_uploads) { this.element.children('.list_item').remove(); } else { this.element.children('.list_item:not(.new-file)').remove(); } }; NotebookList.prototype.load_sessions = function(){ this.session_list.load_sessions(); }; NotebookList.prototype.sessions_loaded = function(data){ this.sessions = data; this.load_list(); }; NotebookList.prototype.load_list = function () { var that = this; this.contents.list_contents(that.notebook_path).then( $.proxy(this.draw_notebook_list, this), function(error) { that.draw_notebook_list({content: []}, "Server error: " + error.message); } ); }; /** * Draw the list of notebooks * @method draw_notebook_list * @param {Array} list An array of dictionaries representing files or * directories. * @param {String} error_msg An error message */ var type_order = {'directory':0,'notebook':1,'file':2}; NotebookList.prototype.draw_notebook_list = function (list, error_msg) { list.content.sort(function(a, b) { if (type_order[a['type']] < type_order[b['type']]) { return -1; } if (type_order[a['type']] > type_order[b['type']]) { return 1; } if (a['name'] < b['name']) { return -1; } if (a['name'] > b['name']) { return 1; } return 0; }); var message = error_msg || 'Notebook list empty.'; var item = null; var model = null; var len = list.content.length; this.clear_list(); var n_uploads = this.element.children('.list_item').length; if (len === 0) { item = this.new_item(0); var span12 = item.children().first(); span12.empty(); span12.append($('
').text(message)); } var path = this.notebook_path; var offset = n_uploads; if (path !== '') { item = this.new_item(offset); model = { type: 'directory', name: '..', path: utils.url_path_split(path)[0], }; this.add_link(model, item); offset += 1; } for (var i=0; i