diff --git a/www/drive/main.js b/www/drive/main.js index 74b36328d..9dc15bcd2 100644 --- a/www/drive/main.js +++ b/www/drive/main.js @@ -228,7 +228,6 @@ define([ if (AppConfig.enableTemplates) { displayedCategories.push(TEMPLATE); } if (isWorkgroup()) { displayedCategories = [ROOT, TRASH, SEARCH]; } - var lastSelectTime; var selectedElement; if (!APP.readOnly) { @@ -262,14 +261,20 @@ define([ // Selection - var removeSelected = function () { + var sel = {}; + + var removeSelected = function (keepObj) { $iframe.find('.selected').removeClass("selected"); var $container = $driveToolbar.find('#contextButtonsContainer'); if (!$container.length) { return; } $container.html(''); + if (!keepObj) { + delete sel.startSelected; + delete sel.endSelected; + delete sel.oldSelection; + } }; - var sel = {}; sel.refresh = 200; sel.$selectBox = $('
', {'class': 'selectBox'}).appendTo($content); var checkSelected = function () { @@ -366,6 +371,81 @@ define([ $content.find('.selectedTmp').removeClass('selectedTmp').addClass('selected'); }); + $(ifrw).keydown(function (e) { + var $elements = $content.find('.element:not(.header)'); + + var ev = {}; + if (e.ctrlKey) { ev.ctrlKey = true; } + if (e.shiftKey) { ev.shiftKey = true; } + var click = function (el) { + onElementClick(ev, $(el)); + }; + + // Enter + if (e.which === 13) { + var $selection = $content.find('.file-element.selected'); + $selection.each(function (idx, el) { + $(el).dblclick(); + }); + return; + } + + // [Left, Up, Right, Down] + if ([37, 38, 39, 40].indexOf(e.which) === -1) { return; } + + var $selection = $content.find('.element.selected'); + if ($selection.length === 0) { return void click($elements.first()[0]); } + + var lastIndex = typeof sel.endSelected === "number" ? sel.endSelected : + typeof sel.startSelected === "number" ? sel.startSelected : + $elements.index($selection.last()[0]); + var length = $elements.length; + if (length === 0) { return; } + // List mode + if (getViewMode() === "list") { + if (e.which === 40) { click($elements.get(Math.min(lastIndex+1, length))); } + if (e.which === 38) { click($elements.get(Math.max(lastIndex-1, 0))); } + return; + } + + // Icon mode + // Get the vertical and horizontal position of lastIndex + // Filter all the elements to get those in the same line/column + var pos = $($elements.get(0)).position(); + var $line = $elements.filter(function (idx, el) { + return $(el).position().top === pos.top; + }); + var cols = $line.length + var lines = Math.ceil(length/cols); + + var lastPos = { + l : Math.floor(lastIndex/cols), + c : lastIndex - Math.floor(lastIndex/cols)*cols + }; + + if (e.which === 37) { + if (lastPos.c === 0) { return; } + click($elements.get(Math.max(lastIndex-1, 0))); + return; + } + if (e.which === 38) { + if (lastPos.l === 0) { return; } + click($elements.get(Math.max(lastIndex-cols, 0))); + return; + } + if (e.which === 39) { + if (lastPos.c === cols-1) { return; } + click($elements.get(Math.min(lastIndex+1, length-1))); + return; + } + if (e.which === 40) { + if (lastPos.l === lines-1) { return; } + click($elements.get(Math.min(lastIndex+cols, length-1))); + return; + } + + }); + var removeInput = function (cancel) { if (!cancel && $iframe.find('.element-row > input').length === 1) { @@ -622,7 +702,7 @@ define([ }; // Add the "selected" class to the "li" corresponding to the clicked element - var onElementClick = function (e, $element, path) { + var onElementClick = function (e, $element) { // If "Ctrl" is pressed, do not remove the current selection removeInput(); $element = findDataHolder($element); @@ -630,19 +710,46 @@ define([ if (e) { module.hideMenu(); } // Remove the selection if we don't hold ctrl key or if we are right-clicking if (!e || !e.ctrlKey) { - removeSelected(); + removeSelected(e.shiftKey); } if (!$element.length) { log(Messages.fm_selectError); return; } // Add the selected class to the clicked / right-clicked element - // Remove the class if it already has it (cannot happen if the user is not holding ctrl key) - if (!$element.hasClass("selected")) { - $element.addClass("selected"); - lastSelectTime = now(); + // Remove the class if it already has it + // If ctrlKey, add to the selection + // If shiftKey, select a range of elements + var $elements = $content.find('.element:not(.header)'); + var $selection = $elements.filter('.selected'); + if (typeof sel.startSelected !== "number" || !e || (e.ctrlKey && !e.shiftKey)) { + sel.startSelected = $elements.index($element[0]); + sel.oldSelection = []; + $selection.each(function (idx, el) { + sel.oldSelection.push(el); + }); + delete sel.endSelected; + } + if (e.shiftKey) { + var end = $elements.index($element[0]); + sel.endSelected = end; + var $el; + removeSelected(true); + sel.oldSelection.forEach(function (el) { + if (!$(el).hasClass("selected")) { $(el).addClass("selected"); } + }); + for (var i = Math.min(sel.startSelected, sel.endSelected); + i <= Math.max(sel.startSelected, sel.endSelected); + i++) { + $el = $($elements.get(i)); + if (!$el.hasClass("selected")) { $el.addClass("selected"); } + } } else { - $element.removeClass("selected"); + if (!$element.hasClass("selected")) { + $element.addClass("selected"); + } else { + $element.removeClass("selected"); + } } updateContextButton(); }; @@ -2342,71 +2449,6 @@ define([ APP.resizeTree = undefined; }); - $(ifrw).keydown(function (e) { - // Enter - if (e.which === 13) { - var $selection = $content.find('.file-element.selected'); - $selection.each(function (idx, el) { - $(el).dblclick(); - }); - return; - } - // [Left, Up, Right, Down] - if ([37, 38, 39, 40].indexOf(e.which) === -1) { return; } - var $selection = $content.find('.element.selected'); - - if ($selection.length === 0) { return void $content.find('.element').first().click(); } - - var $elements = $content.find('.element:not(.header)'); - var $last = $selection.last(); - var lastIndex = $elements.index($last[0]); - var length = $elements.length; - if (length === 0) { return; } - // List mode - if (getViewMode() === "list") { - if (e.which === 40) { $elements.get(Math.min(lastIndex+1, length)).click(); } - if (e.which === 38) { $elements.get(Math.max(lastIndex-1, 0)).click(); } - return; - } - - // Icon mode - // Get the vertical and horizontal position of $last - // Filter all the elements to get those in the same line/column - var pos = $($elements.get(0)).position(); - var $line = $elements.filter(function (idx, el) { - return $(el).position().top === pos.top; - }); - var cols = $line.length - var lines = Math.ceil(length/cols); - - var lastPos = { - l : Math.floor(lastIndex/cols), - c : lastIndex - Math.floor(lastIndex/cols)*cols - }; - - if (e.which === 37) { - if (lastPos.c === 0) { return; } - $elements.get(Math.max(lastIndex-1, 0)).click(); - return; - } - if (e.which === 38) { - if (lastPos.l === 0) { return; } - $elements.get(Math.max(lastIndex-cols, 0)).click(); - return; - } - if (e.which === 39) { - if (lastPos.c === cols-1) { return; } - $elements.get(Math.min(lastIndex+1, length-1)).click(); - return; - } - if (e.which === 40) { - if (lastPos.l === lines-1) { return; } - $elements.get(Math.min(lastIndex+cols, length-1)).click(); - return; - } - - }); - history.onEnterHistory = function (obj) { var files = obj.drive; filesOp = FO.init(files, config);