зеркало из https://github.com/nextcloud/news.git
added drag and drop
This commit is contained in:
Родитель
a248adbd25
Коммит
294333e41f
79
js/menu.js
79
js/menu.js
|
@ -57,6 +57,8 @@ var t = t || function(app, string){ return string; }; // mock translation for lo
|
|||
this._rendered = false;
|
||||
this._id = 0;
|
||||
this._$htmlElement = $('<ul>');
|
||||
this._$htmlElement.attr('data-id', this._id);
|
||||
this._bindDroppable(this._$htmlElement);
|
||||
this._selectedNode = undefined;
|
||||
this._showAll = false;
|
||||
}
|
||||
|
@ -86,17 +88,21 @@ var t = t || function(app, string){ return string; }; // mock translation for lo
|
|||
* from the datastructure
|
||||
* @param type the type of the node (MenuNodeType)
|
||||
* @param id the id of the node
|
||||
* @param removeDom if true, also remove the dom
|
||||
* @return the childelemnt or undefined if not found
|
||||
*/
|
||||
Menu.prototype.removeNode = function(type, id){
|
||||
Menu.prototype.removeNode = function(type, id, removeDom){
|
||||
var nodeIndex;
|
||||
removeDom = removeDom || false;
|
||||
for(var i=0; i<this._children.length; i++){
|
||||
var child = this._children[i];
|
||||
if(child._type === type && child._id === id){
|
||||
var nodeIndex = i;
|
||||
// if we have children, we need to remove their
|
||||
// html from the dom first then we need to
|
||||
if(removeDom){
|
||||
child._$htmlElement.remove();
|
||||
}
|
||||
this._children.splice(nodeIndex, 1);
|
||||
return child;
|
||||
} else {
|
||||
|
@ -251,10 +257,13 @@ var t = t || function(app, string){ return string; }; // mock translation for lo
|
|||
* Recursively traverse the menu and returns the
|
||||
* Node element matching the type and id
|
||||
* @param type the type of the node (MenuNodeType)
|
||||
* @param id the id of the node
|
||||
* @param id the id of the node, 0 returns the menu
|
||||
* @return the node element or undefined
|
||||
*/
|
||||
Menu.prototype._findNode = function(type, id){
|
||||
if(id === 0){
|
||||
return this;
|
||||
}
|
||||
for(var i=0; i<this._children.length; i++){
|
||||
var child = this._children[i];
|
||||
if(child._type === type && child._id === id){
|
||||
|
@ -269,6 +278,17 @@ var t = t || function(app, string){ return string; }; // mock translation for lo
|
|||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root element
|
||||
* @return the root element
|
||||
*/
|
||||
Menu.prototype._getRoot = function(){
|
||||
if(this._parent === false){
|
||||
return this;
|
||||
} else {
|
||||
return this._parent._getRoot();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a node selected and removes the class from the previous node
|
||||
|
@ -282,6 +302,37 @@ var t = t || function(app, string){ return string; }; // mock translation for lo
|
|||
this._selectedNode = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds a droppable on the element
|
||||
* @param $elem the element that should be set droppable
|
||||
*/
|
||||
Menu.prototype._bindDroppable = function($elem){
|
||||
var self = this;
|
||||
var root = this._getRoot();
|
||||
$elem.droppable({
|
||||
accept: '.feed',
|
||||
hoverClass: 'dnd_over',
|
||||
greedy: true,
|
||||
drop: function(event, ui){
|
||||
var $dropped = $(this);
|
||||
var $dragged = $(ui.draggable);
|
||||
|
||||
// fix object structure
|
||||
var feedId = parseInt($dragged.data('id'));
|
||||
var feed = root.removeNode(News.MenuNodeType.Feed, feedId, false);
|
||||
|
||||
var folderId = parseInt($dropped.data('id'));
|
||||
var folder = root._findNode(News.MenuNodeType.Folder, folderId);
|
||||
|
||||
folder._addChildNode(feed);
|
||||
|
||||
$dropped.append($dragged[0]);
|
||||
console.log('Moved elem with id ' + feedId + ' to folder with id ' + folderId);
|
||||
// TODO: notify server
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/*##########################################################################
|
||||
* MenuNode
|
||||
|
@ -366,6 +417,14 @@ var t = t || function(app, string){ return string; }; // mock translation for lo
|
|||
$elem.append($title);
|
||||
$elem.append($deleteButton);
|
||||
$elem.addClass('feed');
|
||||
// bind dragging
|
||||
$elem.draggable({
|
||||
revert: true,
|
||||
stack: '> li',
|
||||
zIndex: 1000,
|
||||
axis: 'y',
|
||||
});
|
||||
$elem.data('id', this._id);
|
||||
break;
|
||||
|
||||
case MenuNodeType.Folder:
|
||||
|
@ -386,14 +445,14 @@ var t = t || function(app, string){ return string; }; // mock translation for lo
|
|||
}
|
||||
|
||||
// recursively append children
|
||||
var $subNode = $('<ul>');
|
||||
var $subList = $('<ul>');
|
||||
for(var i=0; i<this._children.length; i++){
|
||||
var node = this._children[i];
|
||||
$subNode.append(node.render());
|
||||
}
|
||||
if(this._children.length > 0){
|
||||
$elem.append($subNode);
|
||||
$subList.append(node.render());
|
||||
}
|
||||
this._bindDroppable($subList);
|
||||
$subList.attr('data-id', this._id);
|
||||
$elem.append($subList);
|
||||
|
||||
return $elem;
|
||||
}
|
||||
|
@ -431,9 +490,9 @@ var t = t || function(app, string){ return string; }; // mock translation for lo
|
|||
*/
|
||||
MenuNode.prototype._expandClick = function(){
|
||||
this._$htmlElement.children('.collapsable').toggleClass('triggered');
|
||||
var $sublist = this._$htmlElement.children('ul');
|
||||
if($sublist.length > 0){
|
||||
$sublist.toggle();
|
||||
var $subList = this._$htmlElement.children('ul');
|
||||
if($subList.length > 0){
|
||||
$subList.toggle();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -158,7 +158,7 @@ test('Adding a new node should create the correct dom', function(){
|
|||
test('Removing a feed node should remove the correct dom', function(){
|
||||
equal(NewsTests.$popMenuDomElem.children().length, 3);
|
||||
|
||||
var child = NewsTests.popMenu.removeNode(News.MenuNodeType.Feed, 2);
|
||||
var child = NewsTests.popMenu.removeNode(News.MenuNodeType.Feed, 2, true);
|
||||
ok(child !== undefined);
|
||||
|
||||
// top length should stay the same
|
||||
|
@ -170,7 +170,7 @@ test('Removing a feed node should remove the correct dom', function(){
|
|||
});
|
||||
|
||||
test('Removing a non existent node should not change anything', function(){
|
||||
var child = NewsTests.popMenu.removeNode(News.MenuNodeType.Feed, 12);
|
||||
var child = NewsTests.popMenu.removeNode(News.MenuNodeType.Feed, 12, true);
|
||||
ok(child === undefined);
|
||||
|
||||
// top length should stay the same
|
||||
|
@ -181,7 +181,7 @@ test('Removing a non existent node should not change anything', function(){
|
|||
});
|
||||
|
||||
test('Removing a parent node should remove its children', function(){
|
||||
var child = NewsTests.popMenu.removeNode(News.MenuNodeType.Folder, 1);
|
||||
var child = NewsTests.popMenu.removeNode(News.MenuNodeType.Folder, 1, true);
|
||||
ok(child !== undefined);
|
||||
equal(NewsTests.$popMenuDomElem.children().length, 2);
|
||||
equal(NewsTests.popMenu._children.length, 2);
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -5,6 +5,7 @@
|
|||
<title>NewsApp Tests</title>
|
||||
<link rel="stylesheet" href="qunit/qunit-1.9.0.css">
|
||||
<script src="qunit/jquery-1.8.0.min.js"></script>
|
||||
<script src="qunit/jquery-ui-1.8.23.custom.min.js"></script>
|
||||
<script src="qunit/qunit-1.9.0.js"></script>
|
||||
|
||||
<script src="../../js/menu.js"></script>
|
||||
|
|
Загрузка…
Ссылка в новой задаче